在这里咱们所说的并不是自定义属性,关于自定义属性,请参考以前的文章,讲的很细,今天所说的是自定义“属性名”。java
先讲一下,为何咱们须要自定义咱们的属性名,加入你再开发一个应用,该应用你设置好几种主题,每个主题对应与整个程序的不少中属性,假如在一种主题当中有内容背景色(属性为:background),并且还有字体背景色(一样为:background),若是我须要更换主题的时候,以上所说的颜色的改变就会略有麻烦,若是此时,我给以上颜色的取值取了名字。好比第一个颜色我能够设置为"contentBackgrounp",第二个颜色就能够设置为"fontBackgrounp",这样的话呢,我就能够区分这两种 颜色,更换主题时,只需调用setTheme()方法就能够了,其余的什么都不须要改变。android
上面说的有些不太懂,没有办法,语言水平就到这了,下面我用代码去实现这些。app
首先,我须要定义以上两种属性:theme_atrrs.xml
ide
<?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文件中初始化咱们的主题,此处假如咱们默认为日间模式this
<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"
而后,咱们就能够在咱们的布局中去使用咱们定义好的属性:code
<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)便可。orm
因为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方法以后用从新建立一个新的实例