Подтвердить что ты не робот

Как я могу динамически создавать список всех компонентов 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), для которых я хотел бы генерировать их динамически

Предпочтительно без использования какой-либо другой библиотеки

4b9b3361

Ответ 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;
    }
}