What you can do is to create user-defined attributes to see what kinds of (for example, TextView.Person , TextView.Date ...), your xml you can refer to the attributes, and then define the attributes in different themes. For example, your style.xml might be
<resources> <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar" > <item name="TextView.Date">@style/DateTextViewDefault</item> </style> <style name="DateTextViewDefault"> <item name="android:textColor">#ff333333</item> <item name="android:fontFamily">monospace</item> </style> <style name="AppTheme.A"> <item name="colorPrimary">#3F51B5</item> <item name="colorPrimaryDark">#303F9F</item> <item name="colorAccent">#FF4081</item> <item name="TextView.Person">@style/PersonTextViewA</item> </style> <style name="PersonTextViewA"> <item name="android:textSize">16sp</item> <item name="android:fontFamily">serif</item> <item name="android:textColor">#ff999999</item> </style> <style name="AppTheme.B"> <item name="colorPrimary">#888888</item> <item name="colorPrimaryDark">#555555</item> <item name="colorAccent">#000000</item> <item name="TextView.Person">@style/PersonTextViewB</item> <item name="TextView.Date">@style/DateTextViewB</item> </style> <style name="PersonTextViewB"> <item name="android:textSize">20sp</item> <item name="android:fontFamily">monospace</item> <item name="android:textColor">#ff55aa</item> </style> <style name="DateTextViewB"> <item name="android:textColor">#ff0000BB</item> <item name="android:fontFamily">sans-serif</item> </style> <attr name="TextView.Person" format="reference" /> <attr name="TextView.Date" format="reference" /> </resources>
then your xml layout of your activity
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView style="?attr/TextView.Person" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="John Doe" /> <TextView style="?attr/TextView.Date" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="31/12/1999" /> <Button android:id="@+id/buttonA" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="THEME A" /> <Button android:id="@+id/buttonB" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="THEME B" /> </LinearLayout>
note that the TextView styles are
style="?attr/TextView.Person"
and
style="?attr/TextView.Date"
AppTheme.A and AppTheme.B have two different permissions for these attributes.
In this example, the attributes are whole styles for your views, but you can easily have one style for each type of view ( TextView.Person ), and then define common attributes for the individual elements of that style, for example.
<attr name="TextView.Person.TextColor" format="color" />
and change only one attribute in your themes.
Then in your Activity you just need to set the theme in onCreate using setTheme(int) , the value can be either R.style.AppTheme_A , or R.style.AppTheme_B in this case.
With this method, you can add as many styles as you want without touching layouts. In addition, you can always define some default styles in your base theme, and then override this value in some custom themes, while others use the default value for TextView.Date in the example above.
If you want a quick try, here is the Activity code I used to test style.xml and activity_main.xml above
class MainActivity : AppCompatActivity() { private val prefs by lazy { getSharedPreferences("SharedPrefs", Context.MODE_PRIVATE) } private var customTheme: Int get() = prefs.getInt("theme", R.style.AppTheme_A) set(value) = prefs.edit() .putInt("theme", value) .apply() .also { recreate() } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setTheme(customTheme) setContentView(R.layout.activity_main) buttonA.setOnClickListener { customTheme = R.style.AppTheme_A } buttonB.setOnClickListener { customTheme = R.style.AppTheme_B } } }