I'm trying to wrap my head around styles and themes. I currently have a single theme in my app:
<style name="WhiteTheme" parent="Theme.AppCompat.Light.NoActionBar">
...
</style>
I also have many styles for different views, like this:
<style name="BodyText" parent="TextAppearance.AppCompat.Body1">
<item name="android:textSize">14sp</item>
<item name="android:textColor">@color/default_text_color</item>
</style>
...which I use like this:
<TextView
...
android:textAppearance="@style/BodyText"/>
Now, if I were to create a new theme, say, a DarkTheme
, how would I ensure that all the TextViews referencing BodyText
as their TextAppearance would point to the new style?
Create an attr for the resource you would like to have different across themes.
<attr name="someTextColor" format="color"/>
Now in your themes, define the attrs
<style name="WhiteTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="someTextColor">@android:color/black</item>
</style>
<style name="DarkTheme" parent="Theme.AppCompat">
<item name="someTextColor">@android:color/white</item>
</style>
Now you can use them.
<style name="BodyText" parent="TextAppearance.AppCompat.Body1">
<item name="android:textSize">14sp</item>
<item name="android:textColor">?attr/someTextColor</item>
</style>
You can also get the attr from code
/**
* Returns color for attr from the {@link Theme}
*
* @param theme {@link Theme} to get int from
* @param attr Attribute of the int
* @return dimension for attr from the {@link Theme}
*/
@ColorInt
public static int getColor(@NonNull final Theme theme, @AttrRes final int attr) {
final TypedArray array = theme.obtainStyledAttributes(new int[]{attr});
try {
return array.getColor(0, Color.TRANSPARENT);
} finally {
array.recycle();
}
}
Or as ColorStateList
/**
* Returns {@link ColorStateList} for attr from the {@link Theme}
*
* @param theme {@link Theme} to get int from
* @param attr Attribute of the int
* @return dimension for attr from the {@link Theme}
*/
@Nullable
public static ColorStateList getColorStateList(@NonNull final Theme theme,
@AttrRes final int attr) {
final TypedArray array = theme.obtainStyledAttributes(new int[]{attr});
try {
return array.getColorStateList(0);
} finally {
array.recycle();
}
}
Then
final int someTextColor = getColor(getTheme(), R.attr.someTextColor);
// or
final ColorStateList someTextColor = getColorStateList(getTheme(), R.attr.someTextColor);