Android实现切换主题功能
程序员文章站
2022-05-14 21:05:46
...
现在市面上有很多app都有更换主题皮肤的功能,那么到底是怎么实现的呢?
首先我们先上一张简单效果图
特别简单的实现,我们通过点击按钮切换主题
1.实现原理
实现起来特别简单,这里我们准备多个主题资源(自己适配),然后通过代码控制切换主题
项目结构
2.配置styles.xml 和manifest清单
styles.xml
<resources>
<!--正常主题-->
<style name="LightTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimary">@color/white</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/white</item>
<item name="myBgColor">@color/white</item>
<item name="background">@color/white</item>
<item name="myTextColor">@color/white</item>
<item name="myButtonColor">@color/black</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
<!--黑暗主题-->
<style name="NightTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
<item name="colorPrimary">@color/black</item>
<item name="colorPrimaryDark">@color/red</item>
<item name="colorAccent">@color/black</item>
<item name="myBgColor">@color/black</item>
<item name="background">@color/black</item>
<item name="myTextColor">@color/black</item>
<item name="myButtonColor">@color/white</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
</resources>
AndroidManifest.xml
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/LightTheme">//设置自定义主题
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
attr.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="myBgColor" format="color" />
<attr name="myButtonColor" format="color" />
<attr name="myTextColor" format="color" />
</resources>
接下来我们在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"
android:background="?attr/myBgColor"
tools:context=".MainActivity">
<Button
android:id="@+id/btn_setTheme"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_btn"
android:text="切换主题"
android:textColor="?attr/myTextColor"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
3.通过代码控制主题
我们利用 setTheme(id);的方法动态的设置主题(不过需要注意这个方法需要放到setContentView(R.layout.activity_main); 之前)
然后调用recreate();方法重启资源
我们要实现点击按钮就实现连续更换主题,我们需要记录下来更换状态,这里利用了SharedPreferences来存储更换状态。
实现代码:
public class MainActivity extends AppCompatActivity {
private Button mBtn;
private Boolean mUseMyTheme;
@SuppressLint("ObsoleteSdkInt")
@Override
protected void onCreate(Bundle savedInstanceState) {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {
Window window = getWindow();
window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
super.onCreate(savedInstanceState);
final SharedPreferences sharedPreferences = getSharedPreferences("useMyTheme", MODE_PRIVATE);//获取主题更换状态
mUseMyTheme = sharedPreferences.getBoolean("useMyTheme", true);//第一次默认设置为亮色主题
if (!mUseMyTheme) {
setTheme(R.style.NightTheme);//黑色主题
} else {
setTheme(R.style.LightTheme);//亮色主题
}
setContentView(R.layout.activity_main);
mBtn = findViewById(R.id.btn_setTheme);
mBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mUseMyTheme = !mUseMyTheme;//切换主题状态
recreate();//重启资源
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putBoolean("useMyTheme", mUseMyTheme);//存储主题更换状态
editor.commit();
}
});
}
}
到这里简单的实现了主题切换的功能,那大部分app的主题皮肤大多数都是要下载的,不可能把这些五花八门的样式全都都放在apk文件上,那样的话应用会很大。所以皮肤是通过网络下载的(当然可以有几套默认的皮肤)在放入资源文件夹下,实现方法也是这样。