Дополнение к наиболее проголосовавшему ответу.
obtainStyledAttributes ()
Я хочу добавить несколько слов об использовании receiveStyledAttributes (), когда мы создаем пользовательское представление, используя атрибуты android: xxx prdefined. Особенно, когда мы используем TextAppearance.
Как было упомянуто в «2. Создание конструкторов», пользовательское представление получает AttributeSet при его создании. Основное использование мы видим в исходном коде TextView (API 16).
final Resources.Theme theme = context.getTheme();
// TextAppearance is inspected first, but let observe it later
TypedArray a = theme.obtainStyledAttributes(
attrs, com.android.internal.R.styleable.TextView, defStyle, 0);
int n = a.getIndexCount();
for (int i = 0; i < n; i++)
{
int attr = a.getIndex(i);
// huge switch with pattern value=a.getXXX(attr) <=> a.getXXX(a.getIndex(i))
}
a.recycle();
Что мы можем увидеть здесь?
obtainStyledAttributes(AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes)
Набор атрибутов обрабатывается по темам в соответствии с документацией. Значения атрибутов составляются шаг за шагом. Сначала атрибуты заполняются из темы, затем значения заменяются значениями из стиля, и, наконец, точные значения из XML для экземпляра специального представления заменяют другие.
Массив запрошенных атрибутов - com.android.internal.R.styleable.TextView
Это обычный массив констант. Если мы запрашиваем стандартные атрибуты, мы можем создать этот массив вручную.
Что не упомянуто в документации - порядок следования элементов TypedArray.
Когда в attrs.xml объявляется пользовательское представление, генерируются специальные константы для индексов атрибутов. И мы можем извлечь значения следующим образом: a.getString(R.styleable.MyCustomView_android_text)
. Но для руководства int[]
нет никаких констант. Я полагаю, что getXXXValue (arrayIndex) будет работать нормально.
И другой вопрос: «Как мы можем заменить внутренние константы и запросить стандартные атрибуты?» Мы можем использовать значения android.R.attr. *.
Поэтому, если мы хотим использовать стандартный атрибут TextAppearance в пользовательском представлении и читать его значения в конструкторе, мы можем изменить код из TextView следующим образом:
ColorStateList textColorApp = null;
int textSize = 15;
int typefaceIndex = -1;
int styleIndex = -1;
Resources.Theme theme = context.getTheme();
TypedArray a = theme.obtainStyledAttributes(attrs, R.styleable.CustomLabel, defStyle, 0);
TypedArray appearance = null;
int apResourceId = a.getResourceId(R.styleable.CustomLabel_android_textAppearance, -1);
a.recycle();
if (apResourceId != -1)
{
appearance =
theme.obtainStyledAttributes(apResourceId, new int[] { android.R.attr.textColor, android.R.attr.textSize,
android.R.attr.typeface, android.R.attr.textStyle });
}
if (appearance != null)
{
textColorApp = appearance.getColorStateList(0);
textSize = appearance.getDimensionPixelSize(1, textSize);
typefaceIndex = appearance.getInt(2, -1);
styleIndex = appearance.getInt(3, -1);
appearance.recycle();
}
Где определяется CustomLabel:
<declare-styleable name="CustomLabel">
<!-- Label text. -->
<attr name="android:text" />
<!-- Label text color. -->
<attr name="android:textColor" />
<!-- Combined text appearance properties. -->
<attr name="android:textAppearance" />
</declare-styleable>
Может быть, я как-то ошибаюсь, но документация Android для receiveStyledAttributes () очень плохая.
Расширение стандартного компонента пользовательского интерфейса
В то же время мы можем просто расширить стандартный компонент пользовательского интерфейса, используя все его объявленные атрибуты.
Этот подход не очень хорош, потому что TextView, например, объявляет много свойств. И это будет невозможно
реализовать полную функциональность в переопределенных onMeasure () и onDraw ().
Но мы можем пожертвовать теоретическим широким использованием пользовательского компонента. Скажите «Я точно знаю, какие функции я буду использовать», и
не делись ни с кем кодом.
Тогда мы можем реализовать конструктор CustomComponent(Context, AttributeSet, defStyle)
.
После вызова super(...)
все атрибуты будут проанализированы и доступны через методы получения.