Android QQ技术分享三(QQ换肤之SkinEngine实现)

首先展示截图

原作者:http://blog.csdn.net/cc_want/article/details/49179109


【前言说明】此技术在android QQ2.0之后直到现在的QQ5.9版本也一直在使用,额下来我会详细讲解代码及实现原理,此技术目前百度或者google上等一些博客都很少提及,大致原理是通过java反射Resources类,在Resources类中存在sPreloadedDrawables变量,这个便是关键点,它的作用就是实现Drawable图片的预加载,在APP运行时控件或通过Resources.getDrawable(resId)方法获取图片,然而getDrawable会从sPreloadedDrawables获取到图片,但是此方法也并不是万全之策,它可能会因为API的更改而更改。


1.我们看到在此界面有三个按钮,接下来点击“立即换肤”按钮


此刻我们发现界面小机器人图标已被替换为蓝色背景的音乐图标


接下来我们点击“跳转”到AbcActivity界面看看效果。


我们发现在AbcActivity中图片也同样替换了,那么我们再看看AbcActivity的界面布局

在布局文件中,我们发现ImageView根本没有设置控件id,那么这个控件上的图片是怎么被替换的呢?接下来我们一起一步一步的分析。

二,原理分析及实现

在SkinEngine类中我们创建以下两个方法,并在initIntercepter方法中拦截Resources类中的sPreloadedDrawables变量。之后通过定义DrawablePreloadIntercepter做相关的拦截处理。


让DrawablePreloadIntercepter继承 LongSparseArray<Drawable.ConstantState>并重写get方法。


在get方法中我们首先建立mKeyToResourcesId变量,用于存储需要替换的皮肤资源,并添加对外的add方法,替换皮肤时,在Activity中将资源id添加到mKeyToResourcesId中。此时系统通过get方法获取资源时,判断资源文件对应的key在mKeyToResourcesId是否存在,如果不存在返回原本的图片资源,如果存在则调用SkinEngine类中的loadConstantState方法,加载皮肤资源。


在SkinEngine类的loadConstantState方法中,我们首先通过Resources的getValue方法拿到资源文件名,然后加载assets目录下的对应资源文件名的文件(此处可以改为从sd卡中加载)然后通过BitmapFactory创建Bitmap,并通过SkinnableBitmapDrawable类将Bitmap转换为Drawable.ConstantState对象。SkinnableBitmapDrawable类我已经写好了,可以拿去直接用。


此时就可以在Activity中使用换肤功能。使用方法如下


注意reloadDrawable方法,此方法只是为了刷新当前的Activity,在其他Activty不需要做此操作。


接来下说说SkinEngine.getInstances().run()方法,很简单,我们还需要反射Resources类中的mDrawableCache对象,它用于将sPreloadedDrawables的资源缓存下来,刚刚我们只是替换拦截了sPreloadedDrawables而已,此时我们需要将mDrawableCache中已经缓存的资源清空掉,然后通过reloadDrawable方法将页面中的图片重新从Resource中拿一下。此时你会发现换肤功能已经完成了。


接下来说说如何取消换肤,还记DrawablePreloadIntercepter中的mOldPreloadCache变量吗?当时在SkinEngine中的initIntercepter方法中我就已经将Resources类的sPreloadedDrawables变量保存下来了


使用方法,直接在Activity调用即可,然后在重新从Resources中拿一下资源。


好了,最后android的SkinEngine就已经完成了,接下来大家最关心的当然还是源码,那么我就无私的献上了,注意,下载需要1点积分,评论一下就赚回来了,就当时给我谢了这么久代码的一点点支持吧O(∩_∩)O~~


三,代码分享


http://download.csdn.net/detail/cc_want/9187187

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
SkinEngine 3.4.7 安装版SkinEngine控件是一组用于优化界面设计可视化控件,它重写了大部分可视化组件的源代码,使其外观更为美观漂亮,美化了程序界面的设计,使得程序员可以把更多的精力放在系统软件功能的设计上.首先从网上下载SkinEngine控件的安装包,我下载的是3.4.7版本,下载以后发现这个控件的安装竟然是windows的软件安装方式(而不是delphi安装第方控件的安装包方式),安装后发现系统的程序菜单多了一项SkinEngine,里面只有一项内容,就是它的Help文件.什么也不管兴冲冲的打开delphi 7,什么也没有发生?所以打开SkinEngine程序的那个Help文件一看,原来要使用这个控件组还需要进一步的安装.安装顺序如下:打开delphi 6,然后文件--->open,找到SkinEngine的安装目录(默认是ksdev),进一步到\sources\packages目录下面,首先找到se_dsgn_d6.dpk 文件,先编译后安装;然后再找到se_db_dsgn_d6.dpk文件,同样处理,此时delphi的控件组中多出来两组:SkinEngineSkinEngine DB.前者用于delphi程序普通界面的设计,后者用于数据库及其数据表相关内容的界面的设计,每一个组件的使用基本上都有一个delphi组件与之相对应,因此使用起来很方便.然后将“F:\DelphiProjects\VCL\SkinEngine 3.4.7 汉化版”放入Library path中。拖一个button到页面上,编译,通不过,提示找不到相关的DCU文件,没办法,重新回到SkinEngine的安装目录中,把sources目录中的所有文件拷贝到delphi6/lib目录下面,再次编译通过了.具体为什么会这样我也不是很清楚.希望能有高手指点一下.现在就可以安全的享用SkinEngine这道美餐了,合理的搭配好各个部件的使用,可以很轻松的编出来漂亮得不是一般的程序界面.卸载过程:菜单project->options->packages->在design packages下选择要删除的-〉remove按钮
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值