Подтвердить что ты не робот

Почему так сложно установить стиль из кода на Android?

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

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>

Это lates в 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. Это кажется слишком сложным. Кнопка третьего конструктора Аргумент может легко принять идентификатор стиля R.style.XXX

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

4b9b3361

Ответ 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"
        [...] />