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

 更新时间:2016年08月31日 14:31:02   作者:ly513782705  
这篇文章主要为大家详细介绍了android换肤功能中如何动态获取控件中背景图片的资源id? ,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

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

对于换肤,网上都有示例,可以从别的皮肤安装包中读取所要的资源,前提是你必须先持有这个资源的引用名称,像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启动耗时问题的相关资料,需要的朋友可以参考下
    2021-07-07
  • Flutter基本组件Basics Widget学习

    Flutter基本组件Basics Widget学习

    本文详细讲解了Flutter基本组件Basics Widget,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-12-12
  • Android Handler使用案例详解

    Android Handler使用案例详解

    这篇文章主要介绍了Android Handler使用案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • Android多线程断点续传下载功能实现代码

    Android多线程断点续传下载功能实现代码

    这篇文章主要为大家详细介绍了Android多线程断点续传下载功能的实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-03-03
  • Android实现定时自动静音小助手

    Android实现定时自动静音小助手

    这篇文章主要为大家详细介绍了Android实现定时自动静音小助手,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-06-06
  • android中sqlite的按条件查找的小例子

    android中sqlite的按条件查找的小例子

    android中内嵌轻量级数据库sqlite,涉及到的操作无外乎增删改查,今天就来说一说其中的查找操作,更多的时候我们用到的查找是要按条件查找的 例如表的结构如下:
    2013-06-06
  • Android pull解析xml的实现方法

    Android pull解析xml的实现方法

    这篇文章主要介绍了Android pull解析xml的实现方法的相关资料,希望通过本文能帮助到大家,谢谢大家对本站的支持!需要的朋友可以参考下
    2017-10-10
  • Android自定义View实现遥控器按钮

    Android自定义View实现遥控器按钮

    这篇文章主要为大家详细介绍了Android自定义View实现遥控器按钮,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08
  • Android实现的仿淘宝购物车demo示例

    Android实现的仿淘宝购物车demo示例

    这篇文章主要介绍了Android实现的仿淘宝购物车demo示例,结合实例形式分析了Android购物车的功能、布局及逻辑实现技巧,需要的朋友可以参考下
    2016-07-07
  • Android RippleDrawable 水波纹/涟漪效果的实现

    Android RippleDrawable 水波纹/涟漪效果的实现

    这篇文章主要介绍了Android RippleDrawable 水波纹/涟漪效果的实现,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-08-08

最新评论