Изменить значения 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
может иметь несколько атрибутов, и вы хотите изменить некоторые из этих атрибутов на основе некоторого условия и передать это в конструктор.
Несколько лучших практик при разработке собственного представления:
- Если у вас есть пользовательские атрибуты, убедитесь, что вы выставляете их через сеттеры и геттеры. В вашем методе setter, вызовите
invalidate();
- Не пытайтесь изменять какие-либо атрибуты внутри
onDraw()
или жеonMeasure()
методы. - Старайтесь изо всех сил избегать написания пользовательских конструкторов для вашего пользовательского представления.
Таким образом, идеальный способ решения вашей проблемы - создать экземпляр 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
}
}