动态换肤在很多android应用中都有使用,用户根据自己的喜好设置皮肤主题,可以增强用户使用应用的舒适度。

Android换肤可以分为很多种,它们从使用方式,用户体验以及项目框架设计上体现了明显的差异。

接下来几篇文章分别讲解其中比较主流的换肤方式。

应用内置皮肤实现动态切换在技术上是最容易实现的,但有很多局限性,比如不能在使用过程中增减皮肤,除非升级应用,扩展性很弱;如果需要设置皮肤的位置很多,编码起来比较麻烦。主要是使用 SharedPreferences记录当前设置的皮肤序号,然后加载这套皮肤的所有资源,在每个activity中有一个setSkin()的方法设置皮肤。

博主的个人项目好记单词 中的换肤功能就是使用这个方案,感兴趣可以下载看一看,效果还不错。

实现:

  • 确定需要换肤的地方

    首先要确定应用中那些界面需要换肤,他们有什么共性?比如天天动听,一套以蓝色为基调的皮肤,所有的界面title应该是蓝色的,所有的按钮也是蓝色系列的…,这样就可以确定一套皮肤需要哪些颜色以及资源文件。

  • 确定一套皮肤需要的资源(其余皮肤按照第一套皮肤模板做)

    比如首页,四个模块,其中 本地音乐最近播放 的颜色是一样的,这里需要两个颜色值(正常和按下状态),歌曲下载MV下载 的颜色是一样的,这里也需要两个颜色值,每个界面的标题背景色相同,然后一些按钮也需要两个颜色值;综合起来就需要7个色值,在color.xml文件中定义好它们,然后再drawable目录定义好选择器。

    (以下是Demo中的代码片段,真实项目开发中只需要按照这个步骤模板做就行)

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <resources>
  3. <!-- 皮肤1 主色调 天蓝#4AC2E3-->
  4. <!-- 界面背景 -->
  5. <color name="pf1_activity_bg_color1">#46BAE3</color>
  6. <color name="pf1_activity_bg_color2">#63f3e3</color>
  7. <!-- item选择器 -->
  8. <color name="pf1_main_item_bg1">#50CEE3</color>
  9. <color name="pf1_main_item_bg2">#4AC2E3</color>
  10. <!-- 字体颜色黑色 -->
  11. <color name="pf1_text_color">#000000</color>
  12. <!-- 皮肤2 主色调 草绿#53CAC3-->
  13. <!-- 界面背景 -->
  14. <color name="pf2_activity_bg_color1">#53CAC3</color>
  15. <color name="pf2_activity_bg_color2">#73FFB9</color>
  16. <!-- item选择器 -->
  17. <color name="pf2_main_item_bg1">#62E3BE</color>
  18. <color name="pf2_main_item_bg2">#5BD7C0</color>
  19. <!-- 字体颜色白色 -->
  20. <color name="pf2_text_color">#ffffff</color>
  21. </resources>

  • 编写SkinUtil资源加载类
  1. public class SkinUtil {
  2. private SharedPreferences sp;
  3. //KEY
  4. private final String KEY_PF = "skin"; //记录当前皮肤
  5. //VALUE
  6. public static final int VALUE_SKIN_1 = 1; //天蓝
  7. public static final int VALUE_SKIN_2 = 2; //草绿
  8. //当前皮肤资源ID
  9. public int activity_bg;
  10. public int item_bg;
  11. public int textColor;
  12. public SkinUtil(Context context){
  13. sp = context.getSharedPreferences("mySkin", Context.MODE_PRIVATE);
  14. loadPf();
  15. }
  16. /**
  17. * 设置使用那一套皮肤
  18. * @param witch
  19. */
  20. public void setSkin(int witch){
  21. sp.edit().putInt(KEY_PF, witch).commit();
  22. loadPf();
  23. }
  24. /**
  25. * 加载皮肤资源
  26. */
  27. public void loadPf(){
  28. //默认第一套皮肤(如果没有设置过)
  29. int pf_num = sp.getInt(KEY_PF, VALUE_SKIN_1);
  30. switch (pf_num) {
  31. case VALUE_SKIN_1:
  32. setSkin1();
  33. break;
  34. case VALUE_SKIN_2:
  35. setSkin2();
  36. break;
  37. }
  38. }
  39. //加载第一套皮肤资源ID
  40. private void setSkin1() {
  41. activity_bg = R.drawable.skin1_activity_bg;
  42. item_bg = R.drawable.skin1_main_item_bg;
  43. textColor = R.color.pf1_text_color;
  44. }
  45. //加载第二套皮肤资源ID
  46. private void setSkin2() {
  47. activity_bg = R.drawable.skin2_activity_bg;
  48. item_bg = R.drawable.skin2_main_item_bg;
  49. textColor = R.color.pf2_text_color;
  50. }
  51. }
  • 使用皮肤

    在Application中初始化皮肤工具类
  1. public class MyApplication extends Application {
  2. public static SkinUtil skin;
  3. @Override
  4. public void onCreate() {
  5. super.onCreate();
  6. skin = new SkinUtil(getApplicationContext());
  7. }
  8. }

定义BaseActivity

  1. public abstract class BaseActivity extends Activity implements OnClickListener {
  2. @Override
  3. protected void onCreate(Bundle savedInstanceState) {
  4. super.onCreate(savedInstanceState);
  5. initView();
  6. setSkin();
  7. }
  8. protected abstract void initView();
  9. protected abstract void setSkin();
  10. }

实现setSkin()方法设置皮肤

  1. public class MainActivity extends BaseActivity{
  2. private LinearLayout ll_bg;
  3. private TextView tv_skin1, tv_skin2;
  4. @Override
  5. protected void initView() {
  6. setContentView(R.layout.activity_main);
  7. ll_bg = (LinearLayout) findViewById(R.id.ll_bg);
  8. ...
  9. }
  10. protected void setSkin() {
  11. ll_bg.setBackgroundResource(MyApplication.skin.activity_bg);
  12. ...
  13. }
  14. @Override
  15. public void onClick(View v) {
  16. switch (v.getId()) {
  17. case R.id.tv_skin1:
  18. //使用第一套皮肤
  19. MyApplication.skin.setSkin(SkinUtil.VALUE_SKIN_1);
  20. setSkin();
  21. break;
  22. case R.id.tv_skin2:
  23. //使用第二套皮肤
  24. MyApplication.skin.setSkin(SkinUtil.VALUE_SKIN_2);
  25. setSkin();
  26. break;
  27. ...
  28. }
  29. }
  30. }

源码下载

https://github.com/openXu/SkinChange1

Android动态换肤(一、应用内置多套皮肤)的更多相关文章

  1. Android动态换肤(二、apk免安装插件方式)

    在上一篇文章Android动态换肤(一.应用内置多套皮肤)中,我们了解到,动态换肤无非就是调用view的setBackgroundResource(R.drawable.id)等方法设置控件的背景或者 ...

  2. Android动态换肤(三、安装主题apk方式)

    相比之前免安装的方式,这种方法需要用户下载并安装皮肤apk,程序写起来比免安装的要简单很多,像很多系统主题就是通过这种方式实现的. 这种方式的思路是,从所有已安装的应用程序中遍历出皮肤程序(根据特定包 ...

  3. Android应用换肤总结

    换肤,我们都很熟悉,像XP的主题,塞班的主题.看过国外的一些技术博客,就会发现国内和国外对软件的,或者说移动开发的软件的需求的不同.国外用户注重社交.邮件等功能,国内用户则重视音乐.小说.皮肤等功能, ...

  4. duilib入门之贴图描述、类html文本描述、动态换肤、Dll插件、资源打包

    转载自duilib入门文档 贴图描述: Duilib的表现力丰富很大程度上得益于贴图描述的简单强大.Duilib的贴图描述分为简单模式和复杂模式两种. 简单模式使用文件名做为贴图描述内容,在这种方式下 ...

  5. Android主题换肤实现

    本系列文章主要是对一个Material Design的APP的深度解析,主要包括以下内容 基于Material Design Support Library作为项目整体框架.对应博文:Android ...

  6. Android主题换肤 无缝切换

    2016年7月6日 更新:主题换肤库子项目地址:ThemeSkinning,让app集成换肤更加容易.欢迎star以及使用,提供改进意见. 更新日志: v1.3.0:增加一键切换切换字体(初版)v1. ...

  7. hybird之web动态换肤实现

    前言 最近在重构个hybird(原生的壳包着Web页面)的UI框架,进行到了做换肤功能的阶段,所以这里是我思考的解决的方法. 预想 目前实现换肤的功能无非就两种做法. 1.写几个皮肤文件,然后切换使用 ...

  8. CocoStudio基础教程(4)骨骼动画的动态换肤

    1.概述 游戏中人物的状态会发生改变,而这种改变通常要通过局部的变化来表现出来.比如获得一件装备后人物形象的改变,或者战斗中武器.防具的损坏等.这些变化的实现就要通过动态换肤来实现. 2.运行到程序 ...

  9. Cocos2d-x 3.0 cocostudio骨骼动画的动态换肤

    概述 游戏中人物的状态会发生改变,而这种改变通常要通过局部的变化来表现出来.比如获得一件装备后人物形象的改变,或者战斗中武器.防具的损坏等.这些变化的实现就要通过动态换肤来实现.在接下来的这个Demo ...

随机推荐

  1. NOIP 2009 最优贸易

    题目描述 C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个 城市之间最多只有一条道路直接相连.这 m 条道路中有一部分为单向通行的道路,一部分 为双向通行的道路 ...

  2. ●BZOJ 3926 [Zjoi2015]诸神眷顾的幻想乡

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3926题解&&代码: 后缀自动机,Trie树 如果以每个叶子为根,所有的子串一 ...

  3. ●BZOJ 2743 [HEOI2012]采花

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=2743 题解: 树状数组,离线 求区间里面有多少种出现次数大于等于 2 的颜色. 类似某一个题 ...

  4. hdu 5274 Dylans loves tree(LCA + 线段树)

    Dylans loves tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Othe ...

  5. Simpson积分(BZOJ2178)

    lrj的代码常数太大T了QAQ,改了一下. #include <cstdio> #include <cmath> #include <algorithm> usin ...

  6. html高度塌陷以及定位的理解

    高度塌陷的含义: 父元素的高度,默认被子元素撑开,目前来讲box2多高,box1就多高.此时如果子元素设置浮动,则会导致其完全脱离文档流,子元素脱离文档流将无法撑开父元素, 导致父元素的高度丢失,就是 ...

  7. Springboot整合log4j2【详细步骤】

    1.去除logback中的依赖包 <dependency> <groupId>org.springframework.boot</groupId> <arti ...

  8. Cisco banner 登陆消息提示设置命令详解

    从法律角度来看,登陆消息非常重要.当入侵者进入网络而没有受到适当的警告时,他们有可能赢得官司.在放置登陆消息之前应让律师检查下,永远不要使用"欢迎"等问候语,以免被误解为邀请大家使 ...

  9. 数据结构之堆Heap

    1. 概述 堆(也叫优先队列),是一棵完全二叉树,它的特点是父节点的值大于(小于)两个子节点的值(分别称为大顶堆和小顶堆).它常用于管理算法执行过程中的信息,应用场景包括堆排序,优先队列等. 2. 堆 ...

  10. CSS缩写的样式

    熟悉和了解CSS的朋友都知道,CSS样式表有很多缩写方式.比如,定义字体.定义背景等,都可以把CSS代码缩写到一行.为了能更好的搞清楚CSS缩写方法,我收集整理了一些有关CSS简写的参考资料,也是对自 ...