android换肤功能 如何动态获取控件中背景图片的资源id?_Android

这个是在在做一个换肤功能时遇到的问题。  

对于换肤,网上都有示例,可以从别的皮肤安装包中读取所要的资源,前提是你必须先持有这个资源的引用名称,像R.drawable.background(喂,这不是废话嘛)。这个换肤的方案原理就是,自身应用的资源名称是R.drawable.background,那皮肤包中应该也是这个名称,然后通过这个名称获取该资源在皮肤包中的具体id,代码:

  //先获取本地资源引用名称,type name是R.drawable.background中的"drawable",entry name是"background"
  String resTypeName = getContext().getResources().getResourceTypeName(id);
  String resEntryName = getContext().getResources().getResourceEntryName(id);
  //然后创建皮肤包所在应用的Context
  Context apk = getContext().createPackageContext(packageName,
      Context.CONTEXT_IGNORE_SECURITY)
  //然后就是获取皮肤包中的资源id了
  int drawavleId = apk.getResources().getIdentifier(resEntryName, resTypeName,
      apk.getPackageName());  

这个换肤方案中,每个Activity在切换皮肤时,需要遍历整个layout,判断控件如果id中包含“skin”的字符,意味这个控件是需要换肤的控件,这个控件的id可以先保存下来。

遍历视图的代码 

  private List<Integer> skinViewList = new ArrayList<Integer> ();  private void scanViewGroup(ViewGroup group, List<Integer> skinViewList, Resources res) {
    //first we need check if this ViewGroup have a background
    if(group.getId() != View.NO_ID
        && res.getResourceEntryName(group.getId()).contains(SKIN_PATTERN)
        && !skinViewList.contains(group)) {
      skinViewList.add(group.getId());
    }

    //second check its child view
    View child;

    for(int i = 0; i < group.getChildCount(); i++) {
      child = group.getChildAt(i);

      if(child instanceof ViewGroup) {
        scanViewGroup((ViewGroup)child, skinViewList, res);
      } else if(child.getId() == View.NO_ID) {
        return;
      } else {
        int viewId = child.getId();
        String entryName = res.getResourceEntryName(viewId);

        Log("scanViewGroup(), entryName of this childView : " + 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(String name, Context context, AttributeSet attrs)方法,这个方法我的理解是在Activity中每个控件(包括LinearLayout、TextView、Button等等)初始化前会调用,我也打了log,进行了验证,其中attrs参数就是该控件的属性集,这就是我们需要的,代码: 

    //先判断前面扫描的skinViewList是否为空,不为空意味着有控件需要换肤
    if(skinViewList != null && skinViewList.size() > 0) {
      int viewId = -1, backgroundId = -1;
      for(int i = 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);
        }
      }

      //check if background drawable need save
      if(viewId != -1 && backgroundId != -1 &&
          drawableIdList != null && !drawableIdList.containsKey(viewId)) {
        drawableIdList.put(viewId, backgroundId);

        Log("add to drawableIdList, viewId = " + viewId
            + ", backgroundId = " + backgroundId);
      }
    }

有了这个backgroundId,就能获取该资源的引用名称R.drawable.background,然后我们就能通过名称从其他包获取对应的资源文件了,从而可以执行换肤操作。而且,通过这个方法,不只可以获取图片资源的id,也能获取字符串如R.string.title,字体颜色如R.color.red,字体大小如R.dimens.text_size_small等等属性,从而扩大换肤的范围。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索android换肤功能
android 动态换肤、android 动态添加控件、android 动态控件、android 动态创建控件、android动态生成控件,以便于您获取更多的相关知识。

时间: 2024-11-03 18:59:43

android换肤功能 如何动态获取控件中背景图片的资源id?_Android的相关文章

android换肤功能 如何动态获取控件中背景图片的资源id?

这个是在在做一个换肤功能时遇到的问题. 对于换肤,网上都有示例,可以从别的皮肤安装包中读取所要的资源,前提是你必须先持有这个资源的引用名称,像R.drawable.background(喂,这不是废话嘛).这个换肤的方案原理就是,自身应用的资源名称是R.drawable.background,那皮肤包中应该也是这个名称,然后通过这个名称获取该资源在皮肤包中的具体id,代码: //先获取本地资源引用名称,type name是R.drawable.background中的"drawable"

MFC如何给IP控件设置背景图片

问题描述 MFC如何给IP控件设置背景图片 现在做的一个项目中要求给IP控件设置图片作为背景,求大神帮忙 解决方案 http://forums.codeguru.com/showthread.php?158774-CIPAddressCtrl-background-and-text-color 自己重绘,贴图 解决方案二: 重写CIPAddress类,在OnPaint()自绘实现.

单元格-FarPoint控件问题 背景图片

问题描述 FarPoint控件问题 背景图片 FarPoint中我要插入某个单元格中图片,采用了是 设置背景的图片方式,可是这样一来, 图片大小不一 ,都会强制拉伸为 背景图片,有什么好办法没,大家指点 fpSpread.Sheets[sheetIndex].Cells[rowNum columnNum].CellType = chooseImg.BackGrandImage;

Android中findViewById获取控件返回为空问题怎么解决_Android

在Android程序中,有时候需要加载非原来activity中xml布局中的控件,来使Android程序的界面更加丰富. 我本身是在使用ViewFlipper中遇到的问题. public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); inflater=(LayoutInflater)getSystemService(LAYO

C# WPF程序 怎么把image控件中的图片一数据流的形式,保存到sql数据库

问题描述 shujukuglsj=newshujukugl();txbctxbc=newtxbc();byte[]imgData=Encoding.Default.GetBytes(img_tx.Source.ToString());txbc.tupian=imgData;txbc.riqi=DateTime.Now;sj.txbc.Add(txbc);sj.SaveChanges(); 保存图片的时候byte[]数组最大值只有69还有对数据库中保存的图片的提取大神们,解答解答,谢谢了 解决方案

动态获取当前屏幕中光标所在位置的颜色

动态 ////////////////////////////////////////////////////////////////////////// /// 程序:屏幕取色 /// 功能:动态获取当前屏幕中光标所在位置的颜色 /// 作者:黎波 /// 网名:upto(阿球) /// 邮箱:itfun@163.com /// 日期:2004年3月31日 /////////////////////////////////////////////////////////////////////

动态创建控件支持事件响应并可保存与读取

VC++6.0中创建动态控件是比较偏离基础的知识,也有一定的难度.它的完整功能是要动态创建控件后再动态响应控件中的事件,两者全部做到才算完整. 这里我将展示一个完整的动态控件示例,它可以动态创建控件,然后再动态响应控件事件,并可以保存控件信息至ini配置文件,然后再根据ini文件读取出控件信息来动态创建控件.相信它能够解决你在动态控件中所遇到的许多问题. 当然,动态控件的方法有许多种,我展示的只是给我认为较好的. 这里以VC++6.0创建对话框工程为例,添加菜单,分别添加子项按钮,文本框,标签.

在Repeater控件中创建可隐藏区域

创建|控件 在WEB应用中,如何才能使应用高效率呢?如何才能吸引用户呢?这的确是个大学问,页面的内容,色搭配等都十分重要.但不可忽视的是,多数情况下,对于数据的呈现方式也是十分重要的.由于web应用的规模不断增大,数据也越来越多了,有时候,由于在一个页面同时显示的数据太多,从而造成页面的不美观,用户因此也会感到厌倦和操作困难.因此,本文将介绍利用repeater控件的隐藏区域,以达到较好的数据显示效果. 防止数据过多加载有很多方法,比如采用数据分页的方法,又或者采用master/detail的方

imageview-Android关于改变ListView里面的ImageView控件的背景图出现无法触发点击事件的问题

问题描述 Android关于改变ListView里面的ImageView控件的背景图出现无法触发点击事件的问题 问题说明:我使用AudioRecord进行录音,想要点击ImageView开始录音,然后根据音量大小设置ImageView背景图 ,由于ImageView是ListView的Item里面的一个子控件,于是我开启一个线程,使Thread.sleep(100);后 notifyDataSetChanged(),这时问题就出现了,当我再次点击ImageView想要录音暂停时,发现有时候点击事