当前位置: 移动技术网 > IT编程>移动开发>Android > android换肤功能 如何动态获取控件中背景图片的资源id?

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

2019年07月24日  | 移动技术网IT编程  | 我要评论

与宋同行,k365,赛尔号古丽

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

对于换肤,网上都有示例,可以从别的皮肤安装包中读取所要的资源,前提是你必须先持有这个资源的引用名称,像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等等属性,从而扩大换肤的范围。

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

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网