Как наполнить представление значениями настраиваемых атрибутов?

Как мне программно установить значения в моем View, которые он может использовать в onCreate()? Атрибуты могут быть установлены только в XML, а значения элементов могут быть установлены только после того, как View будет раздут (и onCreate() уже вызван).

Нужно ли мне вызывать конструктор View и устанавливать значения элементов перед его раздуванием? Или есть лучший способ?


person Barry Fruitman    schedule 18.01.2018    source источник
comment
Не совсем понятно, чего вы пытаетесь достичь здесь или каковы именно ограничения. Почему вы не можете инициализировать View как обычно? То есть, почему вы не можете просто раздуть его или создать его экземпляр, а затем сразу же установить его свойства по мере необходимости?   -  person Mike M.    schedule 18.01.2018
comment
@МайкМ. Я пытаюсь раздуть представление из XML, а затем программно установить некоторые атрибуты до вызова onCreate(). Это возможно?   -  person Barry Fruitman    schedule 19.01.2018
comment
Не совсем. Ну, во всяком случае, не особенно элегантно, насколько я могу судить. Почему атрибуты должны быть установлены до onCreate()? Это в основном то, где вы должны настроить пользовательский интерфейс до его отображения. View на самом деле не измеряются и не раскладываются до тех пор, пока не закончится onCreate().   -  person Mike M.    schedule 19.01.2018


Ответы (1)


Если вы расширяете представление с помощью Context.getLayoutInflater().createView(), вы можете программно передавать настраиваемые атрибуты в это представление, используя последний параметр

ИЗМЕНИТЬ

Чтобы использовать атрибуты как из xml, так и программно, вам придется реализовать собственный LayoutInflater. Однако, поскольку

Вы можете увидеть пример пользовательского макета в библиотеке Android Rec Library.

Вы можете увидеть пример пользовательского AttributeSet в этом ответе SO.

Пользовательский набор атрибутов

Если я объединим все эти ответы, вы получите то, что хотите, но для этого потребуется некоторый шаблонный код, поскольку AttributeSet не очень подходит для добавления параметров на лету. Таким образом, вам придется реализовать AttributeSet (который является интерфейсом), который получает исходный AttributeSet в конструкторе, обертывает всю его функциональность и возвращает правильные значения для параметров, которые вы хотите добавить программно.

Тогда вы сможете сделать что-то вроде:

private static class MyLayoutInflater implements LayoutInflater.Factory {

        private LayoutInflater other;

        MyLayoutInflater(LayoutInflater other) {
            this.other = other;
        }

        @Override
        public View onCreateView(String name, Context context, AttributeSet attrs) {
            if (name.equals("MyView")) {
                attrs = MyAttributeSet(attrs);
            }
            try {
                return other.createView(name, "", attrs);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();

            }
        }
    }

    private static class MyAttributeSet implements AttributeSet {

        private AttributeSet other;

        MyAttributeSet(AttributeSet other) {
            this.other = other;
        }

        < More implementations ...>
    }

    @Override
    protected void onCreate(Bundle savedInstanceState){
        getLayoutInflater().setFactory(new MyLayoutInflater(getLayoutInflater());
        getLayoutInflater().inflate(...)
    }

Это может сработать, но, вероятно, есть лучший способ добиться того, чего вы хотите.

Добавить пользовательские параметры

Вы можете реализовать собственный layoutinflater, который установит некоторые параметры перед возвратом представления, поэтому они будут добавлены до того, как onCreate будет вызвано представление. Итак, это будет что-то вроде:

@Override
protected void onCreate(Bundle savedInstanceState){
    getLayoutInflater().setFactory(new LayoutInflater.Factory() {
        public View onCreateView(String name, Context context, AttributeSet attrs) {
            if (name.equals("MyView")) {
                View myView = myView(context, attrs); // To get properties from attrs
                myView.setCustomParams(SomeCustomParam);
                return myView;
            } else {
                return null;
            }
        }
    });
    getLayoutInflater().inflate(...)
}
person ElyashivLavi    schedule 18.01.2018
comment
Спасибо, но мне нужно раздуть представление из XML, которое содержит дополнительные атрибуты. - person Barry Fruitman; 19.01.2018
comment
Итак, для этого вам понадобится пользовательский файл LayoutInflater. я отредактирую свой ответ - person ElyashivLavi; 19.01.2018