Ответ 1
Это связано с поощрением шаблонов в Android вокруг использования Views. Это не предполагаемый подход к тому, как он выглядит, как вы пытаетесь сделать. Сначала я объясню, для чего этот механизм, а затем предложим подход для вашего приложения.
Третий аргумент конструктора View, который принимает ресурс attr, обычно используется при реализации подклассов вида и, как вы показали, позволяет указать атрибут темы для использования в качестве ссылки на стиль представления по умолчанию. Если у вас была специальная кнопка AwesomeButton, вы можете реализовать ее конструкторы следующим образом:
public class AwesomeButton extends Button {
public AwesomeButton(Context context) {
this(context, null);
}
public AwesomeButton(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.awesomeButtonStyle);
}
public AwesomeButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr) {
final TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.AwesomeButton, defStyleAttr, 0);
// Read AwesomeButton-specific style attributes from a
a.recycle();
}
// More code
}
Когда Android LayoutInflater
раздувает представления, он использует конструктор с двумя аргументами с аргументами (Context, AttributeSet)
. Константа R.attr передается в версию с тремя аргументами, а затем вниз до конструктора Button
3-argument в вызове super
. Это означает, что Button
будет читать информацию по умолчанию для стилей для вещей, которые она инкапсулирует из стиля AwesomeButton
по умолчанию, как указано в вашей теме. Некоторые представления в Android отличаются от их суперкласса только в стиле по умолчанию, который они используют. (Button
на самом деле является одним из них.)
Вы указываете android:layout_width
и android:layout_height
в своем стиле, но это может быть проблематично. LayoutParams
(любой атрибут, начинающийся с layout_
), зависит от родительского представления, а не от вида, в котором они отображаются. Вот почему вы всегда передаете предполагаемое родительское представление в качестве второго параметра в LayoutInflater#inflate
- он сообщает водителю, какой класс должен отвечать за интерпретацию LayoutParams
. Если вы пропустите это, вы часто обнаружите, что ваш LayoutParams
не ведет себя так, как вы ожидаете, и часто игнорируется напрямую. По соглашению мы не ставим LayoutParams
в стили, хотя в некоторых особых случаях это работает.
Похоже, вы пытаетесь использовать стиль как своего рода шаблон. Есть ли причина не использовать ресурс компоновки для этого и указать стиль там?
final LayoutInflater inflater = LayoutInflater.from(mActivity);
Button btn = (Button) inflater.inflate(R.layout.styled_button, parentView, false);
Рез/макет/styled_button.xml:
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/my_button_background"
[...] />