标签:
在这里我们所说的并非自定义属性,关于自定义属性,请参考之前的文章,讲的很细,今天所说的是自定义“属性名”。
先讲一下,为什么我们需要自定义我们的属性名,加入你再开发一个应用,该应用你设置好几种主题,每一个主题对应与整个程序的很多中属性,假如在一种主题当中有内容背景色(属性为:background),而且还有字体背景色(同样为:background),如果我需要更换主题的时候,以上所说的颜色的改变就会略有麻烦,如果此时,我给以上颜色的取值取了名字。比如第一个颜色我可以设置为"contentBackgrounp",第二个颜色就可以设置为"fontBackgrounp",这样的话呢,我就可以区分这两种 颜色,更换主题时,只需调用setTheme()方法就可以了,其他的什么都不需要改变。
上面说的有些不太懂,没有办法,语言水平就到这了,下面我用代码去实现这些。
首先,我需要定义以上两种属性:theme_atrrs.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <attr name="contentBackgrounp" format="reference"></attr> <attr name="fontBackgrounp" format="reference"></attr> </resources>
NOTICE:以上属性的格式一定要为reference格式,因为虽然我们设置了以上属性,但是我们不关心它是什么,我们关心的是它指向哪里,也就说这个属性实际上就代表着它所指向的值。(这个意思下面我再细说)
下面,我就要对以上属性,在我所使用的主题中进行赋值theme.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <!--夜间模式下的主题--> <style name="AppBaseTheme_Dark" parent="@style/Theme.AppCompat.Light"> <item name="contentBackgrounp">@color/dark_content</item> <item name="fontBackgrounp">@color/dark_font</item> </style> <!--日间模式下的主题--> <style name="AppBaseTheme_Light" parent="@style/Theme.AppCompat.Light"> <item name="contentBackgrounp">@color/day_content</item> <item name="fontBackgrounp">@color/day_font</item> </style> </resources>
下面,我们就要AndroidMainfest.xml文件中初始化我们的主题,此处假如我们默认为日间模式
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@style/AppBaseTheme_Light" > <activity android:name=".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>
也就是说设置如下语句,如果不设置如下语句,程序会报错
android:theme="@style/AppBaseTheme_Light"
然后,我们就可以在我们的布局中去使用我们定义好的属性:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="?attr/contentBackgrounp"> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:background="?attr/fontBackgrounp"/> </RelativeLayout>
因为,我们在使用过程中这两个组件的background都是一个指向的值,它的真正值是我们在theme.xml中设置的,所以,如果要改变主题,其他的什么都不需要改变,如果要设置为夜间模式,只需调用方法setTheme(R.style.AppBasetheme_Dark)即可。
由于setTheme方法的调用必须在调用执行方法setContentView()之前:使用,在使用时有两种处理方法;
第一种,也是最简单的方法:
setTheme(R.style.AppTheme_Light); this.onCreate(new Bundle());
只需以上两句就可以达到更换主题的方法。
第二种方法,虽然代码长度略长,但是是比较好的设计方法:
在SharedPreferences中配置一个键,存储主题模式,使用过程如下:
boolean isNight = false; SharedPreferences sp; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); sp = PreferenceManager.getDefaultSharedPreferences(this); setTheme((isNight = sp.getBoolean("isNight", false)) ? R.style.AppTheme_Dark : R.style.AppTheme_Light); setContentView(R.layout.activity_main);
点击按钮:
@Override public void onClick(View v) { int resId = v.getId(); switch (resId) { case R.id.day: if(isNight) { SharedPreferences.Editor editor = sp.edit(); editor.putBoolean("isNight",false); recreate(); } break; case R.id.dark: if(!isNight) { SharedPreferences.Editor editor = sp.edit(); editor.putBoolean("isNight", true); recreate(); } break; }
关于方法recreate:
Cause this Activity to be recreated with a new instance. This results in essentially the same flow as when the Activity is created due to a configuration change -- the current instance will go through its lifecycle to onDestroy() and a new instance then created after it.
意思是说:调用该方法,会使得该Activity重建一个新的实例,当前的实例会调用生命周期的onDestroy方法,并且在调用onDestroy方法之后用重新创建一个新的实例
标签:
原文地址:http://my.oschina.net/ccqy66/blog/489091