• android 切换主题介绍一


    原文出自: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里面的res
    	private 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 项目为测试皮肤主程序,使用前请先安装皮肤。



  • 相关阅读:
    POJ-1035 Spell checker---字符串处理
    hdu-3572 Task Schedule---最大流判断满流+dinic算法
    BZOJ4826: [Hnoi2017]影魔
    BZOJ4825: [Hnoi2017]单旋
    BZOJ3504: [Cqoi2014]危桥
    BZOJ4407: 于神之怒加强版
    BZOJ2818: Gcd
    BZOJ4542: [Hnoi2016]大数
    BZOJ4540: [Hnoi2016]序列
    BZOJ4537: [Hnoi2016]最小公倍数
  • 原文地址:https://www.cnblogs.com/springskyhome/p/3689907.html
Copyright © 2020-2023  润新知