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

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

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

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

接下来看一下效果图:

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

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>

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

  1. 一种简单的实现:Android一键换肤功能

    现在的APP开发,通常会提供APP的换肤功能,网上流传的换肤代码和实现手段过于复杂,我把原作者的代码重新整理抽取出来,转换成Eclipse项目,重新整理成正确.可直接运行的项目. 代码运行结果如图. ...

  2. Android一键换肤功能:一种简单的实现

     Android一键换肤功能:一种简单的实现 现在的APP开发,通常会提供APP的换肤功能,网上流传的换肤代码和实现手段过于复杂,这里有一个开源实现,我找了一大堆,发现这个项目相对较为简洁:htt ...

  3. Android 打造自己的个性化应用(一):应用程序换肤主流方式的分析与概述

    Android平台api没有特意为换肤提供一套简便的机制,这可能是外国的软件更注重功能和易用,不流行换肤.系统不提供直接支持,只能自行研究. 换肤,可以认为是动态替换资源(文字.颜色.字体大小.图片. ...

  4. Android 换肤功能的实现(Apk插件方式)

    一.概述 由于Android 没有提供一套统一的换肤机制,我猜可能是因为国外更注重功能和体验的原因 所以国内如果要做一个漂亮的换肤方案,需要自己去实现. 目前换肤的方法大概有三种方案: (1)把皮肤资 ...

  5. Unit05: JavaScript对象概述 、 常用内置对象一 、 常用内置对象二 、 常用内置对象三

    Unit05: JavaScript对象概述 . 常用内置对象一 . 常用内置对象二 . 常用内置对象三 常用内置对象使用演示: <!DOCTYPE html> <html> ...

  6. Flex AIR应用换肤功能(Android和IOS)

    说明 换肤功能,即将整个应用的皮肤都进行更换,其实质,是动态加载swf文件的过程,而这些swf文件则有css文件编译而来. 关于换肤功能,在android和ios系统的实现方式是不同的.主要原因,是因 ...

  7. Android QMUI实战:实现APP换肤功能,并自动适配手机深色模式

    Android换肤功能已不是什么新鲜事了,市面上有很多第三方的换肤库和实现方案. 之所以选择腾讯的QMUI库来演示APP的换肤功能,主要原因: 1.换肤功能的实现过程较简单.容易理解: 2.能轻松适配 ...

  8. Android 打造自己的个性化应用(四):仿墨迹天气实现-->自定义扩展名的zip格式的皮肤

    在这里谈一下墨迹天气的换肤实现方式,不过首先声明我只是通过反编译以及参考了一些网上其他资料的方式推测出的换肤原理, 在这里只供参考. 若大家有更好的方式, 欢迎交流. 墨迹天气下载的皮肤就是一个zip ...

  9. Android 打造自己的个性化应用(三):应用程序的插件化

    在android的项目开发中,都会遇到后期功能拓展增强与主程序代码变更的现实矛盾,也就是程序的灵活度. 由于linux平台的安全机制,再加上dalvik的特殊机制,各种权限壁垒,使得开发一个灵活多变的 ...

随机推荐

  1. SVG 路径(path)

    本文转自:https://developer.mozilla.org/zh-CN/docs/Web/SVG/Tutorial/Paths <path>元素是SVG基本形状中最强大的一个,它 ...

  2. K3整理

    当金蝶提示“该模块使用已超过正式版许可最大数!”,需要解决的办法是: 打开K3的“帐套管理”系统,“系统(S)”菜单-“系统使用状况(D)”-系统使用状态窗口,然后点击橡皮擦 删除即可了.

  3. MVC4过滤器(转)

    先来看看一个例子演示过滤器有什么用: public class AdminController : Controller { // ... instance variables and constru ...

  4. REST 相关

    REST 相关 REST:Representational State Transfer,表现层状态转化(出现在阮一峰的博客 理解RESTful架构 中,但是,很明显,Representational ...

  5. 安卓状态栏通知Status Bar Notification

    安卓系统通知用户三种方式: 1.Toast Notification 2.Dialog Notification 3.Status Bar Notification Status Bar Notifi ...

  6. AngularJs练习Demo3

    @{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport&quo ...

  7. Java 装箱、拆箱 包装器

    先说java的基本数据类型.java基本数据类型:byte.short.int.long.float.double.char.boolean 基本数据类型的自动装箱(autoboxing).拆箱(un ...

  8. ios面试汇总

    http://www.360doc.com/content/15/0707/01/26281448_483232245.shtml

  9. arry()数组的理解及api的使用(一)

    我们想要了解数组,首先就要先要了解到什么是数据结构,所谓的数据结构就是把数据与数据见的关系按照特定的结构来保存.设计合理的数据结构是解决问题的前提.了解了数据结构后我们下面来数组的定义:数组(arra ...

  10. OpenGL ES 2.0 光照

    基本的光照 光照分成了3种组成元素(3个通道):环境光.散射光以及镜面光. 材质的反射系数实际指的就是物体被照射处的颜色,散射光强度指的是散射光中的RGB(红.绿.蓝)3个色彩通道的强度. 环境光 指 ...