Cómo: Definir elemento de tema (estilo) para el widget personalizado

He escrito un widget personalizado para un control que usamos ampliamente en toda nuestra aplicación. La clase widget deriva de ImageButton y lo extiende de un par de maneras simples. He definido un estilo que puedo aplicar al widget como se utiliza, pero prefiero configurar esto a través de un tema. En R.styleable veo los atributos del estilo del widget como imageButtonStyle y textViewStyle . ¿Hay alguna manera de crear algo así para el widget personalizado que escribí?

Sí, hay una manera:

Supongamos que tiene una declaración de atributos para su widget (en attrs.xml ):

 <declare-styleable name="CustomImageButton"> <attr name="customAttr" format="string"/> </declare-styleable> 

Declare un atributo que utilizará para una referencia de estilo (en attrs.xml ):

 <declare-styleable name="CustomTheme"> <attr name="customImageButtonStyle" format="reference"/> </declare-styleable> 

Declare un conjunto de valores de atributo por defecto para el widget (en styles.xml ):

 <style name="Widget.ImageButton.Custom" parent="android:style/Widget.ImageButton"> <item name="customAttr">some value</item> </style> 

Declare un tema personalizado (en themes.xml ):

 <style name="Theme.Custom" parent="@android:style/Theme"> <item name="customImageButtonStyle">@style/Widget.ImageButton.Custom</item> </style> 

Utilice este atributo como el tercer argumento en el constructor de su widget (en 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(); } } 

Ahora tienes que aplicar Theme.Custom a todas las actividades que utilizan CustomImageButton (en AndroidManifest.xml):

 <activity android:name=".MyActivity" android:theme="@style/Theme.Custom"/> 

Eso es todo. Ahora CustomImageButton intenta cargar los valores de atributo predeterminados del atributo customImageButtonStyle del tema actual. Si no se encuentra tal atributo en el valor del tema o atributo es @null entonces se @null el argumento final para obtainStyledAttributes : Widget.ImageButton.Custom en este caso.

Puede cambiar los nombres de todas las instancias y todos los archivos (excepto AndroidManifest.xml ), pero sería mejor utilizar la convención de nomenclatura de Android.

Otro aspecto, además de la respuesta excelente de Michael es la sustitución de atributos personalizados en los temas. Suponga que tiene varias vistas personalizadas que se refieren al atributo personalizado "custom_background".

 <declare-styleable name="MyCustomStylables"> <attr name="custom_background" format="color"/> </declare-styleable> 

En un tema se define cuál es el valor

 <style name="MyColorfulTheme" parent="AppTheme"> <item name="custom_background">#ff0000</item> </style> 

o

 <style name="MyBoringTheme" parent="AppTheme"> <item name="custom_background">#ffffff</item> </style> 

Puede hacer referencia al atributo en un estilo

 <style name="MyDefaultLabelStyle" parent="AppTheme"> <item name="android:background">?background_label</item> </style> 

Observe el signo de interrogación, como también se utiliza para el atributo android de referencia como en

 ?android:attr/colorBackground 

Como la mayoría de ustedes han notado, pueden -y probablemente deberían usar- referencias @color en vez de colores codificados.

Entonces, ¿por qué no simplemente hacer

 <item name="android:background">@color/my_background_color</item> 

No puedes cambiar la definición de "my_background_color" en tiempo de ejecución, mientras que puedes cambiar fácilmente los temas.

  • Dependiendo de los recursos
  • Cómo configurar el tema de Holo para la aplicación de Android
  • Invisible ActionMode iconos de elemento en Theme.Sherlock.Light.DarkActionBar
  • Cambiar el color de resaltado y título de los fragmentos en PreferenceActivity
  • ¿Cómo usar el tema predeterminado del dispositivo para la aplicación?
  • Heredando de Theme.AppCompat *
  • Barra de acción plana con Theme.Material
  • ¿Qué atributos de tema necesito anular para cambiar el color de resaltado azul de mis cuadros de diálogo?
  • Cómo cambiar el tema de la aplicación de "Actividad en blanco" a "Flujo maestro / detallado"
  • Tema de botón incorrecto al cambiar el modo Día / Noche
  • Cambiar el color de resaltado del elemento seleccionado para el menú del menú de menú duro
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.