android换肤功能 如何动态获取控件中背景图片的资源id?
这个是在在做一个换肤功能时遇到的问题。
对于换肤,网上都有示例,可以从别的皮肤安装包中读取所要的资源,前提是你必须先持有这个资源的引用名称,像R.drawable.background(喂,这不是废话嘛)。这个换肤的方案原理就是,自身应用的资源名称是R.drawable.background,那皮肤包中应该也是这个名称,然后通过这个名称获取该资源在皮肤包中的具体id,代码:
//先获取本地资源引用名称,typename是R.drawable.background中的"drawable",entryname是"background" StringresTypeName=getContext().getResources().getResourceTypeName(id); StringresEntryName=getContext().getResources().getResourceEntryName(id); //然后创建皮肤包所在应用的Context Contextapk=getContext().createPackageContext(packageName, Context.CONTEXT_IGNORE_SECURITY) //然后就是获取皮肤包中的资源id了 intdrawavleId=apk.getResources().getIdentifier(resEntryName,resTypeName, apk.getPackageName());
这个换肤方案中,每个Activity在切换皮肤时,需要遍历整个layout,判断控件如果id中包含“skin”的字符,意味这个控件是需要换肤的控件,这个控件的id可以先保存下来。
遍历视图的代码
privateList<Integer>skinViewList=newArrayList<Integer>();privatevoidscanViewGroup(ViewGroupgroup,List<Integer>skinViewList,Resourcesres){
//firstweneedcheckifthisViewGrouphaveabackground
if(group.getId()!=View.NO_ID
&&res.getResourceEntryName(group.getId()).contains(SKIN_PATTERN)
&&!skinViewList.contains(group)){
skinViewList.add(group.getId());
}
//secondcheckitschildview
Viewchild;
for(inti=0;i<group.getChildCount();i++){
child=group.getChildAt(i);
if(childinstanceofViewGroup){
scanViewGroup((ViewGroup)child,skinViewList,res);
}elseif(child.getId()==View.NO_ID){
return;
}else{
intviewId=child.getId();
StringentryName=res.getResourceEntryName(viewId);
Log("scanViewGroup(),entryNameofthischildView:"+entryName);
if(entryName.contains(SKIN_PATTERN)&&!skinViewList.contains(child))
skinViewList.add(child.getId());
}
}
}
问题来了,本地应用中,你持有一个控件,比如Button,它的id可以直接调用button.getId()方法获取,但是它的背景图片background呢,我们可以调用button.getBackground()方法获取其对象,但是却没有方法可以获取这个资源图片的引用名称,也就无法得到它的具体id了。后面想到的方案就是,在每次Activity初始化的时候,我们事先遍历每一个控件的属性集AttributeSet,有需要换肤的控件,将其android:background这个属性的值保存下来,为此,需要重载Activity的onCreateView(Stringname,Contextcontext,AttributeSetattrs)方法,这个方法我的理解是在Activity中每个控件(包括LinearLayout、TextView、Button等等)初始化前会调用,我也打了log,进行了验证,其中attrs参数就是该控件的属性集,这就是我们需要的,代码:
//先判断前面扫描的skinViewList是否为空,不为空意味着有控件需要换肤
if(skinViewList!=null&&skinViewList.size()>0){
intviewId=-1,backgroundId=-1;
for(inti=0;i<attrs.getAttributeCount();i++){
if(attrs.getAttributeName(i).equals("id")){
viewId=attrs.getAttributeResourceValue(i,-1);
}
if(attrs.getAttributeName(i).equals("background")){
backgroundId=attrs.getAttributeResourceValue(i,-1);
}
}
//checkifbackgrounddrawableneedsave
if(viewId!=-1&&backgroundId!=-1&&
drawableIdList!=null&&!drawableIdList.containsKey(viewId)){
drawableIdList.put(viewId,backgroundId);
Log("addtodrawableIdList,viewId="+viewId
+",backgroundId="+backgroundId);
}
}
有了这个backgroundId,就能获取该资源的引用名称R.drawable.background,然后我们就能通过名称从其他包获取对应的资源文件了,从而可以执行换肤操作。而且,通过这个方法,不只可以获取图片资源的id,也能获取字符串如R.string.title,字体颜色如R.color.red,字体大小如R.dimens.text_size_small等等属性,从而扩大换肤的范围。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。