Как определить тему (стиль) элемента для пользовательского виджета
Я написал пользовательский виджет для элемента управления, который мы широко используем во всем нашем приложении. Класс widget является производным от ImageButton
и расширяет его несколькими простыми способами. Я определил стиль, который я могу применить к виджету по мере его использования, но я бы предпочел настроить это через тему. В R.styleable
Я вижу атрибуты стиля виджета, как imageButtonStyle
и textViewStyle
. Есть ли способ создать что-то подобное для пользовательского виджета, который я написал?
2 ответа:
Да, есть один способ:
Предположим, у вас есть объявление атрибутов для вашего виджета (в
attrs.xml
):<declare-styleable name="CustomImageButton"> <attr name="customAttr" format="string"/> </declare-styleable>
объявите атрибут, который будет использоваться для ссылки на стиль (в
attrs.xml
):<declare-styleable name="CustomTheme"> <attr name="customImageButtonStyle" format="reference"/> </declare-styleable>
объявить набор значений атрибутов по умолчанию для виджета (в
styles.xml
):<style name="Widget.ImageButton.Custom" parent="android:style/Widget.ImageButton"> <item name="customAttr">some value</item> </style>
объявить пользовательскую тему (в
themes.xml
):<style name="Theme.Custom" parent="@android:style/Theme"> <item name="customImageButtonStyle">@style/Widget.ImageButton.Custom</item> </style>
используйте этот атрибут в качестве третьего аргумента в конструкторе виджета (в
CustomImageButton.java
):public class CustomImageButton extends ImageButton { private String customAttr; public CustomImageButton( Context context ) { this( context, null ); } public CustomImageButton( Context context, AttributeSet attrs ) { this( context, attrs, R.attr.customImageButtonStyle ); } public CustomImageButton( Context context, AttributeSet attrs, int defStyle ) { super( context, attrs, defStyle ); final TypedArray array = context.obtainStyledAttributes( attrs, R.styleable.CustomImageButton, defStyle, R.style.Widget_ImageButton_Custom ); // see below this.customAttr = array.getString( R.styleable.CustomImageButton_customAttr, "" ); array.recycle(); } }
теперь вы должны подать заявку
Theme.Custom
для всех видов деятельности, которые используютCustomImageButton
(в AndroidManifest.xml):<activity android:name=".MyActivity" android:theme="@style/Theme.Custom"/>
вот и все. Сейчас
CustomImageButton
пытается загрузить значения по умолчанию изcustomImageButtonStyle
атрибут текущей темы. Если такой атрибут не найден в теме или значение атрибута@null
тогда последний аргумент кobtainStyledAttributes
будут использованы:Widget.ImageButton.Custom
в этом случае.вы можете изменить имена всех инстанций и всех файлов (кроме
AndroidManifest.xml
) но было бы лучше использовать соглашение об именах Android.
еще один аспект в дополнение к превосходному ответу Майкла-это переопределение пользовательских атрибутов в темах. Предположим, у вас есть несколько пользовательских представлений, которые все ссылаются на пользовательский атрибут "custom_background".
<declare-styleable name="MyCustomStylables"> <attr name="custom_background" format="color"/> </declare-styleable>
в теме вы определяете, что такое значение
<style name="MyColorfulTheme" parent="AppTheme"> <item name="custom_background">#ff0000</item> </style>
или
<style name="MyBoringTheme" parent="AppTheme"> <item name="custom_background">#ffffff</item> </style>
вы можете ссылаться на атрибут в стиле
<style name="MyDefaultLabelStyle" parent="AppTheme"> <item name="android:background">?background_label</item> </style>
обратите внимание на знак вопроса, а также используется для ссылки Android атрибут как в
?android:attr/colorBackground
как большинство из вас заметили, вы можете-и, вероятно, должны - использовать ссылки @color вместо жестко закодированных цветов.
так почему бы просто не сделать
<item name="android:background">@color/my_background_color</item>
вы не можете изменить определение "my_background_color" во время выполнения, в то время как вы можете легко переключать темы.