編輯:關於Android編程
在上篇中 主要有學習到皮膚資源內置到應用程序中 的方式實現換膚的 基本思路,本篇將繼續以上篇的思路學習 皮膚資源內置的方式實現換膚效果、但本篇側重於應用中換膚功能的代碼設計實現上!切換的皮膚資源位於assets下不同的皮膚資源文件夾中。
本篇demo程序的代碼結構如下:
本篇實現換膚功能的代碼設計 UML類圖如下:
本篇demo的換膚效果如下:<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+PGltZyBzcmM9"/uploadfile/Collfiles/20141012/2014101209135434.png" width="360" height="650" alt="\">
主要的實現代碼在於:
1、SkinConfigManager.java
作用:皮膚配置管理,封裝了SharedPreferences對選擇皮膚的序號儲存、以及根據皮膚類型鎖定assets下的皮膚資源。 詳細代碼如下:
package com.ice.skininnerdemo; import android.content.Context; import android.content.SharedPreferences; /** * 皮膚配置管理<單例> * 封裝了 SharedPreferences 對象的儲存操作 * Created by ice on 14-10-9. */ public class SkinConfigManager { private static SkinConfigManager mSkinConfigManager; public static final String SKINCONFIG = "SkinConfig"; public static final String CURSKINTYPEKEY = "curSkinTypeKey"; private static SharedPreferences mSharedPreferences; private SkinConfigManager(Context context){ mSharedPreferences = context.getSharedPreferences(SKINCONFIG, 0); } public synchronized static SkinConfigManager getInstance(Context context) { if (mSkinConfigManager == null) { mSkinConfigManager = new SkinConfigManager(context); } return mSkinConfigManager; } /** * 設置儲存當前選擇的皮膚類型值(int 類型值)到 SharedPreferences * @param skinType 皮膚類型 */ public void setCurSkinType(int skinType){ SharedPreferences.Editor editor = mSharedPreferences.edit(); editor.putInt(CURSKINTYPEKEY, skinType); editor.commit(); } /** * 獲得當前儲存在SharedPreferences中的 當前皮膚類型值 * @return */ public int getCurSkinType(){ if (mSharedPreferences != null) { return mSharedPreferences.getInt(CURSKINTYPEKEY, 0); } return 0; } /** * 獲得assets文件夾下面當前皮膚資源所對應的皮膚文件夾名 * @return */ public String getSkinFileName () { String skinFileName = null; switch (getCurSkinType()){ case 0: // 默認的皮膚類型 break; case 1: skinFileName = "skin_blue"; break; case 2: skinFileName = "skin_orange"; break; case 3: skinFileName = "skin_red"; break; } return skinFileName; } public SharedPreferences getSkinConfigPreferences () { return mSharedPreferences; } }
作用:皮膚資源管理器,用於獲取assets文件下不同皮膚類型的圖片資源文件
詳細代碼如下:
package com.ice.skininnerdemo; import android.content.Context; import android.content.res.AssetManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.drawable.Drawable; import java.io.IOException; import java.io.InputStream; /** * Created by ice on 14-10-8. * 皮膚資源管理器<單例> */ public class SkinManager { private static SkinManager mSkinManager; private AssetManager mAssetManager; private SkinManager (Context context) { this.mAssetManager = context.getAssets(); } public synchronized static SkinManager getInstance(Context context){ if (mSkinManager == null) { mSkinManager = new SkinManager(context); } return mSkinManager; } /** * 根據皮膚文件名 和 資源文件名 獲取Assets 裡面的皮膚資源Drawable對象 * @param skinFileName 皮膚文件名 * @param fileName 資源文件名 * @return */ public Drawable getSkinDrawable(String skinFileName, String fileName) { Drawable drawable = null; try { InputStream inputStream = mAssetManager.open(skinFileName + "/" + fileName); drawable = Drawable.createFromStream(inputStream, null); } catch (IOException e) { e.printStackTrace(); } return drawable; } /** * 根據皮膚文件名 和 資源文件名 獲取Assets 裡面的皮膚資源Bitmap對象 * @param skinFileName * @param fileName * @return */ public Bitmap getSkinBitmap(String skinFileName, String fileName){ Bitmap image = null; try { InputStream inputStream = mAssetManager.open(skinFileName + "/" + fileName); image = BitmapFactory.decodeStream(inputStream); } catch (IOException e) { e.printStackTrace(); } return image; } }
作用:換膚Activity抽象類,如果說應用中某個Activiy有換膚的需求,那麼就繼承SkinableActivity吧!
它主要實現了OnSharedPreferenceChangeListener 監聽接口,並且注冊了SharedPreferences內容改變的事件監聽。
在監聽到SharedPreferences發生改變的同時回調changeSkin()抽象方法,該方法由SkinableActivity的子類具體實現UI上皮膚資源的更換。
詳細代碼如下:
package com.ice.skininnerdemo; import android.app.Activity; import android.content.SharedPreferences; /** * 換膚Activity抽象類 * Created by ice on 14-10-8. */ public abstract class SkinableActivity extends Activity implements SharedPreferences.OnSharedPreferenceChangeListener{ @Override protected void onStart() { super.onStart(); initSkin(); } /** * 初始化皮膚 */ private void initSkin() { changeSkin(); // 注冊監聽,監聽換膚的通知 SkinConfigManager.getInstance(this).getSkinConfigPreferences() .registerOnSharedPreferenceChangeListener(this); } /** * sharedPreferences 內容發生改變時觸發 * @param sharedPreferences * @param key sharedPreferences中的key值 */ @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { if (SkinConfigManager.CURSKINTYPEKEY.equals(key)) { changeSkin(); } } @Override protected void onStop() { super.onStop(); SkinConfigManager.getInstance(this).getSkinConfigPreferences() .unregisterOnSharedPreferenceChangeListener(this); } /** * 更改設置皮膚,SkinableActivity子類必須要實現該方法 完成換膚過程 */ protected abstract void changeSkin(); }
作用:皮膚設置Activity,繼承了SkinableActivity,實現了changeSkin()抽象方法,完成了皮膚設置UI上的皮膚更換。
(應用中其他需要換膚的Activity類似、主要在changeSkin()方法中實現界面的換膚需求)
詳細代碼如下:
package com.ice.skininnerdemo; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.AdapterView; import android.widget.GridView; import android.widget.SimpleAdapter; import android.widget.TextView; import java.util.ArrayList; import java.util.HashMap; import java.util.List; /** * 皮膚設置Activity * Created by ice on 14-10-10. */ public class SkinSettingActivity extends SkinableActivity{ private static final String TAG = "SkinSettingActivity"; private GridView gv_skin_type; private TextView tv_skin_cur; private TextView tv_title_skin_setting; private int[] skinTypeImage = new int[]{ R.drawable.overview_skin_default, R.drawable.overview_skin_blue, R.drawable.overview_skin_orange, R.drawable.overview_skin_red }; private int[] skinTypeName = new int[]{ R.string.skin_default, R.string.skin_blue, R.string.skin_orange, R.string.skin_red }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_skin_setting); initView(); bindEvent(); } private void initView() { tv_title_skin_setting = (TextView)findViewById(R.id.tv_title_skin_setting); tv_skin_cur = (TextView)findViewById(R.id.tv_skin_cur); gv_skin_type = (GridView)findViewById(R.id.gv_skin_type); setGridViewAdapter(gv_skin_type); } private void setGridViewAdapter(GridView mGridView) { List> data = new ArrayList >(); int length = skinTypeImage.length; for(int i=0; i map = new HashMap (); map.put("skinTypeImage", skinTypeImage[i]); map.put("skinTypeName", getString(skinTypeName[i])); data.add(map); } SimpleAdapter simpleAdapter = new SimpleAdapter( this, data, R.layout.traffic_item, new String[]{"skinTypeImage", "skinTypeName"}, new int[]{R.id.iv_traffic, R.id.tv_trafficName}); mGridView.setAdapter(simpleAdapter); } private void bindEvent() { gv_skin_type.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView> adapterView, View view, int i, long l) { tv_skin_cur.setText(skinTypeName[i]); // 將當前選擇的皮膚對應的序號 儲存到 SharedPreferences 中 SkinConfigManager.getInstance(SkinSettingActivity.this).setCurSkinType(i); } }); } @Override protected void changeSkin() { SkinConfigManager mSkinConfigManager = SkinConfigManager.getInstance(SkinSettingActivity.this); String skinFileName = mSkinConfigManager.getSkinFileName(); Log.d(TAG, "changeSkin() 被執行 / skinFileName: " + skinFileName); // 獲取當前正在使用的皮膚序號 int skinType = mSkinConfigManager.getCurSkinType(); tv_skin_cur.setText(skinTypeName[skinType]); if(skinFileName != null){ Drawable drawable = SkinManager.getInstance(this).getSkinDrawable(skinFileName, "bg_title.9.png"); tv_title_skin_setting.setBackground(drawable); } else { tv_title_skin_setting.setBackgroundResource(R.drawable.bg_title); } } }
-- -- 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
-----------------
下篇 小呂將會學習與介紹第二種實現方式: [皮膚資源與應用程序分離]
本文講述了Android模擬器中安裝apk的方法。分享給大家供大家參考,具體如下:第一步:在Eclipse中啟動模擬器。第二步:打開doc命名窗口,轉到你android
一、前言上篇說清楚了Unity和Android調用的方式,但很多實際接入的部分沒有講的很詳細,因為重頭在這篇,會詳細講述具體接入Android SDK的方式,和怎麼去做一
如果listitem裡面包括button或者checkbox等控件,默認情況下listitem會失去焦點,導致無法響應item的事件,最常用的解決辦法是在listitem
前段時間閱讀了RxJava1.x的源碼,剛好RxJava2.x也發布了RC版,為了迎接10月底的正式版,趁熱打鐵,本篇將對RxJava2.x進行一個簡單的剖析。Obser