Как я могу динамически создавать список всех компонентов Android ui программно? например TextView, ImageView и т.д.
Я создаю программу и в которой мне нужно создать список всех различных компонентов Android, а не вычислять и печатать Список вручную. Я хотел бы выяснить программно, могу ли я сделать это для добавления в String Arrays, как показано ниже?
Components[] = {"TextView", "ImageView", "RelativeLayout", "LinearLayout", "Random", "DecimalFormat ...
Аналогично, я хотел бы программно создать Список всех разных типов данных, например. Int, String, ArrayList и т.д., Которые будут добавлены в массивы String, как показано ниже.
DataTypes[] = {"Int", "String", "Object", "Double", "Char", "Boolean ...
То, что я смог сделать до сих пор, выше. Пока я физически печатал их, как описано выше.
Как я могу это сделать? Благодаря
Разъяснение
По типам данных: Я имею в виду типы переменных, объявленные для хранения данных, например, Int, String, object, boolean, double, array, arraylists и т.д.
По компонентам: Я имею в виду любой визуальный компонент, который можно добавить в Android xml, например. ImageView, TextView, LinearLayout, RelativeLayout и т.д.
Да, я знаю, что число этих компонентов может быть бесконечным (определяется используемыми API), для которых я хотел бы генерировать их динамически
Предпочтительно без использования какой-либо другой библиотеки
Ответы
Ответ 1
Вам не нужно использовать сторонние библиотеки, так как Java
имеет размышления.
Этот метод сделает все для вас и сделает UI
без проблем:
for(String s : arrayWithNames){
View view = createViewInstance(0, s);
if(view instance of View){
//handle if it is view
}else{
//this is viewgroup
}
}
И createViewInstance()
:
private View createViewInstance(String name){
View view = null;
try{
if(name.equalsIgnoreCase("View"){ // if it is view
Class viewClass = Class.forName("android.view." + name);
view = (View) viewClass.getConstructor(Context.class).newInstance(new Object[]{ctx});
}else{ // if it is widget: ImageView, RelativeLayout etc
Class viewClass = Class.forName("android.widget." + name);
view = (View) viewClass.getConstructor(Context.class).newInstance(new Object[]{ctx});
}
} catch (ClassNotFoundException | InvocationTargetException | NoSuchMethodException
| InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
return view;
}
Что это. У вас есть все, чтобы справиться с любым типом View
.
Я проверил код выше и использовал его в проекте. Он отлично работает.
Точно такая же ситуация с другими Object
s. Вы не можете создать int
с отражением, но вы можете создать Integer
, так что в основном то же самое.
Одной из проблем с этим является гораздо больше типов, чем просто View
и ViewGroup
. Но это также зависит от того, сколько видов Object
вы хотите создать... В данном примере скажем, что я сделаю char
, String
, int
, Object
, а затем вы сможете легко его расширить.
for(String s : arrayWithNames){
if(s.equalsIgnoreCase("int")){
Integer integer = (Integer)createVarInstance(s); //ready to use. Integer, not int!
}else if(s.equalsIgnoreCase("String"){
String string = (String)createVarInstance(s);
}else if(s.equalsIgnoreCase("char"){
Character character = (Character)createVarInstance(s); //Character, not char!
}else if(s.equalsIgnoreCase("Object"){
Object object = (Object)createVarInstance(s);
}
}
Поскольку все эти типы данных находятся в одном пакете, нам становится намного легче. Метод createVarInstance()
:
private Object createVarInstance(String name){
Object obj = null;
try{
Class varClass = Class.forName("java.lang." + name);
object = (Object) varClass.newInstance();
} catch (ClassNotFoundException | InvocationTargetException | NoSuchMethodException
| InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
return object;
}
Если потребуется, можно сделать один метод для разных пакетов.
Если в будущем вы захотите создать больше и разных типов переменных, которые находятся в разных пакетах, вам придется проверять имена или выполнять аналогичные операции, как в примере с View
s.
Ответ 2
Вы можете перечислить компоненты интерфейса всех классов в пакет android.view
или android.view.View
, используя Библиотека отражения:
Reflections reflections = new Reflections("android.view");
//Reflections reflections = new Reflections("android.view.View");
Set<Class<? extends Object>> allClasses = reflections.getSubTypesOf(Object.class);
Чтобы создать список всех типов данных, вы могли бы сделать то же самое выше, используя класс Object, но сначала я лично задал себе вопрос, что делать.
Ответ 3
Reflections - это потрясающая библиотека для Java. Я не уверен, работает ли он на Android тоже. Кто-то открыл проблему, он вскоре закрылся без объяснений.
Если вы можете заставить его работать в Android, вы можете использовать этот код для получения всех компонентов:
Reflections reflections = new Reflection("android.widget") //specifiy the package (TextView etc. are in here)
Set<Class<? extends View>> components = reflections.getSubTypesOf(View.class);
Если вы хотите, вы можете повторить эту процедуру с помощью пакета android.view
, где расположены некоторые другие классы, такие как ViewGroup.
Кроме того, если вы действительно хотите String Array, получите имена классов:
List<String> componentNames = new ArrayList<String>();
for (Class<? extends View> c: components) {
componentNames.add(c.getName());
}
String[] allComponents = componentNames.toArray();
Если вышеуказанное решение не работает для вас, попробуйте получить классы с официального сайта. Классы перечислены в пакетах android.view и android.widget. Просто скопируйте соответствующие имена и вставьте их в исходный код. Это не было бы динамичным, но оно работает.
Ответ 4
как использовать Factory для создания Компонента следующим образом:
public class ComponentFactory {
private HashMap<String, View> mMap;
public ComponentFactory(Context context) {
mMap = new HashMap<String, View>();
mMap.put("TextView", new TextView(context));
...
...
}
public View getComponent(String name) {
View v = mMap.get(name);
if (v == null) {
throw new IlllegalArgumentException();
}
return v;
}
}