您可以做的是为视图类型创建自定义属性(例如TextView.Person,TextView.Date …),在xml中,您可以引用属性,然后在不同的主题中定义属性.例如,你可以使用style.xml
@style/DateTextViewDefault
#ff333333
monospace
#3F51B5
#303F9F
#FF4081
@style/PersonTextViewA
16sp
serif
#ff999999
#888888
#555555
#000000
@style/PersonTextViewB
@style/DateTextViewB
20sp
monospace
#ff55aa
#ff0000BB
sans-serif
然后你的活动xml布局
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
style="?attr/TextView.Person"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="John Doe" />
style="?attr/TextView.Date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="31/12/1999" />
android:id="@+id/buttonA"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="THEME A" />
android:id="@+id/buttonB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="THEME B" />
注意TextView的样式是
style="?attr/TextView.Person"
和
style="?attr/TextView.Date"
AppTheme.A和AppTheme.B对这些属性有2种不同的分辨率
在此示例中,属性是视图的整个样式,但您可以轻松地为每种视图类型(TextView.person)设置一种样式,然后为该样式的单个项目定义通用属性,例如:
并且只更改主题中的单个属性.
然后在您的Activity中,您只需要使用setTheme(int)在onCreate中设置主题,在这种情况下,值可以是R.style.AppTheme_A或R.style.AppTheme_B.
使用此方法,您可以根据需要添加任意数量的样式,而无需触摸布局.此外,您始终可以在基本主题中定义一些默认样式,然后仅在某些自定义主题中覆盖该值,而其他样式则使用上面示例中的TextView.Date的默认样式.
如果你想快速尝试一下,这里是我用来测试style.xml和activity_main.xml的Activity的代码
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 }
}
}