一、软件换肤从功能上可以划分三种:
1) 软件内置多个皮肤,不可由用户增加或修改;
2) 官方提供皮肤供下载,用户可以使用下载的皮肤;
3) 官方提供皮肤制作工具或方法,用户可自制皮肤。
二、软件换肤从实现上来可以划分二种:
1) 皮肤内置到应用程序中;
2) 皮肤资源与应用程序分离;
三、本篇将先学习第一种相对非常简单的实现方式一:[皮肤资源内置到应用程序中]
该方式的主要思路:
1. 把几套皮肤[作为应用背景的图片资源]放在res/drawable目录里,然后用SharedPreferences来记录当前皮肤的资源id.然后在程序启动时加载Activity背景。
2. 主要的实现在皮肤设置管理器SkinSettingManager类中. 将皮肤资源的ID加入集合中. 由该类统一调度皮肤更换,如初始化皮肤,获取当前皮肤符号以及具体的对应资源的更换皮肤.
下面将以一个小demo程序来介绍具体的代码实现:
1) 首先程序运行效果图如下:
2) 布局文件:src\main\res\layout\activity_skin_main.xml
【我这里使用的是Android Studio, 项目结构与Eclipse不一样】
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context="com.ice.skininnerdemo.SkinInnerDemoActivity">
<CheckBox
android:id="@+id/cb_skin1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/skin_default"/>
<!-- 分割线 -->
<View
android:layout_width="fill_parent"
android:layout_height="1dp"
android:layout_marginTop="10dp"
android:background="@drawable/line_shape" />
<CheckBox
android:id="@+id/cb_skin2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="@string/skin_morning" />
<!-- 分割线 -->
<View
android:layout_width="fill_parent"
android:layout_height="1dp"
android:layout_marginTop="10dp"
android:background="@drawable/line_shape" />
<CheckBox
android:id="@+id/cb_skin3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="@string/skin_night" />
<!-- 分割线 -->
<View
android:layout_width="fill_parent"
android:layout_height="1dp"
android:layout_marginTop="10dp"
android:background="@drawable/line_shape" />
</LinearLayout>
里面有个 Shpae绘制的 分割线drawable资源文件:@drawable/line_shape ,内容如下:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#DCDCDC" />
<size android:height="1dp" android:width="1dp" />
</shape>
3) 重要的皮肤设置管理器:SkinSettingManager.java
package com.ice.skininnerdemo;
import android.app.Activity;
import android.content.SharedPreferences;
/**
* Copy by http://blog.youkuaiyun.com/t12x3456/article/details/7933382
*/
public class SkinSettingManager {
public final static String SKIN_PREF = "skinSetting";
public SharedPreferences skinSettingPreference;
/** 初始化3种皮肤资源 */
private int[] skinResources = { R.drawable.dusk,
R.drawable.morning, R.drawable.night
};
private Activity mActivity;
public SkinSettingManager(Activity activity) {
this.mActivity = activity;
skinSettingPreference = mActivity.getSharedPreferences(SKIN_PREF, 3);
}
/**
* 获取当前程序的皮肤序号
*
* @return
*/
public int getSkinType() {
String key = "skin_type";
return skinSettingPreference.getInt(key, 0);
}
/**
* 把皮肤序号写到全局设置里去
*
* @param j
*/
public void setSkinType(int j) {
SharedPreferences.Editor editor = skinSettingPreference.edit();
String key = "skin_type";
editor.putInt(key, j);
editor.commit();
}
/**
* 获取当前皮肤的背景图资源id
*
* @return
*/
public int getCurrentSkinRes() {
int skinLen = skinResources.length;
int getSkinLen = getSkinType();
if(getSkinLen >= skinLen){
getSkinLen = 0;
}
return skinResources[getSkinLen];
}
/**
* 选择皮肤资源
* @param skinTypeIndex 皮肤资源索引
*/
public void selectSkinType(int skinTypeIndex){
setSkinType(skinTypeIndex);
mActivity.getWindow().setBackgroundDrawable(null);
try {
mActivity.getWindow().setBackgroundDrawableResource(getCurrentSkinRes());
} catch (Exception e){
e.printStackTrace();
}
}
/**
* 用于初始化皮肤
*/
public void initSkins(){
mActivity.getWindow().setBackgroundDrawableResource(getCurrentSkinRes());
}
}
4) 程序Activity主界面: SkinInnerDemoActivity。
package com.ice.skininnerdemo;
import android.app.Activity;
import android.os.Bundle;
import android.widget.CheckBox;
import android.widget.CompoundButton;
public class SkinInnerDemoActivity extends Activity {
private SkinSettingManager mSkinSettingManager;
private CheckBox cb_skin1, cb_skin2, cb_skin3;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_skin_main);
mSkinSettingManager = new SkinSettingManager(this);
initView();
bindEvent();
}
private void initView() {
cb_skin1 = (CheckBox) findViewById(R.id.cb_skin1);
cb_skin2 = (CheckBox) findViewById(R.id.cb_skin2);
cb_skin3 = (CheckBox) findViewById(R.id.cb_skin3);
// 初始化默认皮肤
mSkinSettingManager.initSkins();
cb_skin1.setChecked(true);
}
private void bindEvent() {
SkinCheckedChangeListener skinCheckListener = new SkinCheckedChangeListener();
cb_skin1.setOnCheckedChangeListener(skinCheckListener);
cb_skin2.setOnCheckedChangeListener(skinCheckListener);
cb_skin3.setOnCheckedChangeListener(skinCheckListener);
}
/**
* CheckBox Check选中变化事件监听类
*/
class SkinCheckedChangeListener implements CompoundButton.OnCheckedChangeListener{
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
switch (compoundButton.getId()) {
case R.id.cb_skin1:
if (checked) {
// 选中状态
mSkinSettingManager.selectSkinType(0);
cb_skin2.setChecked(false);
cb_skin3.setChecked(false);
}
break;
case R.id.cb_skin2:
if (checked) {
// 选中状态
mSkinSettingManager.selectSkinType(1);
cb_skin1.setChecked(false);
cb_skin3.setChecked(false);
}
break;
case R.id.cb_skin3:
if (checked) {
// 选中状态
mSkinSettingManager.selectSkinType(2);
cb_skin1.setChecked(false);
cb_skin2.setChecked(false);
}
break;
}
}
}
}
到这里 主要介绍、学习了第一种实现换肤的方式:皮肤资源内置到应用程序中的换肤、这种方式一般适用于小型、对换肤图片背景资源要求不高的情况、不支持下载皮肤、自定义皮肤、只能更换应用内置的几种皮肤效果。本demo程序也只是一个简单、粗暴、单界面的展示、重点是掌握内置换肤的思路。
++++++++++++++++++++
本篇学习参考于:http://blog.youkuaiyun.com/t12x3456/article/details/7933382