对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代码。