不通过R类获取自定义样式资源ID数组

昨天遇到并解决的需求,以此文记录,供遇到同类问题的同仁参考!

需求描述

不引用R类获取到自定义样式的值(资源id数组),如下是R.java中某个自定义样式的值

public static final int[] LoadingView = { 0x7f0200ac, 0x7f0200c5, 0x7f0200cd, 0x7f0200ce, 0x7f0200cf };

即如下代码如示,在自定义view组件中,获取自定义样式的值时不能使用R.styleable

TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.drop_down_list_attr);
mIsOnBottomStyle = ta.getBoolean(R.styleable.drop_down_list_attr_isOnBottomStyle, false);
mIsAutoLoadOnBottom = ta.getBoolean(R.styleable.drop_down_list_attr_isAutoLoadOnBottom, false);

解决方案

通过资源字符串获取资源id的方式获取自定义样式各个项的资源id值
示例代码如下

 public MyLoadingView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);


        /**
        int a = R.attr.loadding_color;
        int b = R.attr.ring_style;
        int styleAttrId[] = R.styleable.LoadingView;
        a == styleAttrId[0]
        b == styleAttrId[2]    
        **/

        Resources res = context.getResources();

        int styleAttrIdArray[] = new int[2]; //LoadingView的属性项的个数,示例中仅有两个
        styleAttrIdArray[0] =  res.getIdentifier("loadding_color", "attr", context.getPackageName());
        styleAttrIdArray[1] =  res.getIdentifier("ring_style", "attr", context.getPackageName());


        //TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LoadingView, 0, 0);
        TypedArray a = context.obtainStyledAttributes(attrs, styleAttrIdArray, 0, 0);

        //如下的R.styleable.LoadingView_loadding_color,LoadingView_ring_style是索引常量,在R.java类中查看替换即可
        setColor(a.getInt(R.styleable.LoadingView_loadding_color, -12871201));
        setRingStyle(a.getInt(R.styleable.LoadingView_ring_style, 0));
        //setColor, setRingStyle这里是自定义方法
    }

技术原理

关键点:自定义样式所有属性项的值(资源ID数组)其实都是存放在资源类R的内部attr类的!
如下是某个自定义样式

<declare-styleable name="LoadingView">
        <attr format="color" name="loadding_color"/>
        <attr format="enum" name="ring_style">
            <enum name="square" value="0"/>
            <enum name="round" value="1"/>
        </attr>
        <attr format="enum" name="progress_style">
            <enum name="material" value="0"/>
            <enum name="linear" value="1"/>
        </attr>
        <attr format="dimension" name="ring_width"/>
        <attr format="dimension" name="ring_radius"/>
    </declare-styleable>

生成的R类,对应字段如下
这里写图片描述
对应的某个属性项在R类的attr区,如下所示
这里写图片描述

解决方案二

有时候方案一会失效,原因是“打包”后的资源文件中自定义属性的排序与你“看到的”R文件中的排序不一致,解决方案是对自定义属性id值的数据做排序,并动态获取自定义属性的索引值,代码如下所示

 int id1 = res.getIdentifier("loadding_color", "attr", context.getPackageName());
 int id2 = res.getIdentifier("ring_style", "attr", context.getPackageName());
 int styleAttrIdArray[] = new int[2]; //LoadingView的属性项的个数,示例中仅有两个
 styleAttrIdArray[0] = id1; 
 styleAttrIdArray[1] = id2; 
 //排序一下
 Arrays.sort(styleAttrIdArray);
 int ringStyleAttrIndex = Arrays.binarySearch(styleAttrIdArray, id1);
 int loaddingAttrIndex = Arrays.binarySearch(styleAttrIdArray, id2);

 //TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LoadingView, 0, 0);
 TypedArray a = context.obtainStyledAttributes(attrs, styleAttrIdArray, 0, 0);

 //如下的R.styleable.LoadingView_loadding_color,LoadingView_ring_style是索引常量,在R.java类中查看替换即可
 setColor(a.getInt(loaddingAttrIndex, -12871201));
 setRingStyle(a.getInt(ringStyleAttrIndex, 0));
 //setColor, setRingStyle这里是自定义方法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值