Sí, hay una forma:
Suponga 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 usará 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 atributos predeterminados 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 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 );
this.customAttr =
array.getString( R.styleable.CustomImageButton_customAttr, "" );
array.recycle();
}
}
Ahora tienes que aplicar Theme.Custom
a todas las actividades que usan CustomImageButton
(en AndroidManifest.xml):
<activity android:name=".MyActivity" android:theme="@style/Theme.Custom"/>
Eso es todo. Ahora CustomImageButton
intenta cargar valores de customImageButtonStyle
atributo predeterminados del atributo del tema actual. Si no se encuentra tal atributo en el tema o el valor del atributo es , se utilizará @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 usar la convención de nomenclatura de Android.
customImageButtonStyle
en esta respuesta). Así es como se personaliza la barra de acciones en Android. Y si te refieres a cambiar un tema en tiempo de ejecución, entonces no es posible con este enfoque.name="CustomTheme"
Eldeclare-styleable
envoltorio de atributo tiene algún propósito? Es solo para organización, porque no veo que se use en ningún lado. ¿Puedo poner todos mis atributos de estilo para varios widgets en un contenedor?Otro aspecto además de la excelente respuesta de Michael es anular los atributos personalizados en los temas. Suponga que tiene varias vistas personalizadas que hacen referencia al atributo personalizado "fondo_personalizado".
<declare-styleable name="MyCustomStylables"> <attr name="custom_background" format="color"/> </declare-styleable>
En un tema, defines 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, que también se usa para el atributo de Android de referencia como en
?android:attr/colorBackground
Como la mayoría de ustedes ha notado, puede -y probablemente debería- usar referencias de @color en lugar de colores codificados.
Entonces, ¿por qué no hacerlo?
<item name="android:background">@color/my_background_color</item>
No puede cambiar la definición de "my_background_color" en tiempo de ejecución, mientras que puede cambiar de tema fácilmente.
fuente