Android读取系统控件的自定义属性
2017-02-25 21:09
405 查看
读取自定义属性
通常读取自定义控件的自定义属性是在自定义控件的构造函数中用context的obtainStyledAttributes方法获取TpyeArray对象,通过TpyeArray对象获取个自定义属性,最后别忘了recycle()。
attrs.xml
当系统控件中带有自定义属性如何读取?
方法一:利用LayoutParams
当自定义控件是ViewGroup的子控件时且带有自定义属性的系统控件是其内,如下布局
首先了解下generateLayoutParams()方法,为父容器生成
子view 的布局LayoutParams在Layoutinflater.rInflate()中被调用
如果一个View想要被添加到这个容器中,这个view可以调用此方法生成和容器类匹配的布局LayoutParams;
那么可以在自定义控件中重写generateLayoutParams()方法生成自定义的LayoutParams类对象从而达到读取自定义属性。
布局文件
通过源码看出LayoutInflater.inflate()方法会调用createViewFromTag()---->mFactory.onCreateView(name,context,attrs)
只要重写Factory.onCreateView()就能得到控件的AttributeSet属性对象
通常读取自定义控件的自定义属性是在自定义控件的构造函数中用context的obtainStyledAttributes方法获取TpyeArray对象,通过TpyeArray对象获取个自定义属性,最后别忘了recycle()。
attrs.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="MyViewGroup" > <attr name="x_in" format="float"/> <attr name="y_in" format="float"/> </declare-styleable> </resources>自定义控件
public MyViewGroup(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray array=context.obtainStyledAttributes(attrs,R.styleable.MyViewGroup); x_in=array.getFloat(R.styleable.MyViewGroup_x_in,0); y_in=array.getFloat(R.styleable.MyViewGroup_y_in,0); array.recycle(); }
当系统控件中带有自定义属性如何读取?
<ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@mipmap/ic_launcher" vg:x_in="0.2" vg:y_in="0.3" />
方法一:利用LayoutParams
当自定义控件是ViewGroup的子控件时且带有自定义属性的系统控件是其内,如下布局
<com.znvoid.blogs.MyViewGroup
android:id="@+id/myview"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@mipmap/ic_launcher" vg:x_in="0.2" vg:y_in="0.3" />
</com.znvoid.blogs.MyViewGroup>
首先了解下generateLayoutParams()方法,为父容器生成
子view 的布局LayoutParams在Layoutinflater.rInflate()中被调用
public LayoutParams generateLayoutParams(AttributeSet attrs) { return new LayoutParams(getContext(), attrs); }
如果一个View想要被添加到这个容器中,这个view可以调用此方法生成和容器类匹配的布局LayoutParams;
那么可以在自定义控件中重写generateLayoutParams()方法生成自定义的LayoutParams类对象从而达到读取自定义属性。
@Override public LayoutParams generateLayoutParams(AttributeSet attrs) { return new MyLayoutParams(getContext(), attrs); } class MyLayoutParams extends LayoutParams{ public float x_in; public float y_in; public MyLayoutParams(Context c, AttributeSet attrs) { super(c, attrs); TypedArray array=c.obtainStyledAttributes(attrs,R.styleable.MyViewGroup); x_in=array.getFloat(R.styleable.MyViewGroup_x_in,0); y_in=array.getFloat(R.styleable.MyViewGroup_y_in,0); //System.out.println("x_in"+x_in); array.recycle(); } }方法二 LayoutInflater
布局文件
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@mipmap/ic_launcher" app:x_in="1.2" app:y_in="2.3"/> </RelativeLayout>先看LayoutInflater.inflate()源码
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) { return inflate(resource, root, root != null); }
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) { final Resources res = getContext().getResources(); if (DEBUG) { Log.d(TAG, "INFLATING from resource: \"" + res.getResourceName(resource) + "\" (" + Integer.toHexString(resource) + ")"); } final XmlResourceParser parser = res.getLayout(resource); try { return inflate(parser, root, attachToRoot); } finally { parser.close(); } }
public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) { synchronized (mConstructorArgs) { Trace.traceBegin(Trace.TRACE_TAG_VIEW, "inflate"); //省略代码...... // Temp is the root view that was found in the xml final View temp = createViewFromTag(root, name, inflaterContext, attrs);
//省略代码......}}
View createViewFromTag(View parent, String name, Context context, AttributeSet attrs, boolean ignoreThemeAttr) {
//省略代码......try { View view; if (mFactory2 != null) { view = mFactory2.onCreateView(parent, name, context, attrs); } else if (mFactory != null) { view = mFactory.onCreateView(name, context, attrs); } else { view = null; } if (view == null && mPrivateFactory != null) { view = mPrivateFactory.onCreateView(parent, name, context, attrs); }
//省略代码......}
通过源码看出LayoutInflater.inflate()方法会调用createViewFromTag()---->mFactory.onCreateView(name,context,attrs)
只要重写Factory.onCreateView()就能得到控件的AttributeSet属性对象
* * 自定义布局加载器 */ public class MyLayoutInflater extends LayoutInflater { public MyLayoutInflater( Context newContext) { super( newContext); setFactory(new MyFatory()); } public MyLayoutInflater(LayoutInflater original, Context newContext) { super(original, newContext); setFactory2(new MyFactory2()); } @Override public LayoutInflater cloneInContext(Context newContext) { return new MyLayoutInflater(this, newContext); } public class MyFatory implements LayoutInflater.Factory { @Override public View onCreateView(String name, Context context, AttributeSet attrs) { return doCreateView(name,context,attrs); } // } public View doCreateView(String name, Context context, AttributeSet attrs) { View view = null; if (name.contains(".")) {//自定义控件生成 view = doCreateViewWithPackage(name, null, context, attrs); } else {//系统控件的生成 if ((view = doCreateViewWithPackage(name, "android.view.", context, attrs)) == null) view = doCreateViewWithPackage(name, "android.widget.", context, attrs); } if (view != null) {//自定义属性的读取 TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.MyViewGroup); float x_in = array.getFloat(R.styleable.MyViewGroup_x_in, 0); float y_in = array.getFloat(R.styleable.MyViewGroup_y_in, 0); System.out.println("x_in的值:" + x_in); array.recycle(); } return view; } private View doCreateViewWithPackage(String name, String prefix, Context context, AttributeSet attrs) {//根据控件名创建控件对象 try { return MyLayoutInflater.this.createView(name, prefix, attrs); } catch (ClassNotFoundException e) { //e.printStackTrace(); } return null; } class MyFactory2 implements Factory2 { @Override public View onCreateView(View parent, String name, Context context, AttributeSet attrs) { return onCreateView(name,context,attrs); } @Override public View onCreateView(String name, Context context, AttributeSet attrs) { return doCreateView(name,context,attrs); } } }用自定义布局加载器去加载带有自定义属性的系统控件的布局就能读取其中的自定义属性
相关文章推荐
- Android 自定义属性,系统控件扩展
- Android 自定义属性,系统控件扩展
- Android 自定义属性,系统控件扩展
- Android 自定义属性,系统控件扩展
- Android 自定义属性,系统控件扩展
- Android 自定义属性,系统控件扩展
- android 自定义视图控件属性
- Android C 语言读取系统属性
- Android进阶——自定义View之必学的系统控件架构及自定义控件概述
- android自定义滑动开关控件,适合所有的android系统
- android之视频播放系统VideoView和自定义VideoView控件的应用
- Android进阶——自定义View之继承系统控件实现自带删除按钮动画效果和软键盘自动悬浮于文本框下方
- Android 重写系统控件UI,自定义进度条
- android之视频播放系统VideoView和自定义VideoView控件的应用
- android之视频播放系统VideoView和自定义VideoView控件的应用
- Android 从0开始自定义控件之 自定义属性详解(十一)
- Android系统setting中读取apk的属性
- android 系统控件及其自定义---ViewPager
- Android使用属性动画如何自定义倒计时控件详解
- Android进阶——自定义View之扩展系统控件的另一种思路实现渐变文字动画的TextView