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

Android系统通过XML 形式描述各种资源,包括布局、字符串、样式、交互风格等,通常存放在res目录中,使应用逻辑和界面设计分离开来,让开发者可以专注于代码逻辑。

换肤就是换掉皮肤包括的部分或所有资源。皮肤一般含有多个文件,例如图片、配置等文件,分散的文件不利于传输和使用,最好打包。打包的格式一般选择zip格式。这里分两种情况,一种是apk,例如腾讯微博,它的皮肤格式是一个apk;另一种是自定义扩展名,例如小米主题的扩展名为mtz,墨迹天气皮肤扩展名是mja,搜狗输入法皮肤扩展名为ssf,本质都是zip格式。

本节课程就来讲解Android应用程序如何实现换肤功能。

软件换肤从功能上可以划分三种:

1) 软件内置多个皮肤,不可由用户增加或修改;
  最低的自由度,软件实现相对于后两种最容易。
2) 官方提供皮肤供下载,用户可以使用下载的皮肤;
  用户可以下载自己喜欢的皮肤,然后安装使用,如腾讯微博中就提供了四种皮肤,用户可以下载使用。

3) 官方提供皮肤制作工具或方法,用户可自制皮肤。
  这种方式使用户有参与感,自由度较高。用户可根据自己的喜好定制软件的皮肤。

软件换肤从实现上可以划分三种:

1.一个应用中放置几个固定的皮肤,皮肤之间的控制由程序来控制实现。
   优点:实现简单。
   缺点:拥有多套皮肤(图片,布局文件定义),动态的修改布局。这样会让工程比较大,不仅不够灵活,而且生成的安装包太大,要增加新的皮肤需更新应用。

实现技术:这个很简单,可以通过sharereference统一控制皮肤的前后缀或者路径来实现一个通用的换肤目的。

2. zip压缩包式皮肤。应用可设置一个默认路径。如果用户选择某个皮肤,则解压该皮肤.zip到这个文件夹中。
   优点:无需安装,即使卸载掉皮肤应用,该皮肤仍然可用,不会影响正常使用。
   缺点:可能会因为用户的误操作,使皮肤文件损坏,资源访问的效率低。

实现技术: 该技术重点在于如何去读取zip文件中的资源以及皮肤文件存放策略。
  方案:如果软件每次启动都去读取SD卡上的皮肤文件,速度会比较慢。较好的做法是提供一个皮肤设置的界面,用户选择了哪一个皮肤,就把那个皮肤文件解压缩到”/data/data/[package name]/skin”路径下,这样不需要跨存储器读取,速度较快,而且不需要每次都去zip压缩包中读取,不依赖SD卡中的文件,即使皮肤压缩包文件被删除了也没有关系。

实现方法:
  1. 在软件的帮助或者官网的帮助中提示用户将皮肤文件拷贝到SD卡指定路径下
  2. 在软件中提供皮肤设置界面。可以在菜单或者在设置中。可参考墨迹天气(zip格式)等支持换肤的软件。
  3. 加载指定路径下的皮肤文件,读取其中的缩略图,在皮肤设置界面中显示,将用户选中的皮肤文件解压缩到”/data/data/[package name]/skin”路径下。
  4. 软件中优先读取”/data/data/[package name]/skin/”路径下的资源。如果没有则使用apk中的资源.

实现实例:墨迹天气下载的皮肤就是一个mja格式的压缩包,在应用的时候把皮肤资源释放到墨迹天气应用的目录下,更换皮肤时新的皮肤资源会替换掉老的皮肤资源每次加载的时候就是从手机硬盘上读取图片,这些图片资源的命名和程序中的资源的命名保持一致,一旦找不到这些资源,可以选择到系统默认中查找。(注:墨迹天气应用在设置中可以让用户自己控制插件皮肤是否装入内存)

下面是一个简单的例子:

下载zip资源包(略)----->解压zip到指定路径,应用程序加载时加载该路径下的资源。

   private String basePathString = "/data/data/com.wts.skin/Skin_kris";

   private String skinBasePath = basePathString + "/skin/";

//把zip格式的资源包解压到指定路径下:

ZipUtil zipp = new ZipUtil(2049);

zipp.unZip("/sdcard/skin.zip",basePathString);

//为button和背景设置资源

Bitmap bmp =BitmapFactory.decodeFile(skinBasePath+"test.png");

BitmapDrawable bd=new BitmapDrawable(bmp);

btnSet.setBackgroundDrawable(bd);

layout.setBackgroundDrawable(new  BitmapDrawable(

BitmapFactory.decodeFile(skinBasePath +"bg/bg.png")));

3. manifest中设置android:sharedUserId,通过这种方式可以达到不同应用相互访问数据的目的,以实现换肤功能。此外需要注意,皮肤apk和应用要有相同签名。

优点:可定期提供换肤包供下载,换肤方式灵活,同时效率比较高。
    缺点:如需使用某个皮肤,必须安装该皮肤。但其实现起来还是用代码的方式来提供置换的。同时,让两个工程来共享一个进程,这样做十分的危险。此外,安装了很多皮肤后,应用程序列表里面会有很多皮肤程序。在主程序卸载后,皮肤工程不能同样的卸载。如卸载腾讯微博之后,安装的皮肤apk没有被卸载。

实现技术:该技术的重点是怎样实现一个应用如何读取另一个apk中的资源。
  在android系统中,apk之间可以相互读取数据的条件是:有同样的签名,并且manifest中配置的android:sharedUserId属性值相同,那么两个apk运行在同一个进程中,可以互相访问任意数据.注意:只访问资源时不需要添加该属性值。

实现方法:

1)应用程序和皮肤程序的AndroidManifest.xml中配置minifest属性
   例如: android:sharedUserId="com.wwwww.skin",值可以是做任意的。

2) 文件与应用apk中对同一功能的皮肤文件名要一致
  例如:应用程序的背景图片路径:\WBlogSkin\res\drawable-hdpi\bg.png
   则皮肤apk中的背景图片文件路径也应该是SkinApk\res\drawable-hdpi\bg.png
3)访问资源的方法

  Context context =createPackageContext("com.wts.skin.night.hdpi",

Context.CONTEXT_IGNORE_SECURITY);

获取到皮肤包包名(com.wts.skin.night.hdpi)对应Context,通过返回的context对象就可以访问com.wts.skin.night.hdpi中的任何资源。
  例如:应用apk要获得皮肤apk中的xml资源(mSkin为包名)

Context context = mApp.createPackageContext(mSkin, 0);

mSkinResources = context.getResources();

int configResId = mSkinResources.getIdentifier(CONFIG_XML_NAME,"xml", mSkin);

XmlPullParser xmlpull = mSkinResources.getXml(configResId);

这样就得到了对xml资源的引用,其他资源文件的获取方式也是类似的。

注意:通过当前工程的R.id来调用被调用工程的资源,这是错误的,因为R是自动生成的,两个应用的id是没有办法对应的,所以需要通过getIdentifier来查找。

实现实例:腾讯微博等。

从上面可以看出,只有后两种实现(apk方式和zip方式)可以做到皮肤与应用程序实现分离

Android应用换肤总结的更多相关文章

  1. Android主题换肤实现

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

  2. Android主题换肤 无缝切换

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

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

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

  4. Android实现换肤功能(一)

    上周有个朋友给建议说讲讲换肤吧,真巧这周公司的工作安排也有这个需求,换的地方之多之繁,让人伤神死了.正所谓磨刀不误砍柴工,先磨下刀,抽出一个工具类,写了个关于换肤的简单demo. Android中换肤 ...

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

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

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

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

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

    动态换肤在很多android应用中都有使用,用户根据自己的喜好设置皮肤主题,可以增强用户使用应用的舒适度. Android换肤可以分为很多种,它们从使用方式,用户体验以及项目框架设计上体现了明显的差异 ...

  8. Android实现换肤功能(二)

    前两天写的上章关于换肤的功能获得了很好的反响,今天为大家介绍另一种方式.今天实现的策略也是网友建议的,然后我自己去写了个demo,大家自己评估下相比第一种方式的优势和劣势在哪里. 简单介绍下关于第一种 ...

  9. Android插件换肤 一.实现原理

    学习缺的不是时间,而是耐心 目的 1.搞懂系统获取资源文件到在加载布局的整个流程是自己实现换肤功能的理论基础 2.提高分析源码.追踪源码的能力 要点 1.XmlResourceParser (通过这个 ...

随机推荐

  1. java常见内存溢出(OOM)

    jvm内存区域 程序计数器一块很小的内存空间,作用是当前线程所执行的字节码的行号指示器. java栈与程序计数器一样,java栈(虚拟机栈)也是线程私有的,其生命周期与线程相同.通常存放基本数据类型, ...

  2. Firefly 配置说明

    下图一一个典型的config.json的配置:配置中主要包括四个部分,master,servers,db,memcached.master用来定义master的端口,servers用来定义各个服务器中 ...

  3. easyui源码翻译1.32--Tabs(选项卡)

    前言 使用$.fn.tabs.defaults重写默认值对象.下载该插件翻译源码 选项卡显示一批面板.但在同一个时间只会显示一个面板.每个选项卡面板都有头标题和一些小的按钮工具菜单,包括关闭按钮和其他 ...

  4. 开发完整的Web项目必备

    开发工具 数据库系统 DB2数据库 Oracle数据库 SQL Server数据库 MySQL数据库 Access数据库 Web服务器 IIS BEA WebLogic Server Apache T ...

  5. URAL1029. Ministry(DP+路径)

    链接 路径麻烦啊 很多细节 倒回去搜一遍 卡了一节数据库.. #include <iostream> #include<cstdio> #include<cstring& ...

  6. poj2723

    把每对钥匙看做一个变量,那两个钥匙看做他的两个状态 每一个开门的要求就是一个条件(xi or xj) 很显然有了2sat的基本要素 2sat是一个判定性问题,而这题求最多能过几个门: 不难想到二分答案 ...

  7. c语言实用功能库函数#include<stdlib.h>

    实用函数<stdlib.h> 在头文件<stdlib.h>中说明了用于数值转换.内存分配以及具有其他相似任务的函数. 1 atof #include <stdlib.h& ...

  8. 盘点国内程序员不常用的热门iOS第三方库

    https://github.com/syedhali/EZAudio 基于核心音频,有助于进行实时,低延迟音频处理和可视化的iOS和OSX音频可视化框架. https://github.com/ba ...

  9. 18款 非常实用 jquery幻灯片图片切换

    1.jquery图片滚动仿QQ商城带左右按钮控制焦点图片切换滚动 jquery图片特效制作仿腾讯QQ商城首页banner焦点图片轮播切换效果,带索引按钮控制和左右按钮控制图片切换. 查看演示>& ...

  10. MsoShapeType /InlineShape枚举

    指定形状的类型或形状范围. 名称 值 说明 msoAutoShape 1 自选图形. msoCallout 2 标注. msoCanvas 20 画布. msoChart 3 图. msoCommen ...