Android 打造自己的个性化应用(二):应用程序内置资源实现换肤功能

时间:2022-10-30 20:38:57

通过应用程序内置资源实现换肤,典型的应用为QQ空间中换肤的实现. 应用场景为: 应用一般不大,且页面较少,风格相对简单,一般只用实现部分资源或者只用实现背景的更换.

此种换肤方式实现的思路:

1. 把几套皮肤放在res/drawable目录里,然后用SharedPreferences来记录当前皮肤的资源id.然后在程序启动时加载Activity背景。

2. 主要的实现在皮肤管理器SkinManager类中. 将皮肤资源的ID加入集合中. 由该类同一调度皮肤更换,如初始化皮肤,获取当前皮肤符号以及具体的对应资源的更换皮肤.

接下来看一下效果图:

Android 打造自己的个性化应用(二):应用程序内置资源实现换肤功能

Android 打造自己的个性化应用(二):应用程序内置资源实现换肤功能

内置皮肤的实现相对比较简单,下面直接上代码:

AndroidMainfest.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3. package="com.tony.skindemo"
  4. android:versionCode="1"
  5. android:versionName="1.0" >
  6. <uses-sdk android:minSdkVersion="8" />
  7. <application
  8. android:icon="@drawable/ic_launcher"
  9. android:label="@string/app_name" >
  10. <activity
  11. android:label="@string/app_name"
  12. android:name="com.tony.skindemo.SkinDemoActivity" >
  13. <intent-filter >
  14. <action android:name="android.intent.action.MAIN" />
  15. <category android:name="android.intent.category.LAUNCHER" />
  16. </intent-filter>
  17. </activity>
  18. </application>
  19. </manifest>

布局文件:

main.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="fill_parent"
  4. android:layout_height="fill_parent"
  5. android:orientation="vertical" >
  6. <TextView
  7. android:textColor="#ff00ff"
  8. android:text="程序皮肤更换"
  9. android:layout_width="fill_parent"
  10. android:layout_height="wrap_content" />
  11. <RadioGroup
  12. android:id="@+id/skin_options"
  13. android:layout_width="fill_parent"
  14. android:layout_height="wrap_content"
  15. >
  16. <RadioButton
  17. android:layout_weight="1"
  18. android:id="@+id/radioButton1"
  19. android:layout_width="wrap_content"
  20. android:layout_height="wrap_content"
  21. android:text="风格1" />
  22. <RadioButton
  23. android:layout_weight="1"
  24. android:id="@+id/radioButton2"
  25. android:layout_width="wrap_content"
  26. android:layout_height="wrap_content"
  27. android:text="风格2" />
  28. <RadioButton
  29. android:layout_weight="1"
  30. android:id="@+id/radioButton3"
  31. android:layout_width="wrap_content"
  32. android:layout_height="wrap_content"
  33. android:text="风格3" />
  34. <RadioButton
  35. android:layout_weight="1"
  36. android:id="@+id/radioButton4"
  37. android:layout_width="wrap_content"
  38. android:layout_height="wrap_content"
  39. android:text="风格4" />
  40. <RadioButton
  41. android:layout_weight="1"
  42. android:id="@+id/radioButton5"
  43. android:layout_width="wrap_content"
  44. android:layout_height="wrap_content"
  45. android:text="风格5" />
  46. </RadioGroup>
  47. </LinearLayout>

程序主Activity

  1. package com.tony.skindemo;
  2. import android.app.Activity;
  3. import android.os.Bundle;
  4. import android.view.MotionEvent;
  5. import android.view.Window;
  6. import android.view.WindowManager;
  7. import android.widget.RadioButton;
  8. import android.widget.RadioGroup;
  9. import android.widget.RadioGroup.OnCheckedChangeListener;
  10. public class SkinDemoActivity extends Activity {
  11. private SkinSettingManager mSettingManager;
  12. private RadioButton radioButton1;
  13. private RadioButton radioButton2;
  14. private RadioButton radioButton3;
  15. private RadioButton radioButton4;
  16. private RadioButton radioButton5;
  17. @Override
  18. public void onCreate(Bundle savedInstanceState) {
  19. super.onCreate(savedInstanceState);
  20. // 取消标题栏
  21. requestWindowFeature(Window.FEATURE_NO_TITLE);
  22. // 完成窗体的全屏显示 // 取消掉状态栏
  23. getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
  24. WindowManager.LayoutParams.FLAG_FULLSCREEN);
  25. setContentView(R.layout.main);
  26. // 初始化皮肤
  27. mSettingManager = new SkinSettingManager(this);
  28. mSettingManager.initSkins();
  29. //通过单选按钮设置皮肤(可自定义更换的方式,如导航栏,也可以加上预览功能,此处不再实现)
  30. radioButton1 = (RadioButton) findViewById(R.id.radioButton1);
  31. radioButton2 = (RadioButton) findViewById(R.id.radioButton2);
  32. radioButton3 = (RadioButton) findViewById(R.id.radioButton3);
  33. radioButton4 = (RadioButton) findViewById(R.id.radioButton4);
  34. radioButton5 = (RadioButton) findViewById(R.id.radioButton5);
  35. RadioGroup radioGroup = (RadioGroup) findViewById(R.id.skin_options);
  36. radioGroup.setOnCheckedChangeListener(new OnCheckedChangeListener() {
  37. @Override
  38. public void onCheckedChanged(RadioGroup group, int checkedId) {
  39. switch (checkedId) {
  40. case R.id.radioButton1:
  41. mSettingManager.changeSkin(1);
  42. break;
  43. case R.id.radioButton2:
  44. mSettingManager.changeSkin(2);
  45. break;
  46. case R.id.radioButton3:
  47. mSettingManager.changeSkin(3);
  48. break;
  49. case R.id.radioButton4:
  50. mSettingManager.changeSkin(4);
  51. break;
  52. case R.id.radioButton5:
  53. mSettingManager.changeSkin(5);
  54. break;
  55. default:
  56. break;
  57. }
  58. }
  59. });
  60. }
  61. // 这里为了简单实现,实现换肤
  62. public boolean onTouchEvent(MotionEvent event) {
  63. mSettingManager.toggleSkins();
  64. return super.onTouchEvent(event);
  65. }
  66. }
    1. <pre name="code" class="java"></pre><pre></pre><p></p><pre></pre>皮肤管理器:<p></p><p></p><pre name="code" class="java">package com.tony.skindemo;
    2. import android.app.Activity;
    3. import android.content.SharedPreferences;
    4. /**
    5. * 皮肤管理器
    6. * @author tony
    7. *
    8. */
    9. public class SkinSettingManager {
    10. public final static String SKIN_PREF = "skinSetting";
    11. public SharedPreferences skinSettingPreference;
    12. private int[] skinResources = { R.drawable.default_wallpaper,
    13. R.drawable.wallpaper_c,R.drawable.wallpaper_d,R.drawable.wallpaper_f,
    14. R.drawable.wallpaper_g
    15. };
    16. private Activity mActivity;
    17. public SkinSettingManager(Activity activity) {
    18. this.mActivity = activity;
    19. skinSettingPreference = mActivity.getSharedPreferences(SKIN_PREF, 3);
    20. }
    21. /**
    22. * 获取当前程序的皮肤序号
    23. *
    24. * @return
    25. */
    26. public int getSkinType() {
    27. String key = "skin_type";
    28. return skinSettingPreference.getInt(key, 0);
    29. }
    30. /**
    31. * 把皮肤序号写到全局设置里去
    32. *
    33. * @param j
    34. */
    35. public void setSkinType(int j) {
    36. SharedPreferences.Editor editor = skinSettingPreference.edit();
    37. String key  = "skin_type";
    38. editor.putInt(key, j);
    39. editor.commit();
    40. }
    41. /**
    42. * 获取当前皮肤的背景图资源id
    43. *
    44. * @return
    45. */
    46. public int getCurrentSkinRes() {
    47. int skinLen = skinResources.length;
    48. int getSkinLen = getSkinType();
    49. if(getSkinLen >= skinLen){
    50. getSkinLen = 0;
    51. }
    52. return skinResources[getSkinLen];
    53. }
    54. public void toggleSkins(){
    55. int skinType = getSkinType();
    56. if(skinType == skinResources.length - 1){
    57. skinType = 0;
    58. }else{
    59. skinType ++;
    60. }
    61. setSkinType(skinType);
    62. mActivity.getWindow().setBackgroundDrawable(null);
    63. try {
    64. mActivity.getWindow().setBackgroundDrawableResource(getCurrentSkinRes());
    65. } catch (Throwable e) {
    66. e.printStackTrace();
    67. }
    68. }
    69. /**
    70. * 用于初始化皮肤
    71. */
    72. public void initSkins(){
    73. mActivity.getWindow().setBackgroundDrawableResource(getCurrentSkinRes());
    74. }
    75. /**
    76. * 随即切换一个背景皮肤
    77. */
    78. public void changeSkin(int id) {
    79. setSkinType(id);
    80. mActivity.getWindow().setBackgroundDrawable(null);
    81. try {
    82. mActivity.getWindow().setBackgroundDrawableResource(getCurrentSkinRes());
    83. } catch (Throwable e) {
    84. e.printStackTrace();
    85. }
    86. }
    87. }
    88. </pre><br><p></p><p>就这样,通过程序内置皮肤的基本功能完成了.</p><p>若想在自己的应用中实现,仍需注意以下几点(实现起来并不复杂,此处不再写具体实现):<br></p><p>1.  实现多个activity的更换皮肤. 需要利用自定义MyApplication类,继承自Application. 并加入activity的集合属性.用于存储应用所有的activity<br></p><p>    修改SkinManager,在更换皮肤时,从application中取出该集合,进行遍历并更换皮肤</p><p><br></p><p>2. 可以优化用户体验,通过导航栏方式进入更换皮肤界面,并可以加入预览功能,当确定修改配置后,才完成更换皮肤功能.</p><p>3. 加入style.theme等资源,实现更加复杂的皮肤更换. 具体实现同更换背景.<br></p><p><br></p><p><br></p><p><br></p><p><br></p>