Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android 切換主題介紹一

android 切換主題介紹一

編輯:關於Android編程

 

近日春暖花開,又是一個金三銀四的季節,瞅瞅外面的風景,一聲長歎,還是埋頭繼續修技養神。近日在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
 * 
資源工具類
 * 
Email:[email protected]
 * 創建時間: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,因為這樣皮膚可以做成插件,封層清楚,同時可以在多個項目中使用。如有疑問請聯系我。

 

 

Face1Resource 項目為皮膚工程

FaceDemo 項目為測試皮膚主程序,使用前請先安裝皮膚。
 

 

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved