以编程方式全局更改应用主题



我正在编写一个应用程序,它具有光明和黑暗模式,声明在这里:

styles.xml

<style name="Noon" parent="Theme.AppCompat.NoActionBar">
<item name="upper_bg">@drawable/day_sky_top</item>
<item name="lower_bg">@drawable/day_sky</item>
<item name="android:statusBarColor">@color/colorPrimaryDark</item>
</style>
<style name="Night" parent="Theme.AppCompat.NoActionBar">
<item name="upper_bg">@drawable/night_sky_top</item>
<item name="lower_bg">@drawable/night_sky</item>
<item name="android:statusBarColor">@color/colorNightDark</item>
</style>
根据这个答案,我创建了以下文件:

/res/价值/attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="customAttrs">
<attr name="upper_bg" format="reference" />
<attr name="lower_bg" format="reference" />
</declare-styleable>
</resources>

并像这样自定义我的ImageViews:

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="@+id/top_bg"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.65"
android:src="?attr/upper_bg"/>
<ImageView
android:id="@+id/bottom_bg"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.35"
android:src="?attr/lower_bg"/>
</LinearLayout>

(注意这是代码的一部分,所有标记都正确关闭)

只要我有:

boolean night = true;
setTheme(night ? R.style.Night : R.style.Noon);
setContentView(R.layout.activity_main); // or whatever activity I'm in.

在我的应用程序的每一个活动。是否有一种方法来运行这个代码一次,使我的主题改变全局?

您仍然可以添加BaseActivity来覆盖override fun onCreate(),将setTheme()的责任委托给从它继承的任何其他Activity

override fun onCreate(savedInstanceState: Bundle?) {
val night = true
setTheme(if (night) R.style.Night else R.style.Noon) 
}

如果你不喜欢BaseActivity,你可以在某个地方创建一个扩展函数,负责根据用户偏好设置主题:

fun Activity.setTheme() {
val night = true
// Or even have more than two theme styles
this.setTheme(if (night) R.style.Night else R.style.Noon)
}

然后被这样调用:

override fun onCreate(savedInstanceState: Bundle?) {
setTheme()
}

UPDATE: Java code

这个类将是每个所需Activity的基类

public abstract class BaseActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
boolean night = true;
setTheme(night ? R.style.Night : R.style.Noon);
}
}

现在,假设你要实现"特性1"one_answers"特性2",因此,您可以直接从BaseActivity继承它们。

"功能1":

public class Feature1Activity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // <- BaseActivity's onCreate() will set theme for you
setContentView(R.layout.activity_feature_1);
}
}
2">

"特点:

public class Feature2Activity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // <- BaseActivity's onCreate() will set theme for you
setContentView(R.layout.activity_feature_2);
}
}

你可以!你必须使用类AppCompatDelegate的setDefaultNightMode()方法,它接受你想应用的主题的值,可用的值是MODE_NIGHT_NO &MODE_NIGHT_YES,MODE_NIGHT_FOLLOW_SYSTEM分别设置为灯光、夜晚和手机默认主题,你可以这样做:

AppCompatDelegate.setDefaultNightMode(THE_MODE_YOU_WANT);

重要的是要注意,从AppCompat v1.0.0开始,当这个方法被调用时,它会重新创建所有正在运行的活动来应用主题。

如果你正在运行Api 29或更高版本,你应该考虑使用Force Dark,你可以在官方文档中查看它以更好地理解它。

享受吧!

相关内容

  • 没有找到相关文章

最新更新