Java 如何通过反射从声明可设置样式的TypedArray获取值?

Java 如何通过反射从声明可设置样式的TypedArray获取值?,java,android,reflection,declare-styleable,Java,Android,Reflection,Declare Styleable,我使用的是shape image view(),当我想从declare styleable中获取shape image view定义的值时: <declare-styleable name="ShaderImageView"> <attr name="siSquare" format="boolean" /> <attr name="siBorderColor" format="color" /> <attr name="siBo

我使用的是shape image view(),当我想从declare styleable中获取shape image view定义的值时:

<declare-styleable name="ShaderImageView">
    <attr name="siSquare" format="boolean" />
    <attr name="siBorderColor" format="color" />
    <attr name="siBorderWidth" format="dimension" />
    <attr name="siBorderAlpha" format="float" />
    <attr name="siForeground" format="integer|reference" />
    <!--  Rounded Image View-->
    <attr name="siRadius" format="dimension" />
    <!-- BubbleImageView-->
    <attr name="siArrowPosition" />
    <attr name="siTriangleHeight" format="dimension" />
    <!-- PorterImageView-->
    <attr name="siShape" format="integer|reference" />
    <!-- ShaderImageView-->
    <attr name="siBorderType" />
    <attr name="siStrokeCap" />
    <attr name="siStrokeJoin" />
    <attr name="siStrokeMiter" format="dimension" />
</declare-styleable>
<attr name="siArrowPosition">
    <enum name="left" value="0" />
    <enum name="right" value="1" />
</attr>
<attr name="siBorderType">
    <enum name="stroke" value="0" />
    <enum name="fill" value="1" />
</attr>
<attr name="siStrokeCap">
    <enum name="butt" value="0" />
    <enum name="round" value="1" />
    <enum name="square" value="2" />
</attr>
<attr name="siStrokeJoin">
    <enum name="bevel" value="0" />
    <enum name="miter" value="1" />
    <enum name="round" value="2" />
</attr>
IdHelper中定义的方法:

public static int[] getResourceDeclareStyleableIntArray(Context context, String name) {
    try {
        //use reflection to access the resource class
        Field[] fields2 = Class.forName(context.getPackageName() + ".R$styleable").getFields();

        //browse all fields
        for (Field f : fields2) {
            //pick matching field
            if (f.getName().equals(name)) {
                //return as int array
                return (int[]) f.get(null);
            }
        }
    } catch (Throwable t) {
        t.printStackTrace();
    }

    return null;
}
public static int getAttr(Context context, String attrName) {
    return context.getResources().getIdentifier(attrName, "attr",
            context.getApplicationContext().getPackageName());
}
当我运行我的应用程序时,我得到了日志:

01-11 17:04:07.244 3744-3744/?W/System.err:由以下原因引起:java.lang.reflect.InvocationTargetException 01-11 17:04:07.247 3744-3744/? W/System.err:at java.lang.reflect.Constructor.constructNative(本机方法) 01-11 17:04:07.247 3744-3744/? W/System.err:at java.lang.reflect.Constructor.newInstance(Constructor.java:423) 01-11 17:04:07.247 3744-3744/? W/System.err:at-android.view.LayoutInflater.createView(LayoutInflater.java:594) 01-11 17:04:07.247 3744-3744/? W/System.err:。。。57多 01-11 17:04:07.247 3744-3744/? W/System.err:原因:java.lang.UnsupportedOperationException:无法转换为维度:type=0x10 01-11 17:04:07.252 3744-3744/? W/System.err:at-android.content.res.TypedArray.getDimensionPixelSize(TypedArray.java:464) 01-11 17:04:07.252 3744-3744/? W/System.err:cn.jmessage.android.uikit.chatting.shader.ShaderHelper.init(ShaderHelper.java:80) 01-11 17:04:07.252 3744-3744/? W/System.err:cn.jmessage.android.uikit.chating.shader.BubbleShader.init(BubbleShader.java:45) 01-11 17:04:07.253 3744-3744/? W/System.err:cn.jmessage.android.uikit.chating.ShaderImageView.setup(ShaderImageView.java:45) 01-11 17:04:07.253 3744-3744/? W/System.err:cn.jmessage.android.uikit.chating.ShaderImageView。(ShaderImageView.java:36) 01-11 17:04:07.253 3744-3744/? W/System.err:cn.jmessage.android.uikit.chatting.BubbleImageView。(BubbleImageView.java:27) 01-11 17:04:07.253 3744-3744/? W/System.err:。。。60多


我怎样才能解决这个问题?

我已经解决了这个问题。在attrs文件中定义的declare styleable属性,经过解析后,将在R文件中生成一个int数组。在我的例子中,数组如下所示:

       @see #ShaderImageView_siArrowPosition
       @see #ShaderImageView_siBorderAlpha
       @see #ShaderImageView_siBorderColor
       @see #ShaderImageView_siBorderType
       @see #ShaderImageView_siBorderWidth
       @see #ShaderImageView_siForeground
       @see #ShaderImageView_siRadius
       @see #ShaderImageView_siShape
       @see #ShaderImageView_siSquare
       @see #ShaderImageView_siStrokeCap
       @see #ShaderImageView_siStrokeJoin
       @see #ShaderImageView_siStrokeMiter
       @see #ShaderImageView_siTriangleHeight
     */
    public static final int[] ShaderImageView = {
        0x7f010001, 0x7f010002, 0x7f010003, 0x7f010004,
        0x7f01000c, 0x7f01000d, 0x7f01000e, 0x7f01000f,
        0x7f010010, 0x7f010011, 0x7f010012, 0x7f010013,
        0x7f010014
    };
注意这个数组的顺序,是按照字母的升序排列的,所以我可以使用这种方法来获取属性值:

public void init(Context context, AttributeSet attrs, int defStyle) {
    if(attrs != null){
        int[] declareStyleableArray = IdHelper.getResourceDeclareStyleableIntArray(context, "ShaderImageView");
        if (declareStyleableArray != null && declareStyleableArray.length > 0) {
            TypedArray typedArray = context.obtainStyledAttributes(attrs, declareStyleableArray, defStyle, 0);
            square = typedArray.getBoolean(8, square);
            borderColor = typedArray.getColor(2, borderColor);
            borderWidth = typedArray.getDimensionPixelSize(4, borderWidth);
            borderAlpha = typedArray.getFloat(1, borderAlpha);
            typedArray.recycle();
        }

    }
注意这一行:square=typedArray.getBoolean(8,square)第一个参数是8,这是在R文件中生成的数组ShaderImageView中属性“ShaderImageView_siSquare”的顺序。这意味着,如果在attrs文件中定义自定义的declare styleable集,则定义的顺序可能与解析后在R文件中生成的顺序不同,如果使用R获取属性值,如:

square = typedArray.getBoolean(R.styleable.ShaderImageView_siSquare, square);
那么订单就不用担心了。 希望我的案例能对其他人有所帮助

public void init(Context context, AttributeSet attrs, int defStyle) {
    if(attrs != null){
        int[] declareStyleableArray = IdHelper.getResourceDeclareStyleableIntArray(context, "ShaderImageView");
        if (declareStyleableArray != null && declareStyleableArray.length > 0) {
            TypedArray typedArray = context.obtainStyledAttributes(attrs, declareStyleableArray, defStyle, 0);
            square = typedArray.getBoolean(8, square);
            borderColor = typedArray.getColor(2, borderColor);
            borderWidth = typedArray.getDimensionPixelSize(4, borderWidth);
            borderAlpha = typedArray.getFloat(1, borderAlpha);
            typedArray.recycle();
        }

    }
square = typedArray.getBoolean(R.styleable.ShaderImageView_siSquare, square);