今天带给大家一篇干货。Android的主题换肤,无需Activity重启直接实现无缝切换,本文属于使用APP内置资源文件加载的方案,适合不需要插件化提供皮肤的APP。我的这个方法最大的优点就是简单易学。
相比于网上其他的方案需要各种复杂的API,或者直接就是一个第三方,但是我这个你只需要定义一个Moudle就可以了。下面来看具体的实现。
1、开启DataBinding
首先我们这个项目是使用DataBinding的一个项目,所以我们要在gradle中将DataBinding给开启。使用DataBinding的好处我这里就不再赘述。有兴趣的可以自行上网查阅。具体的使用可以参考下面的博客地址。
http://blog.csdn.net/u012702547/article/details/52077515
android {
......
dataBinding {
enabled true
}
}
2、定义Moudle
这里我们使用DataBinding的方式,让Moudle继承BaseObservable使其数据更新时,界面无缝刷新。这也是本方案的核心思想。
public class SkinInfo extends BaseObservable {
private int main_bg;
private int btn_bg;
@BindingAdapter("bind:bg")
public static void loadSkinBg(View view, int main_bg) {
view.setBackgroundResource(main_bg);
}
@Bindable
public int getBtn_bg() {
return btn_bg;
}
public void setBtn_bg(int btn_bg) {
this.btn_bg = btn_bg;
notifyPropertyChanged(com.zhenquan.skindemo.BR.btn_bg);
}
@Bindable
public int getMain_bg() {
return main_bg;
}
public void setMain_bg(int main_bg) {
this.main_bg = main_bg;
notifyPropertyChanged(com.zhenquan.skindemo.BR.main_bg);
}
}
3、在MainActivity中使用DataBinding
首先是布局:
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
>
<data
>
<variable
name="skinInfo"
type="com.zhenquan.skindemo.SkinInfo"/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:bg="@{skinInfo.main_bg}">
<Button
android:id="@+id/btn_normal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="默认皮肤"
app:bg="@{skinInfo.btn_bg}"/>
<Button
android:id="@+id/btn_green"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Green皮肤"
app:bg="@{skinInfo.btn_bg}"/>
</LinearLayout>
</layout>
然后是代码:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding viewDataBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
viewDataBinding.setSkinInfo(MyApplication.getSkinInfo());
final SkinInfo skinInfo = MyApplication.getSkinInfo();
viewDataBinding.btnNormal.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
skinInfo.setBtn_bg(R.drawable.btn_blue);
skinInfo.setMain_bg(R.drawable.main_gradient_blue);
PreferenceManager.getDefaultSharedPreferences(MainActivity.this).edit().putInt("btn_bg", skinInfo.getBtn_bg()).apply();
PreferenceManager.getDefaultSharedPreferences(MainActivity.this).edit().putInt("main_bg", skinInfo.getMain_bg()).apply();
}
});
viewDataBinding.btnGreen.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
skinInfo.setBtn_bg(R.drawable.btn_green);
skinInfo.setMain_bg(R.drawable.main_gradient_green);
PreferenceManager.getDefaultSharedPreferences(MainActivity.this).edit().putInt("btn_bg", skinInfo.getBtn_bg()).apply();
PreferenceManager.getDefaultSharedPreferences(MainActivity.this).edit().putInt("main_bg", skinInfo.getMain_bg()).apply();
}
});
}
}
MyApplication提供SkinInfo
public class MyApplication extends Application {
private static SkinInfo mSkinInfo;
@Override
public void onCreate() {
super.onCreate();
mSkinInfo = new SkinInfo();
mSkinInfo.setMain_bg(PreferenceManager.getDefaultSharedPreferences(this).getInt("main_bg",R.drawable.main_gradient_blue));
mSkinInfo.setBtn_bg(PreferenceManager.getDefaultSharedPreferences(this).getInt("btn_bg",R.drawable.btn_blue));
}
public static SkinInfo getSkinInfo() {
return mSkinInfo;
}
}
最后不要忘记在清单文件中使用MyApplication.
这样我们基本的换肤功能就实现了,这里是使用Sp保存的换肤配置信息,更近一步的优化我们可以去使用数据库直接将SkinInfo这个Moudle给保存下来。当我们想要让App的某一个部分实现换肤的时候,只要在SkinIndo中添加一个字段,然后在切换皮肤的时候将此字段设置为相应的资源文件即可。
Demo源码:http://pan.baidu.com/s/1hsDq0mw