Изменить значения AttributeSet в Android

У меня есть пользовательский вид, который будет принимать набор атрибутов (значение XML) в качестве значения конструктора

public CustomView(Context context)  // No Attributes in this one.
{
    super(context);
    this(context, null, 0);
}

public CustomView(Context context, AttributeSet attrs) {
    super(context, attrs);
    this(context, attrs, 0)
}

public CustomView(Context context, AttributeSet attrs, int default_style) {
    super(context, attrs, default_style);
    readAttrs(context, attrs, defStyle);
    init();
}

В классе Fragment я устанавливаю вид как

CustomView customView = (CustomView) view.findViewById(R.id.customView); 

где пользовательский вид содержит различные значения, такие как высота, ширина, отступы и т. д.

Я хочу изменить эти значения в зависимости от требуемого условия и вернуть его к пользовательскому виду. Я поместил код настройки ширины высоты в метод onDraw и вызвал представление invalidte. Но приведенный выше метод будет устанавливаться каждый раз, если я вызову метод invalidate в классе CustomView. Как преодолеть это так, чтобы я мог передать измененное значение набора атрибутов только в конструкторе.?

Изменить: мне нужно изменить значения представления (инициализировать с новыми значениями), который устанавливается во время конструктора атрибута, чтобы я получил обновленное представление с новыми значениями. Переопределить @OnDraw или "Invalidate" не очень хорошая функция для меня, где внутри недействительным я написал методы, которые будут выполняться в каждом втором интервале.

3 ответа

Я вижу, что ваш CustomView может иметь несколько атрибутов, и вы хотите изменить некоторые из этих атрибутов на основе некоторого условия и передать это в конструктор.

Несколько лучших практик при разработке собственного представления:

  1. Если у вас есть пользовательские атрибуты, убедитесь, что вы выставляете их через сеттеры и геттеры. В вашем методе setter, вызовите invalidate();
  2. Не пытайтесь изменять какие-либо атрибуты внутри onDraw() или же onMeasure() методы.
  3. Старайтесь изо всех сил избегать написания пользовательских конструкторов для вашего пользовательского представления.

Таким образом, идеальный способ решения вашей проблемы - создать экземпляр CustomView и затем изменить атрибуты, либо внешне (в вашей деятельности или фрагменте), либо иметь метод внутри CustomView.java а затем вызвать его извне. Выполнение этого все равно даст вам тот же результат, который вы ищете.

Вероятно, это не то решение, на которое вы надеялись, но поместите FrameLayout в ваш XML вместо CustomView, а затем создайте свой CustomView программно с FrameLayout в качестве его родителя.

Допустим, вы объявили свои пользовательские атрибуты таким образом для представления с именем StarsView

<declare-styleable name="StarsView">
    <attr name="stars" format="integer" />
    <attr name="score" format="float" />
</declare-styleable>

И вы хотите прочитать атрибуты из чего-то вроде этого

<my.package..StarsView
    app:stars="5"
    app:score="4.6"

Вы делаете это в конструкторе

public StarsView(Context context, AttributeSet attrs) {
    super(context, attrs);
    if(attrs != null) {
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.StarsView, defStyleAttr, 0);
        stars = Tools.MathEx.clamp(1, 10, a.getInt(R.styleable.StarsView_stars, 5));
        score =  (int)Math.floor(a.getFloat(R.styleable.StarsView_score, stars) * 2f);
        a.recycle(); // its important to call recycle after we are done
    }
}
Другие вопросы по тегам