Android 深色模式使用失效
Android提供了一种简单的深色模式来实现简单的换肤功能
最近使用时发现应用的颜色没有与系统的深色模式一起切换,原因在于我们是否使用了android:configChanges="uiMode"
假如我们没有在清单文件加上该配置
那么我们可以在attrs.xml定义
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="testColor" format="color" />
</resources>
然后在values下定义themes
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.TestApp" parent="Theme.MaterialComponents.DayNight">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_500</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_700</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
<item name="testColor">#0f0</item>
<!-- Customize your theme here. -->
</style>
</resources>
然后在values-night下定义themes
<resources xmlns:tools="http://schemas.android.com/tools">
<style name="Theme.TestApp" parent="Theme.MaterialComponents.DayNight">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_200</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/black</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_200</item>
<item name="colorOnSecondary">@color/white</item>
<!-- Status bar color. -->
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
<item name="testColor">#f00</item>
</style>
</resources>
我们创建一个包含Fragment的Activity:
activity.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<LinearLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</LinearLayout>
</LinearLayout>
fragment1.xml
<?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:background="?attr/colorOnPrimary"
android:gravity="center"
android:orientation="vertical" >
<TextView
android:id="@+id/textView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textColor="?attr/testColor"
android:text="我是界面1" />
</LinearLayout>
Fragment1.kt
class Fragment1 : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment1, null)
}
}
MainActivity.kt
class MainActivity : FragmentActivity() {
private val TAG: String = "hjcai"
private lateinit var content:LinearLayout
private lateinit var fm: FragmentManager
private lateinit var ft: FragmentTransaction
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
content = findViewById(R.id.content)
fm = supportFragmentManager
ft = fm.beginTransaction()
ft.replace(R.id.content, Fragment1())
ft.commit()
}
}
这时Android的深色模式会帮助我们自动根据当前系统的色彩模式选择正确的颜色
但是如果我们在清单文件中加上了configChanges="uiMode"
那么Android将不会自动切换颜色
我们可以在MainActivity加上这段代码
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
recreateViews()
}
private fun recreateViews() {
val fragment: Fragment? = supportFragmentManager.findFragmentById(R.id.content)
if (fragment != null) {
supportFragmentManager.beginTransaction().detach(fragment).commit()
supportFragmentManager.beginTransaction().attach(fragment).commit()
}
}
此时我们需要重新创建fragment来加载正确的颜色
我们还可以在onConfigurationChanged监听day night mode的变化
val nightMode = newConfig.uiMode and Configuration.UI_MODE_NIGHT_MASK
if (nightMode == Configuration.UI_MODE_NIGHT_YES) {
//night mode
}
if (nightMode == Configuration.UI_MODE_NIGHT_NO) {
//not night mode
}
这是一种简单的换肤方案 只有两套皮肤,如果想实现多种皮肤换肤还是得使用之前红橙Darren视频笔记 换肤框架中拦截view创建的方式去换肤