原文出自:Spring sky ,欢迎转载,请保留版权和原文地址 http://blog.csdn.net/springsky_/article/details/24476137

近日春暖花开,又是一个金三银四的季节,瞅瞅外面的风景,一声长叹,还是埋头继续修技养神。近日在android主题上遇到了一个很纠结的问题,怎么才能保证android更滑多种皮肤。经历了三次实验,各有不同,首先本文先讲解一下依靠插件的方式更换主题:

简介:把创建一个工程,把资源文件放入,然后打包成apk,放在主程序的Assets中,然后切换皮肤的时候,安装该app,再根据皮肤apk的包名获取“Resource”对象中得资源对象。

优点:本身皮肤就是一个apk,apk可以随时下载,随时安装,可以控制版本动态的更新,灵活方便,因为安装在手机的内存中,不收内存卡下载的影响。同时可以独立于主程序,所以能减少主程序的体积大小。

缺点:第一次使用,需要用户安装;如果用户下载了无法使用。

下面,我们来介绍相关的技术点:
1.怎么获取皮肤的Resource?

这个时候,就是用我们的PackageManger了。代码:

PackageManager packageManager = getPackageManager();try {PackageInfo packageInfo =  packageManager.getPackageInfo("com.springsky.face1", PackageManager.GET_ACTIVITIES);resources  = packageManager.getResourcesForApplication(packageInfo.applicationInfo);resource = new ReflectResource(resources, packageInfo.packageName);} catch (NameNotFoundException e) {Toast.makeText(this, "皮肤未安装,请安装皮肤", Toast.LENGTH_LONG).show();e.printStackTrace();}

上面的方式,首先使用getPackageManager()获取到包管理者,然后使用包名获取到Packageinfo对象,Packageinfo对象中,会保证程序的icon,版本等这种权限,目前大部分程序管理工具很神奇,就是依靠PackageManager完成的。从包PackageInfo对象中,我们可以得到Resource对象,其实,这个时候,我们已经成功一半了,因为得到这个,基本上皮肤的资源,我们是拿到了。接下来进入第二步。

2.怎么获取每个图片资源的ID?

在我们得到的Resource对象中,有一个方法:res.getIdentifier(name,defType,defPackage)  这个方法 ,相当的重要,他返回的int,其实从英文字面意思,可以理解为 获取唯一的辨识。也就是我们的ID,那么下面的三个参数的意思分别为:

name:ID的名称

defType:类型 ()

defPackage:包名称

其实,也就是说,我们只要根据 我们的ID的名称+类型+包名称,就可以获取到该图片。

其实重点在defType这个参数,其实不难,这边的取值也是固定的,比如:图片=”drawable“,其他的什么的,仔细阅读介绍即可。

3.怎么获取资源对象?

其实,这个问题,你查阅Resource对象的方法是,会发现一个方法:getDrawable(id);    这个方法,真的不难理解,所以基本上就ok了吧。

下面我就简单的提供一个工具类。

package com.springsky.facedemo;import java.io.IOException;
import java.io.InputStream;import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Xml;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.RotateAnimation;
import android.view.animation.ScaleAnimation;
import android.view.animation.TranslateAnimation;/**** @author spring sky* <br>资源工具类* <br>Email:vipa1888@163.com* 创建时间:2014-4-25下午4:08:00*/
public class ReflectResource {private Resources res;// 获取的资源apk里面的resprivate String apkPackageName;// 资源apk里面的包名public ReflectResource(Resources res, String apkPackageName) {this.res = res;this.apkPackageName = apkPackageName;}/*** 获取layout文件中的id号* * @param layoutName*            layout名*/public int getResApkLayoutId(String layoutName) {return res.getIdentifier(layoutName, "layout", apkPackageName);}/*** 获取布局layout文件* * @param context*            上下文* @params layoutName* @return view*/public View getResApkLayoutView(Context context, String layoutName) {LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);return inflater.inflate(res.getLayout(getResApkLayoutId(layoutName)), null);}/*** 获取控件view的id号* * @param widgetName*            控件名*/public int getResApkWidgetViewID(String widgetName) {return res.getIdentifier(widgetName, "id", apkPackageName);}/*** 获取布局文件中的控件* * @params layout,资源apk中的布局(view)* @params widgetName 控件名称* @return widgetView*/public View getResApkWidgetView(View layout, String widgetName) {return layout.findViewById(getResApkWidgetViewID(widgetName));}/*** 获取drawable文件的id* * @param DrawableName*            图片名字*/public int getDrawableId(String imgName) {return res.getIdentifier(imgName, "drawable", apkPackageName);}/*** 获取图片资源* * @param imgName* @return drawable*/public Drawable getResApkDrawable(String imgName) {int id = getDrawableId(imgName);if(id > 0){return res.getDrawable(id);}Log.i("getResApkDrawable", imgName+" 在皮肤插件中未找到");return null;}/*** 获取string文件中的id号* * @param stringName*            字符串在String文件中的名字*/public int getResApkStringId(String stringName) {return res.getIdentifier(stringName, "string", apkPackageName);}/*** 获取String字符串* * @param stringName* @return string*/public String getResApkString(String stringName) {return res.getString(getResApkStringId(stringName));}/*** 获取anim文件中的id号* * @param animationName*/public int getResApkAnimId(String animationName) {return res.getIdentifier(animationName, "anim", apkPackageName);}/*** 获取anim文件 XmlPullParser* * @param animationName* @return XmlPullParser*/public XmlPullParser getResApkAnimXml(String animationName) {return res.getAnimation(getResApkAnimId(animationName));}/*** 获取动画anim* * @params animationName* @param animation*/public Animation getResApkAnim(Context context, String animationName) {Animation animation = null;XmlPullParser parser = getResApkAnimXml(animationName);AttributeSet attrs = Xml.asAttributeSet(parser);try {animation = createAnimationFromXml(context, parser, null, attrs);} catch (XmlPullParserException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return animation;}/*** 获取anim动画*/private Animation createAnimationFromXml(Context c, XmlPullParser parser,AnimationSet parent, AttributeSet attrs)throws XmlPullParserException, IOException {Animation anim = null;int type;int depth = parser.getDepth();while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {if (type != XmlPullParser.START_TAG) {continue;}String name = parser.getName();if (name.equals("set")) {anim = new AnimationSet(c, attrs);createAnimationFromXml(c, parser, (AnimationSet) anim, attrs);} else if (name.equals("alpha")) {anim = new AlphaAnimation(c, attrs);} else if (name.equals("scale")) {anim = new ScaleAnimation(c, attrs);} else if (name.equals("rotate")) {anim = new RotateAnimation(c, attrs);} else if (name.equals("translate")) {anim = new TranslateAnimation(c, attrs);} else {throw new RuntimeException("Unknown animation name: "+ parser.getName());}if (parent != null) {parent.addAnimation(anim);}}return anim;}/*** 获取 color文件中的id号* * @param colorName*/public int getResApkColorId(String colorName) {return res.getIdentifier(colorName, "color", apkPackageName);}/*** 获取color 值* * @param colorName* @return int*/public int getResApkColor(String colorName) {return res.getColor(getResApkColorId(colorName));}/*** 获取 dimens文件中的id号* * @param dimenName*/public int getResApkDimensId(String dimenName) {return res.getIdentifier(dimenName, "dimen", apkPackageName);}/*** 获取dimens文件中值* * @param dimenName* @return float*/public float getResApkDimens(String dimenName) {return res.getDimension(getResApkDimensId(dimenName));}public InputStream getResApkRaw(String string) {return res.openRawResource(getResApkRawId(string));}private int getResApkRawId(String string) {return res.getIdentifier(string, "raw", apkPackageName);}}

以上工具类,基本上提供了 各种方法来获取Resource的所有资源,所以,这下放心了把。

具体界面实现只有一行代码:

findViewById(R.id.btn_bg).setBackgroundDrawable(resource.getResApkDrawable("more_item_bg"));

这样就可以完成换肤功能了!

总结:总体来说,如果项目中能接受该方式安装apk,我试极力推荐该apk,因为这样皮肤可以做成插件,封层清楚,同时可以在多个项目中使用。如有疑问请联系我。

具体代码: http://download.csdn.net/detail/vipa1888/7251845

Face1Resource 项目为皮肤工程

FaceDemo 项目为测试皮肤主程序,使用前请先安装皮肤。

转载于:https://www.cnblogs.com/springskyhome/p/3689907.html

android 切换主题介绍一相关推荐

  1. android换主题功能,Android 切换主题风格(Theme换肤效果)

    参考 截图 1.默认打开 image.png 2.点击[换主题色] image.png 需知 主题色运用:manifest清单文件中application的属性之一,android:theme=&qu ...

  2. android 界面切换监听,Android切换页面--setContentView

    setContentView 一般切换页面,通过Intent,startActivity可以实现,但系统创建Activity是非常耗时的,如果对切换画面时间有要求,只能用setContentView在 ...

  3. Android开发 关于避免切换主题时免闪屏的几种方式

    Android开发 关于避免切换主题时闪屏的几种方式 在activity中调用setTheme来切换夜间模式的方法可能大家有看过相关的文章了,但是调用setTheme设置的主题后界面并没有变化,这时需 ...

  4. Android 实现切换主题皮肤功能(类似于众多app中的 夜间模式,主题包等)

    首先来个最简单的一键切换主题功能,就做个白天和晚上的主题好了. 先看我们的styles文件: 1 <resources>2 3 <!-- Base application theme ...

  5. Android动态切换主题

    软件换肤从功能上可以划分三种: 1) 软件内置多个皮肤,不可由用户增加或修改: 最低的自由度,软件实现相对于后两种最容易. 2) 官方提供皮肤供下载,用户可以使用下载的皮肤: 用户可选择下载自己喜欢的 ...

  6. Android实现切换主题功能

    现在市面上有很多app都有更换主题皮肤的功能,那么到底是怎么实现的呢? 首先我们先上一张简单效果图 特别简单的实现,我们通过点击按钮切换主题 1.实现原理 实现起来特别简单,这里我们准备多个主题资源( ...

  7. android黑暗主题实现,Android实现黑白主题切换

    黑夜,白天两种模式的切换,其实就是黑白两种主题的切换 看效果吧: 实现步骤 1:创建两种主题模式 @color/colorPrimary @color/colorPrimaryDark @color/ ...

  8. android colorstatelist_B站Android多主题框架开源:MagicaSakura

    最近不少同学在后台催更,还有朋友开始问我是不是出啥事了- -!,是得出来解释下,其实就是最近重心没有放在公众号这块,至于具体缘由就不说啦,感觉各种借口都要被我用完了,你们就当我懒癌复发吧.讲真,真心要 ...

  9. Android项目工程结构介绍

    Android项目工程结构介绍 (1)gradle和.idea Android Studio自动生成的文件,打包的时候一般会删掉再进行打包 (2)app 项目的代码资源都在其中,也是我们工作的核心目录 ...

最新文章

  1. rrdtool的完整例子
  2. 神经网络之 CNN 与 RNN 的关系
  3. 引号快捷键_高效率的Excel-Ctrl类快捷键二
  4. just函数python_提升 Python 性能 Numba 与 Cython
  5. 从HelloWorld看iphone程序的生命周期
  6. java中springdi_java中spring入门
  7. python爬虫与django_请问django和爬虫程序如何整合?
  8. 手把手教你调试Linux C++ 代码(一步到位包含静态库和动态库调试)
  9. linux live usb下载,LinuxLive USB Creator
  10. pythoncharm怎么保存代码_pycharm怎么保存代码
  11. php长篇特点,《细说PHP》特色
  12. UEFI 文件类型.efi
  13. 看完此文,告诉你什么是黑中介
  14. 波导缝隙天线(一)[搬运]
  15. c语言字符串输出有乱码,C语言puts函数输出乱码测试
  16. 小米5 Android 8.0解bl,小米8 刷机 解账号BL锁 隐藏帐户 免授权解锁刷机包-刷机之家...
  17. PPI_DPI 对比
  18. 内核线程ksoftirqd
  19. [C/C++]神经元结构编码
  20. arcgis多个图共用一个图例_ArcGIS制图技巧,一个小技巧使图例与之匹配!

热门文章

  1. linux平均负载什么意思_在Linux中什么是平均负载?
  2. Android CountDownTimer示例
  3. android实例教程_Android ConstraintLayout示例教程
  4. testng 监听器_TestNG侦听器
  5. 使用PDF-XChange Editor为PDF文件添加图章(仅图片)
  6. ArcGIS Engine中删除要素的几种方法总结
  7. asp.net core的TagHelper简单使用
  8. GAD游戏学院系列丛书发布,引爆峰会现场
  9. springMVC4(4)json与对象互转实例解析请求响应数据转换器
  10. HashMap--并发下死循环(HashMap不能在多线程下使用)