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是一致的。

Androidmanifest文件:

<?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>

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

在需要切换显示不同themeactivity中,一些博客中在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. [置顶] 我的Android进阶之旅------>Android之Animations动画详解
  2. xmlns:tools
  3. 关于上传的app的标识号和版本号
  4. Android为ViewPager增加切换动画——使用属性动画
  5. android 应用的网络请求工具
  6. EditText属性和相关用法
  7. 如何更改Android(安卓)程序的icon快捷方式图标?
  8. Android(安卓)—— TextView中的MaxLines和ellipsize属性的冲突
  9. Android(安卓)SDK Manager 无法更新解决办法

随机推荐

  1. 浅入浅出 Android 安全:第二章 Android Li
  2. 如何把多个Android Project打包成一个APK
  3. Android九环刀之RatingBar之评委请亮分
  4. Android应用程序防止被LMK干掉
  5. 升级Android SDK后ADT找不到adb.exe文件
  6. Android Debug Bridge(adb, Android调试
  7. Android视频播放程序关键部分简要解析
  8. Android API Demos学习(1) - Hello World
  9. Android中Bundle的使用示例
  10. VisionMobile:生态环境的游戏:破坏Android