前不久碰到了需要给软件更换主题的问题,研究了一段时间后可以基本实现功能了,在这里拿出来分享下方法,如有不足欢迎指正。

要想实现主题切换,我们得自定义一些主题的属性,自定义属性的attrs.xml新建在res/values下面。在这里我定义了软件背景,对话框图案和按钮的样式。

resources>

有了自定义主题属性后,就可以编写自己的主题了,同样在values文件夹里,找到styles.xml,可以看到里面有一个默认的系统主题,不用管它,在下面写自己主题的各种属性。注意我们的自定义主题也需要继承系统主题,也就是style的parent属性。

style>

"dialog_back">@drawable/spring_dialog

"dialog_button1">@drawable/spring_button1

"dialog_button2">@drawable/spring_button2

style>

"dialog_back">@drawable/summer_dialog

"dialog_button1">@drawable/summer_button1

"dialog_button2">@drawable/summer_button2

style>

"dialog_back">@drawable/autumn_dialog

"dialog_button1">@drawable/autumn_button1

"dialog_button2">@drawable/autumn_button2

style>

"dialog_back">@drawable/winter_dialog

"dialog_button1">@drawable/winter_button1

"dialog_button2">@drawable/winter_button2

style>

resources>

这里我用的是四季变化的主题,(说实话,由于不大会用PS软件,我做这套主题图片花的时间比我写代码要长多了。找到好看的背景,然后强迫症发作一定要搞定相匹配的对话框与按钮)大家可以选择自己喜欢的图片来替换这些。

这样一来前期准备就完成了,剩下的就是代码实现。由于主题切换涉及到很多的界面都需要更换背景,所以我干脆重写了Activity,需要更换背景的活动直接继承自己写的MyActivity会省事一些。

public class MyActivity extends Activity {

public int mytheme;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

SharedPreferences sharedPreferences = getSharedPreferences("info", MODE_PRIVATE);

mytheme = sharedPreferences.getInt("theme", 1);

if (mytheme == 1) {

setTheme(R.style.SpringTheme);

} else if (mytheme == 2) {

setTheme(R.style.SummerTheme);

} else if (mytheme == 3) {

setTheme(R.style.AutumnTheme);

} else if (mytheme == 4) {

setTheme(R.style.WinterTheme);

} else {

setTheme(R.style.SpringTheme);

}

}

@Override

protected void onResume() {

super.onResume();

if (mytheme != getSharedPreferences("info", MODE_PRIVATE).getInt("theme", 1)) {

changetheme();

}

}

protected void changetheme() {

Intent intent = getIntent();

intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);//它可以关掉所到的界面中间的activity

startActivity(intent);

overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);//设置进入退出动画

finish();

}

}

我是把切换过得主题用SharedPreferences保存下来,这样即使下次打开后还是上一次切换后的主题。这里的核心语句是setTheme(R.style.XXX),表示想要切换的主题。对于主题切换过程中的动画我这里使用的是渐出与渐入,大家也可以凭自己爱好修改。

注意,如果没有重写Acticvity,在活动中切换主题时记得把setTheme这一句放在setContentView的前面,不然有可能程序会出错,因为setContentView后活动的界面已经完成了,再设置主题在顺序上就有问题。在onResume()中进行界面跳转,这样不仅当前界面会切换主题背景,跳回前面的界面会发现背景也跟着变了。

最后就是具体的继承MyActivity来实现主题切换功能了。新建一个活动继承MyActivity,这里我只设置了一个按钮,点击弹出对话框提示是否确认切换主题,点确认就可以看到旧背景淡出,新背景淡入,且按钮的样式有了变化,点击按钮出现的对话框背景也相应变化。

下面是每次点击切换主题时候的逻辑代码,每次从SharedPreferences中取出当前主题代号,并相应地把代号往后挪一位再存进去。每次都调用onResume()方法来保证当前界面也能立即切换。

private void changethemeonce() {

SharedPreferences sharedPreferences = getSharedPreferences("info", MODE_PRIVATE);

int theme = sharedPreferences.getInt("theme", 1);

if (theme == 1) {

SharedPreferences.Editor editor = sharedPreferences.edit();

editor.putInt("theme", 2);

editor.apply();

onResume();

} else if (theme == 2) {

SharedPreferences.Editor editor = sharedPreferences.edit();

editor.putInt("theme", 3);

editor.apply();

onResume();

} else if (theme == 3) {

SharedPreferences.Editor editor = sharedPreferences.edit();

editor.putInt("theme", 4);

editor.apply();

onResume();

} else if (theme == 4) {

SharedPreferences.Editor editor = sharedPreferences.edit();

editor.putInt("theme", 1);

editor.apply();

onResume();

}

至于对话框样式的xml文件和刚进入程序的过渡Activity比较简单,大家可以按需求改动,在这里就不贴出来了,有兴趣的话可以下载来自己改着玩。

下载地址

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐