Это связано с поддерживаемыми шаблонами в Android вокруг использования Views. Это не тот подход, который, как вам кажется, вы пытаетесь сделать. Сначала я объясню, для чего предназначен этот механизм, а затем предложу подход для вашего приложения.
Третий аргумент для конструкторов View, который использует ресурс attr, обычно используется при реализации подклассов View и, как вы показали, позволяет вам указать атрибут темы, который будет использоваться в качестве ссылки на стиль по умолчанию для View. Если у вас есть кнопка особого вида, называемая 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
с тремя аргументами в вызове 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"
[...] />