android换肤实现

来源:互联网 发布:免费空间 绑定域名 编辑:程序博客网 时间:2024/05/22 07:09

 皮肤资源内置的方式实现换肤效果、但本篇侧重于应用中换肤功能的代码设计实现上!切换的皮肤资源位于assets下不同的皮肤资源文件夹中。

    本篇demo程序的代码结构如下:

     

本篇实现换肤功能的代码设计 UML类图如下:


本篇demo的换肤效果如下:

      


      


主要的实现代码在于:

1、SkinConfigManager.java  

作用:皮肤配置管理,封装了SharedPreferences对选择皮肤的序号储存、以及根据皮肤类型锁定assets下的皮肤资源。 详细代码如下:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package com.ice.skininnerdemo;  
  2.   
  3. import android.content.Context;  
  4. import android.content.SharedPreferences;  
  5.   
  6. /** 
  7.  * 皮肤配置管理<单例> </br> 
  8.  * 封装了 SharedPreferences 对象的储存操作 
  9.  * Created by ice on 14-10-9. 
  10.  */  
  11. public class SkinConfigManager {  
  12.   
  13.     private static SkinConfigManager mSkinConfigManager;  
  14.     public static final String SKINCONFIG = "SkinConfig";  
  15.     public static final String CURSKINTYPEKEY = "curSkinTypeKey";  
  16.   
  17.     private static SharedPreferences mSharedPreferences;  
  18.   
  19.     private SkinConfigManager(Context context){  
  20.         mSharedPreferences = context.getSharedPreferences(SKINCONFIG, 0);  
  21.     }  
  22.   
  23.     public synchronized static SkinConfigManager getInstance(Context context) {  
  24.         if (mSkinConfigManager == null) {  
  25.             mSkinConfigManager = new SkinConfigManager(context);  
  26.         }  
  27.         return mSkinConfigManager;  
  28.     }  
  29.   
  30.   
  31.     /** 
  32.      * 设置储存当前选择的皮肤类型值(int 类型值)到 SharedPreferences 
  33.      * @param skinType  皮肤类型 
  34.      */  
  35.     public void setCurSkinType(int skinType){  
  36.         SharedPreferences.Editor editor = mSharedPreferences.edit();  
  37.         editor.putInt(CURSKINTYPEKEY, skinType);  
  38.         editor.commit();  
  39.     }  
  40.   
  41.   
  42.     /** 
  43.      * 获得当前储存在SharedPreferences中的 当前皮肤类型<CURSKINTYPE> 值 
  44.      * @return 
  45.      */  
  46.     public int getCurSkinType(){  
  47.         if (mSharedPreferences != null) {  
  48.             return mSharedPreferences.getInt(CURSKINTYPEKEY, 0);  
  49.         }  
  50.         return 0;  
  51.     }  
  52.   
  53.   
  54.     /** 
  55.      * 获得assets文件夹下面当前皮肤资源所对应的皮肤文件夹名 
  56.      * @return 
  57.      */  
  58.     public String getSkinFileName () {  
  59.         String skinFileName = null;  
  60.         switch (getCurSkinType()){  
  61.             case 0:  
  62.                 // 默认的皮肤类型  
  63.                 break;  
  64.             case 1:  
  65.                 skinFileName = "skin_blue";  
  66.                 break;  
  67.             case 2:  
  68.                 skinFileName = "skin_orange";  
  69.                 break;  
  70.             case 3:  
  71.                 skinFileName = "skin_red";  
  72.                 break;  
  73.         }  
  74.         return skinFileName;  
  75.     }  
  76.   
  77.   
  78.     public SharedPreferences getSkinConfigPreferences () {  
  79.         return mSharedPreferences;  
  80.     }  
  81. }  

2、SkinManager.java   

作用:皮肤资源管理器,用于获取assets文件下不同皮肤类型的图片资源文件

详细代码如下:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package com.ice.skininnerdemo;  
  2.   
  3. import android.content.Context;  
  4. import android.content.res.AssetManager;  
  5. import android.graphics.Bitmap;  
  6. import android.graphics.BitmapFactory;  
  7. import android.graphics.drawable.Drawable;  
  8.   
  9. import java.io.IOException;  
  10. import java.io.InputStream;  
  11.   
  12. /** 
  13.  * Created by ice on 14-10-8. 
  14.  * 皮肤资源管理器<单例> 
  15.  */  
  16. public class SkinManager {  
  17.   
  18.     private static SkinManager mSkinManager;  
  19.     private AssetManager mAssetManager;  
  20.   
  21.     private SkinManager (Context context) {  
  22.         this.mAssetManager = context.getAssets();  
  23.     }  
  24.   
  25.     public synchronized static SkinManager getInstance(Context context){  
  26.   
  27.         if (mSkinManager == null) {  
  28.             mSkinManager = new SkinManager(context);  
  29.         }  
  30.         return mSkinManager;  
  31.     }  
  32.   
  33.   
  34.     /** 
  35.      * 根据皮肤文件名 和 资源文件名 获取Assets 里面的皮肤资源Drawable对象 
  36.      * @param skinFileName  皮肤文件名 
  37.      * @param fileName   资源文件名 
  38.      * @return 
  39.      */  
  40.     public Drawable getSkinDrawable(String skinFileName, String fileName) {  
  41.         Drawable drawable = null;  
  42.         try {  
  43.             InputStream inputStream = mAssetManager.open(skinFileName + "/" + fileName);  
  44.             drawable = Drawable.createFromStream(inputStream, null);  
  45.         } catch (IOException e) {  
  46.             e.printStackTrace();  
  47.         }  
  48.   
  49.         return drawable;  
  50.     }  
  51.   
  52.   
  53.     /** 
  54.      * 根据皮肤文件名 和 资源文件名 获取Assets 里面的皮肤资源Bitmap对象 
  55.      * @param skinFileName 
  56.      * @param fileName 
  57.      * @return 
  58.      */  
  59.     public Bitmap getSkinBitmap(String skinFileName, String fileName){  
  60.         Bitmap image = null;  
  61.         try {  
  62.             InputStream inputStream = mAssetManager.open(skinFileName + "/" + fileName);  
  63.             image = BitmapFactory.decodeStream(inputStream);  
  64.         } catch (IOException e) {  
  65.             e.printStackTrace();  
  66.         }  
  67.   
  68.         return image;  
  69.     }  
  70.   
  71. }  

3、SkinableActivity.java 

作用:换肤Activity抽象类,如果说应用中某个Activiy有换肤的需求,那么就继承SkinableActivity吧!

它主要实现了OnSharedPreferenceChangeListener 监听接口,并且注册了SharedPreferences内容改变的事件监听。

在监听到SharedPreferences发生改变的同时回调changeSkin()抽象方法,该方法由SkinableActivity的子类具体实现UI上皮肤资源的更换。

详细代码如下:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package com.ice.skininnerdemo;  
  2.   
  3. import android.app.Activity;  
  4. import android.content.SharedPreferences;  
  5.   
  6. /** 
  7.  * 换肤Activity抽象类 
  8.  * Created by ice on 14-10-8. 
  9.  */  
  10. public abstract class SkinableActivity extends Activity implements SharedPreferences.OnSharedPreferenceChangeListener{  
  11.   
  12.     @Override  
  13.     protected void onStart() {  
  14.         super.onStart();  
  15.         initSkin();  
  16.     }  
  17.   
  18.   
  19.     /** 
  20.      *  初始化皮肤 
  21.      */  
  22.     private void initSkin() {  
  23.         changeSkin();  
  24.         // 注册监听,监听换肤的通知  
  25.         SkinConfigManager.getInstance(this).getSkinConfigPreferences()  
  26.                 .registerOnSharedPreferenceChangeListener(this);  
  27.   
  28.     }  
  29.   
  30.   
  31.     /** 
  32.      * sharedPreferences 内容发生改变时触发 
  33.      * @param sharedPreferences 
  34.      * @param key sharedPreferences中的key值 
  35.      */  
  36.     @Override  
  37.     public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {  
  38.         if (SkinConfigManager.CURSKINTYPEKEY.equals(key)) {  
  39.             changeSkin();  
  40.         }  
  41.     }  
  42.   
  43.   
  44.     @Override  
  45.     protected void onStop() {  
  46.         super.onStop();  
  47.         SkinConfigManager.getInstance(this).getSkinConfigPreferences()  
  48.                 .unregisterOnSharedPreferenceChangeListener(this);  
  49.     }  
  50.   
  51.   
  52.     /** 
  53.      * 更改设置皮肤,SkinableActivity子类必须要实现该方法 完成换肤过程 
  54.      */  
  55.     protected abstract void changeSkin();  
  56.   
  57. }  

4、SkinSettingActivity.java

作用:皮肤设置Activity,继承了SkinableActivity,实现了changeSkin()抽象方法,完成了皮肤设置UI上的皮肤更换。

(应用中其他需要换肤的Activity类似、主要在changeSkin()方法中实现界面的换肤需求)

详细代码如下:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package com.ice.skininnerdemo;  
  2.   
  3. import android.graphics.drawable.Drawable;  
  4. import android.os.Bundle;  
  5. import android.util.Log;  
  6. import android.view.View;  
  7. import android.widget.AdapterView;  
  8. import android.widget.GridView;  
  9. import android.widget.SimpleAdapter;  
  10. import android.widget.TextView;  
  11. import java.util.ArrayList;  
  12. import java.util.HashMap;  
  13. import java.util.List;  
  14.   
  15. /** 
  16.  * 皮肤设置Activity 
  17.  * Created by ice on 14-10-10. 
  18.  */  
  19. public class SkinSettingActivity extends SkinableActivity{  
  20.   
  21.     private static final String TAG = "SkinSettingActivity";  
  22.     private GridView gv_skin_type;  
  23.     private TextView tv_skin_cur;  
  24.     private TextView tv_title_skin_setting;  
  25.   
  26.     private int[] skinTypeImage = new int[]{  
  27.             R.drawable.overview_skin_default, R.drawable.overview_skin_blue,  
  28.             R.drawable.overview_skin_orange, R.drawable.overview_skin_red  
  29.     };  
  30.   
  31.     private int[] skinTypeName = new int[]{  
  32.             R.string.skin_default, R.string.skin_blue,  
  33.             R.string.skin_orange, R.string.skin_red  
  34.     };  
  35.   
  36.     @Override  
  37.     protected void onCreate(Bundle savedInstanceState) {  
  38.         super.onCreate(savedInstanceState);  
  39.         setContentView(R.layout.activity_skin_setting);  
  40.         initView();  
  41.         bindEvent();  
  42.     }  
  43.   
  44.   
  45.     private void initView() {  
  46.         tv_title_skin_setting = (TextView)findViewById(R.id.tv_title_skin_setting);  
  47.         tv_skin_cur = (TextView)findViewById(R.id.tv_skin_cur);  
  48.         gv_skin_type = (GridView)findViewById(R.id.gv_skin_type);  
  49.   
  50.         setGridViewAdapter(gv_skin_type);  
  51.     }  
  52.   
  53.   
  54.     private void setGridViewAdapter(GridView mGridView) {  
  55.         List<HashMap<String, Object>> data = new ArrayList<HashMap<String, Object>>();  
  56.         int length = skinTypeImage.length;  
  57.         for(int i=0; i<length; i++){  
  58.             HashMap<String,Object> map = new HashMap<String, Object>();  
  59.             map.put("skinTypeImage", skinTypeImage[i]);  
  60.             map.put("skinTypeName", getString(skinTypeName[i]));  
  61.             data.add(map);  
  62.         }  
  63.   
  64.         SimpleAdapter simpleAdapter = new SimpleAdapter(  
  65.                 this,  
  66.                 data,  
  67.                 R.layout.traffic_item,  
  68.                 new String[]{"skinTypeImage""skinTypeName"},  
  69.                 new int[]{R.id.iv_traffic, R.id.tv_trafficName});  
  70.   
  71.         mGridView.setAdapter(simpleAdapter);  
  72.     }  
  73.   
  74.   
  75.     private void bindEvent() {  
  76.         gv_skin_type.setOnItemClickListener(new AdapterView.OnItemClickListener() {  
  77.             @Override  
  78.             public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {  
  79.                 tv_skin_cur.setText(skinTypeName[i]);  
  80.                 // 将当前选择的皮肤对应的序号 储存到 SharedPreferences 中  
  81.                 SkinConfigManager.getInstance(SkinSettingActivity.this).setCurSkinType(i);  
  82.             }  
  83.         });  
  84.     }  
  85.   
  86.   
  87.     @Override  
  88.     protected void changeSkin() {  
  89.         SkinConfigManager mSkinConfigManager = SkinConfigManager.getInstance(SkinSettingActivity.this);  
  90.         String skinFileName = mSkinConfigManager.getSkinFileName();  
  91.         Log.d(TAG, "changeSkin() 被执行 / skinFileName: " + skinFileName);  
  92.   
  93.         // 获取当前正在使用的皮肤序号  
  94.         int skinType = mSkinConfigManager.getCurSkinType();  
  95.         tv_skin_cur.setText(skinTypeName[skinType]);  
  96.   
  97.         if(skinFileName != null){  
  98.             Drawable drawable = SkinManager.getInstance(this).getSkinDrawable(skinFileName, "bg_title.9.png");  
  99.             tv_title_skin_setting.setBackground(drawable);  
  100.         } else {  
  101.             tv_title_skin_setting.setBackgroundResource(R.drawable.bg_title);  
  102.         }  
  103.     }  
  104.   
  105. }  


-- -- ok、本篇demo实现换肤效果的主要代码、设计思路于此!小吕其实还想过另外一种皮肤资源的配置方式,

大体想法如下:

1、在assets文件下下面新建一个皮肤资源的配置文件 如:skin.properties 或是 skin_configure.xml

2、所有的皮肤资源(图片)将会放在res/drawable/下面,而什么皮肤类型所对应的皮肤资源图片将会在1中的skin.properties 或是 skin_configure.xml中 通过配置的方式引用。


当然  这只是小吕目前的一个初步想法及设计思想、如果 看到这里的您 如果还有其他实现换肤的设计思想、还希望大气的给小吕留言、学习、和交流。


补充内容:本demo中 有关于获取assets文件中的.9格式图片。

                   关于获取assets下面的.9格式图片问题,这里是很有趣的,

                   该demo中assets下的.9格式图片 都是先使用 AAPT 命令编译处理后的,及被Android系统编译过的。

                   那为什么要这样做呢?大家可以先自己研究下 或是 在网上搜索答案、小吕后面有时间将会整理成博客。


最后附上本篇demo的代码<免下载积分>: http://download.csdn.net/detail/l416112167/8027581

0 0
原创粉丝点击