Android动态换肤(一、应用内置多套皮肤)

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

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

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

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

实现:

  • 确定需要换肤的地方

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

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

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

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

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- 皮肤1 主色调 天蓝#4AC2E3-->
    <!-- 界面背景 -->
    <color name="pf1_activity_bg_color1">#46BAE3</color>
    <color name="pf1_activity_bg_color2">#63f3e3</color>
    <!-- item选择器 -->
    <color name="pf1_main_item_bg1">#50CEE3</color>
    <color name="pf1_main_item_bg2">#4AC2E3</color>
    <!-- 字体颜色黑色 -->
    <color name="pf1_text_color">#000000</color>               

    <!-- 皮肤2 主色调 草绿#53CAC3-->
    <!-- 界面背景 -->
    <color name="pf2_activity_bg_color1">#53CAC3</color>
    <color name="pf2_activity_bg_color2">#73FFB9</color>
    <!-- item选择器 -->
    <color name="pf2_main_item_bg1">#62E3BE</color>
    <color name="pf2_main_item_bg2">#5BD7C0</color>
    <!-- 字体颜色白色 -->
    <color name="pf2_text_color">#ffffff</color>
</resources>

  • 编写SkinUtil资源加载类
public class SkinUtil {
    private SharedPreferences sp;
    //KEY
    private final String KEY_PF = "skin";  //记录当前皮肤
    //VALUE
    public static final int VALUE_SKIN_1 = 1;   //天蓝
    public static final int VALUE_SKIN_2 = 2;   //草绿

    //当前皮肤资源ID
    public int activity_bg;
    public int item_bg;
    public int textColor;

    public SkinUtil(Context context){
        sp = context.getSharedPreferences("mySkin", Context.MODE_PRIVATE);
        loadPf();
    }
    /**
     * 设置使用那一套皮肤
     * @param witch
     */
    public void setSkin(int witch){
        sp.edit().putInt(KEY_PF, witch).commit();
        loadPf();
    }
    /**
     * 加载皮肤资源
     */
    public void loadPf(){
        //默认第一套皮肤(如果没有设置过)
        int pf_num =  sp.getInt(KEY_PF, VALUE_SKIN_1);
        switch (pf_num) {
        case VALUE_SKIN_1:
            setSkin1();
            break;
        case VALUE_SKIN_2:
            setSkin2();
            break;
        }
    }

    //加载第一套皮肤资源ID
    private void setSkin1() {
        activity_bg = R.drawable.skin1_activity_bg;
        item_bg = R.drawable.skin1_main_item_bg;
        textColor = R.color.pf1_text_color;
    }

    //加载第二套皮肤资源ID
    private void setSkin2() {
        activity_bg = R.drawable.skin2_activity_bg;
        item_bg = R.drawable.skin2_main_item_bg;
        textColor = R.color.pf2_text_color;
    }
}
  • 使用皮肤

    在Application中初始化皮肤工具类

public class MyApplication extends Application {
    public static SkinUtil skin;
    @Override
    public void onCreate() {
        super.onCreate();
        skin = new SkinUtil(getApplicationContext());
    }
}

定义BaseActivity

public abstract class BaseActivity extends Activity implements OnClickListener {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initView();
        setSkin();
    }
    protected abstract void initView();
    protected abstract void setSkin();
}

实现setSkin()方法设置皮肤

public class MainActivity extends BaseActivity{
    private LinearLayout ll_bg;
    private TextView tv_skin1, tv_skin2;
    @Override
    protected void initView() {
        setContentView(R.layout.activity_main);
        ll_bg = (LinearLayout) findViewById(R.id.ll_bg);
       ...
    }
    protected void setSkin() {
        ll_bg.setBackgroundResource(MyApplication.skin.activity_bg);
        ...
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.tv_skin1:
            //使用第一套皮肤
            MyApplication.skin.setSkin(SkinUtil.VALUE_SKIN_1);
            setSkin();
            break;
        case R.id.tv_skin2:
            //使用第二套皮肤
            MyApplication.skin.setSkin(SkinUtil.VALUE_SKIN_2);
            setSkin();
            break;
        ...
        }
    }
}

源码下载

https://github.com/openXu/SkinChange1

时间: 2024-12-13 02:22:28

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

Android动态换肤开源库Colorful发布

最近本人需要用到夜间模式,但是经过一番搜索似乎并没有看到好的开源实现,看到有一个类似的库MultipleTheme,但是需要自定义所有要实现换肤功能的View,感觉比较麻烦.当发现现有的解决方案不能很好的解决问题时,往往只能自己实现,因此本人花了点时间简单弄了一个实现该功能的开源库,命名为Colorful. Colorful是基于Theme,无需重启Activity.无需自定义View,方便的实现日间.夜间模式,github地址为 https://github.com/bboyfeiyu/Col

一个功能齐全的CMS管理系统模板,内置6套皮肤,已经转化为标准的Eclipse项目,直接导入即可

原文:一个功能齐全的CMS管理系统模板,内置6套皮肤,已经转化为标准的Eclipse项目,直接导入即可 源代码下载地址:http://www.zuidaima.com/share/1550463745526784.htm - MrZhao只分享精品,话不多说,直接上图  - 为了压缩文件我把WEB-INF下面的lib包打包放在网盘下载地址:http://pan.baidu.com/s/1eQEbAAA - 把lib解压进去以后项目直接导入Eclise即可运行 - 数据库Mysql,初始脚本项目里

一个超漂亮的Java版博客系统,内置14套皮肤,已经转化为标准的Eclipse项目,直接导入即可

原文:一个超漂亮的Java版博客系统,内置14套皮肤,已经转化为标准的Eclipse项目,直接导入即可 源代码下载地址:http://www.zuidaima.com/share/1550463745002496.htm MrZhao只分享精品,话不多说,直接上图      - 为了压缩文件我把WEB-INF下面的lib包打包放在网盘下载地址:http://pan.baidu.com/s/1hqqqWOc - 把lib解压进去以后项目直接导入Eclise即可运行 - 数据库Mysql,确保一个新

DevExpress 动态换肤

我们都知道Devexpress内置了很多themes,那要怎么在使用时动态更改呢. 下面是方法以: 1.如果你们已经有主题了,那就在XAML中删除类似下下面的语句. dx:ThemeManager.ThemeName="LightGray" 2.确保你的XAML中Window是引用下面的 <dx:DXWindow 后台也一样: MainWindow : DXWindow 3.下面就可以读取DevExpress中所有的主题: comboBoxEdit1.ItemsSource =

Android实现换肤功能(二)

前两天写的上章关于换肤的功能获得了很好的反响,今天为大家介绍另一种方式.今天实现的策略也是网友建议的,然后我自己去写了个demo,大家自己评估下相比第一种方式的优势和劣势在哪里. 简单介绍下关于第一种关于换肤实现的方法一些不友好的地方,比如点击了换肤的功能键,需要先下载一个资源apk,然后再去引用其中的资源ID,于用户使用起来确实有有很多不便之处.今天为大家介绍的方法是克服了这一弊端的,可以实现直接在应用内切换,把资源文件存储在本地apk的,读取和操作也是更加便捷的,下面介绍下大致的一个实现逻辑

Android主题换肤 无缝切换

2016年7月6日 更新:主题换肤库子项目地址:ThemeSkinning,让app集成换肤更加容易.欢迎star以及使用,提供改进意见. 更新日志: v1.3.0:增加一键切换切换字体(初版)v1.2.1:完善之前版本View的创建v1.2.0:增加对换肤属性自定义扩展v1.1.0:可以直接加载网络上的皮肤文件 今天再给大家带来一篇干货. Android的主题换肤 ,可插件化提供皮肤包,无需Activity的重启直接实现无缝切换,可高仿网易云音乐的主题换肤. 这个链接是本次的Demo打包出来的

android之换肤原理解读

如下是解读demo的链接,自行下载 https://github.com/fengjundev/Android-Skin-Loader 由于是开源的,而且对于想了解换肤功能的童鞋这个demo实在是通俗易懂,原理也很清晰,所以忍不住想要记录一下, 题外话:附上一篇换肤技术总结的博客,这是一篇动态换肤与本地换肤(传统的theme)换肤优劣势的详细比较,需要的童鞋,可以详细拜读,至少知道来源 http://blog.zhaiyifan.cn/2015/09/10/Android%E6%8D%A2%E8

Android实现换肤功能(一)

上周有个朋友给建议说讲讲换肤吧,真巧这周公司的工作安排也有这个需求,换的地方之多之繁,让人伤神死了.正所谓磨刀不误砍柴工,先磨下刀,抽出一个工具类,写了个关于换肤的简单demo. Android中换肤的实现有几种方法,我使用的是读取共享进程空间另一apk中的资源的方法.大致的原理如下,让你的app和一个只有资源文件的app运行在同一进程中,这样你的app就可以访问另一app的资源了.原理很简单,下面我们分步骤讲解实现过程. 一.共享进程运行的空间 通过在两个工程下的manifest根节点添加相同

hybird之web动态换肤实现

前言 最近在重构个hybird(原生的壳包着Web页面)的UI框架,进行到了做换肤功能的阶段,所以这里是我思考的解决的方法. 预想 目前实现换肤的功能无非就两种做法. 1.写几个皮肤文件,然后切换使用这几个文件达到换肤的目的. 不得不说这是最常见的方式,效果也比较明显,但是它有几个缺点. 缺点: 1.如果更改一个皮肤的内容,那其他的皮肤文件也要做相应修改(这挺麻烦,不过可以用less管理css解决,所以也不是什么大问题). 2.它是固定的,在使用的时候皮肤文件已经是写好的了,而当我需要动态设置一