SVG适配_使用反射获取自定义属性中TypedArray中的资源ID

对SVG不熟悉的同学可以查看 SVG详解

我们在自定义属性的时候代码如下:

 <com.lj.schedule.ui.view.RichTextClock
       android:layout_width="wrap_content"
         android:layout_height="40dp"
         android:layout_marginBottom="8dp"
         android:layout_marginStart="16dp"
         android:layout_marginTop="8dp"
         android:gravity="center_vertical"
         android:textColor="@color/tool_titleColor"
         app:drawable_height="20dp"
         app:drawable_location="top"
         app:drawable_src="@drawable/ic_icon_clock"
         app:drawable_width="20dp"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent" />

app:drawable_src=”@drawable/ic_icon_clock”使用的位图资源,在自定义View中如何获取呢?

 public RichText(Context context, AttributeSet attrs) {
        super(context, attrs);

        TypedArray a = context.obtainStyledAttributes(attrs,
                R.styleable.RichText);
        mWidth = a
                .getDimensionPixelSize(R.styleable.RichText_drawable_width, 0);
        mHeight = a.getDimensionPixelSize(R.styleable.RichText_drawable_height,
                0);
//        mDrawable = a.getDrawable(R.styleable.RichText_drawable_src);

        int index = R.styleable.RichText_drawable_src;

        try {
            Class typedArrayClass =  Class.forName("android.content.res.TypedArray");
            Field[] farray = typedArrayClass.getDeclaredFields();
            Field f = typedArrayClass.getDeclaredField("mData");
            f.setAccessible(true);//暴力反射,解除私有限定
            int[] mData = (int[]) f.get(a);
            final TypedValue value = new TypedValue();
            //执行getValueAt方法
            Method getValueAt = typedArrayClass.getDeclaredMethod("getValueAt", int.class, TypedValue.class);
            getValueAt.setAccessible(true);//解除私有限定
            boolean result = (boolean) getValueAt.invoke(a,index*6, value);//需要两个参数,一个是要调用的对象(获取有反射),一个是实参
            if (result) {
                if (value.type == TypedValue.TYPE_ATTRIBUTE) {
                    throw new UnsupportedOperationException(
                            "Failed to resolve attribute at index " + index + ": " + value);
                }
                mDrawable = VectorDrawableCompat.create(getResources(), value.resourceId, null);

//                if (density > 0) {
//                    // If the density is overridden, the value in the TypedArray will not reflect this.
//                    // Do a separate lookup of the resourceId with the density override.
//                    mResources.getValueForDensity(value.resourceId, density, value, true);
//                }
//                return mResources.loadDrawable(value, value.resourceId, density, mTheme);
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        mLocation = a.getInt(R.styleable.RichText_drawable_location, LEFT);

        a.recycle();
        //绘制Drawable宽高,位置
        drawDrawable(mDrawable);

    }

其中 // mDrawable = a.getDrawable(R.styleable.RichText_drawable_src); 在就5.0+的版本中可一正常使用,但是在5.0以下的版本中就会报错。

解决方案使用 mDrawable = VectorDrawableCompat.create(getResources(), value.resourceId, null); 但是这个value.resourceId需要通过反射才能获取:

 int index = R.styleable.RichText_drawable_src;

        try {
            Class typedArrayClass =  Class.forName("android.content.res.TypedArray");
            Field[] farray = typedArrayClass.getDeclaredFields();
            Field f = typedArrayClass.getDeclaredField("mData");
            f.setAccessible(true);//暴力反射,解除私有限定
            int[] mData = (int[]) f.get(a);
            final TypedValue value = new TypedValue();
            //执行getValueAt方法
            Method getValueAt = typedArrayClass.getDeclaredMethod("getValueAt", int.class, TypedValue.class);
            getValueAt.setAccessible(true);//解除私有限定
            boolean result = (boolean) getValueAt.invoke(a,index*6, value);//需要两个参数,一个是要调用的对象(获取有反射),一个是实参
            if (result) {
                if (value.type == TypedValue.TYPE_ATTRIBUTE) {
                    throw new UnsupportedOperationException(
                            "Failed to resolve attribute at index " + index + ": " + value);
                }
                mDrawable = VectorDrawableCompat.create(getResources(), value.resourceId, null);
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

上面是通过反射获取资源ID代码。

猜你喜欢

转载自blog.csdn.net/liujian8654562/article/details/80400843
今日推荐