在android应用程序中我们可能需要切换模式,如晚上切换到夜间模式便于阅读等。本文参考了网上的一些资料,并结合实例,实现了动态更改主题的效果。

Android中实现theme主题可以使用在activity中使用setTheme(int)的方法,SDK中对此方法的说明为:

//Set the base theme for this context. Note that this should be called before any views are instantiated in the Context (for example before calling android.app.Activity.setContentView or android.view.LayoutInflater.inflate).
//需要在setcontentview函数或者inflate函数之前使用。

效果图如下:

  

实现步骤:

首先需要定义一个属性,此属性用于赋值给控件的属性,相当于控件属性值的“变量”。

在attrs.xml中,定义三个属性,属性的format均为reference|color

<resources>

    <attr name="button_bg" format="reference|color" />
<attr name="activity_bg" format="reference|color" />
<attr name="text_cl" format="reference|color" /> </resources>

接下来,在styles.xml中,编写自定义的Theme

<style name="AppBaseTheme" parent="android:Theme.Light">
</style> <style name="AppTheme" parent="AppBaseTheme">
<item name="text_cl">#ffffff</item>
<item name="button_bg">#000000</item>
<item name="activity_bg">#ffffff</item>
</style> <style name="DarkTheme" parent="AppBaseTheme">
<item name="text_cl">#000000</item>
<item name="button_bg">#ffffff</item>
<item name="activity_bg">#000000</item>
</style>

选择一种模式作为程序的默认theme,注意:由于我是在layout布局文件中定义的view的样式,因此,为了保证theme切换时不会出现找不到资源的问题,因此需要在每一种用到的自定义theme中,都加上item。这里的item如text_cl和view的textColor属性的format是一致的。

Android manifest文件:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.testandroidsettheme"
android:versionCode="1"
android:versionName="1.0" > <uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" /> <application
android:allowBackup="true"
android:name="com.example.testandroidsettheme.app.MyApp"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.testandroidsettheme.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application> </manifest>

我将android:theme="@style/AppTheme"作为默认的样式。

主界面layout布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?activity_bg"
android:gravity="center"
android:orientation="vertical" > <Button
android:id="@+id/button0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?button_bg"
android:textColor="?text_cl"
android:text="set theme" /> </LinearLayout>

在布局文件中,button的background属性采用的是当前theme下的button_bg的属性值,外部的linearlayout采用的是当前theme下的activity_bg的属性值,在填写此属性值时,需要在前面添加”?”,表示这是一个style中的变量。

在需要切换显示不同theme的activity中,一些博客中在button点击事件中使用

setTheme(int);

recreate();

的方式,我发现此种方式无法实现theme的切换,因为recreate()方法会重新创建此activity,之前的setTheme()无效。我的实现方式如下:

public class MainActivity extends Activity {

    public Button button0;

    @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyApp app = (MyApp)MainActivity.this.getApplication();
if(app.theme == 0){
//使用默认主题
}else{
//使用自定义的主题
setTheme(app.theme);
}
setContentView(R.layout.activity_main); button0 = (Button) this.findViewById(R.id.button0);
button0.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MyApp app = (MyApp)MainActivity.this.getApplication();
app.theme = R.style.DarkTheme;
recreate();
}
});
}
} public class MyApp extends Application{
public int theme = 0;
}

在此activityoncreate()中的setContentView()方法调用之前,判断当前的theme,并调用setTheme(),实现改变theme的效果。

注意:这种方法实现切换theme不是很友好,因为在activity重新创建时,可能会有闪屏的现象。比较好的解决方案如知乎客户端采用的是截屏,并渐隐图片的过度方式,具体的实现还有待学习。

参考资料:http://www.kymjs.com/code/2015/05/26/01/

最新文章

  1. 30分钟学会反向Ajax
  2. js判断中文
  3. JS运动基础
  4. sublime3+wamp配置php,(无需配环境变量)
  5. zookeeper适用场景:zookeeper解决了哪些问题
  6. ORACLE 总结
  7. 使你的 Google Summer of Code 建议被接收的5个技巧
  8. HDU 4424 Conquer a New Region
  9. http://src.chromium.org/svn/ 定制chrome浏览器教程及源码
  10. list.h
  11. silverlight依赖属性
  12. 《MATLAB从入门到放弃》打通 “矩阵” 障碍
  13. Spark环境搭建(中)——Hadoop安装
  14. docker 数据卷管理
  15. 第三个Sprint冲刺第3天
  16. PKCS 15 个标准
  17. UVA10341 Solve It
  18. Django中使用mysql数据库并使用原生sql语句操作
  19. 如何删除VS2015中的OpenCV的配置
  20. python基础学习1-列表使用

热门文章

  1. C2第三次作业解题报告
  2. Spring &lt;context:annotation-config/&gt; 解说
  3. IOS笔记之UIKit_UIScrollView
  4. Razor视图引擎输出没有编码的 Html 字符串
  5. SQL语句汇总(二)——数据修改、数据查询
  6. MySql、SqlServer、Oracle 三种数据库查询分页方式
  7. [C++] 将 mp3 等音乐资源以资源形式嵌入 exe 文件中
  8. Java基础的一次总结
  9. proj01总结:spring jdbc操作
  10. docker学习笔记一:基本安装和设置容器静态ip