Почему так сложно установить стиль из кода в Android - PullRequest
35 голосов
/ 03 декабря 2011

Если вы хотите установить стиль кнопки, которую вы создаете из кода, вы должны сделать что-то вроде этого:

Button  btn  = new Button (mActivity, null, R.attr.someattribute);

в attrs.xml, вы установите ссылку

<attr name="someStyleRef" format="reference"/>

В styles.xml вы определяете тему

<resources>
  <style name="Theme.SomeTheme" parent="android:style/Theme.Black">
     <item name="someStyleRef">@style/someStyle</item>
  </style>
</resources>

, которая указывается в файле styles.xml следующим образом:

<style name="someStyle">
        <item name="android:layout_width">2px</item>
        <item name="android:layout_height">fill_parent</item>
        <item name="android:background">@drawable/actionbar_compat_separator</item>
 </style>

Это работает, и в соответствииНасколько я понимаю, способ установить стиль в представлении из кода в Android.Это кажется слишком сложным.Третий конструктор кнопки Argument мог легко принять идентификатор стиля R.style.XXX

Может кто-нибудь объяснить, зачем нужна эта дополнительная сложность?

1 Ответ

65 голосов
/ 03 декабря 2011

Это связано с поддерживаемыми шаблонами в 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"
        [...] />
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...