Android之探究viewGroup自定义子属性参数的获取流程
来源:互联网 发布:java socket 发送数据 编辑:程序博客网 时间:2024/05/17 22:11
通常会疑惑,当使用不同的布局方式时,子view得布局属性就不太一样,比如当父布局是LinearLayout时,子view就能有效的使用它的一些布局属性如layout_weight、weightSum、等;当使用的是RelativeLayout时,其子view就能使用属于它的有效的属性;当然使用FrameLayout时,其属性集就少多了,也就常说的FrameLayout是最简单的布局方式了。
简单的说我们就是想要实现自定的属性可以再子view里面使用。
那么我们先来探索下ViewGroup中的LayoutParams吧。
viewGroup也是继承自view,主要是实现布局容器。
那么它有个内部基类LayoutParams。当然,这个viewGroup中的LayoutParams是所有的FrameLayout、RelativeLayout、、、的LayoutParams的基础类。当继承后,子layoutParams就拥有了父亲的所有的属性集合
这个类注释了,是用于view去告诉他们的父布局他们想咋滴,也就是说这个是子view和父布局的通讯方式吧
现在来看看ViewGroup中的addView的实现流程
public void addView(View child, int index) { ... LayoutParams params = child.getLayoutParams; if (params == null) { params = generateDefaultLayoutParams; .... } addView(child, index, params); }
public void addView(View child, int index, LayoutParams params) {...addViewInner(child, index, params, false);}private void addViewInner(View child, int index, LayoutParams params,
boolean preventRequestLayout) {...if (!checkLayoutParams(params)) {params = generateLayoutParams(params);}if (preventRequestLayout) {child.mLayoutParams = params;} else {child.setLayoutParams(params);}
}
通过整个addview的片段流程可以看到。
首先是checkLayoutParams,目的是检测这个参数是否为空,如果为空的话就给它生成一个普通的LayoutParams;
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { return p != null; }
protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {return p;}
public LayoutParams generateLayoutParams(AttributeSet attrs) {return new LayoutParams(getContext, attrs);}
可以得到前面两个方法protected主要是给子类去实现的,第三个方法是公开的。还是有些蹊跷的。所以要实现布局参数转换成自定义的参数,这三个方法就显得尤为重要了。
最后把这个params赋予子view,那么params是谁实现的,子view中的mLayoutParams就是什么类型的。这就是为什么我们在代码中改变view的LayoutParams时,把它转换成其他类型了就会报错的原因。
当然最为容易明白的还是先去研究下FrameLayout吧,因为这个类看下来不过300行代码。它其中的FrameLayout.LayoutParams中自定义了一个Gravity属性。
public static class LayoutParams extends MarginLayoutParams { public int gravity = -1; public LayoutParams(Context c, AttributeSet attrs) { super(c, attrs); TypedArray a = c.obtainStyledAttributes(attrs, com.android.internal.R.styleable.FrameLayout_Layout); gravity = a.getInt(com.android.internal.R.styleable.FrameLayout_Layout_layout_gravity, -1); a.recycle; } public LayoutParams(int width, int height) { super(width, height); } public LayoutParams(int width, int height, int gravity) { super(width, height); this.gravity = gravity; } .... public LayoutParams(LayoutParams source) { super(source); this.gravity = source.gravity; } }
并且也实现了add流程中所提的三个方法:
@Override public LayoutParams generateLayoutParams(AttributeSet attrs) { return new FrameLayout.LayoutParams(getContext, attrs); } @Override protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { return p instanceof LayoutParams; } @Override protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { return new LayoutParams(p); }
最后FrameLayout才能在OnMeasure或者onLayout方法中对子view 进行大展身手:
研究完了原理后,我也实现了一下这个动作,也得到了一些对方法的使用猜测
代码如下:
/** * 自定义测试viewgroup ,探究viewgroup中的addview的流程,已经子view中属性的获取 * Created by taofuxn on 2016/12/27. */public class ViewPropertiesLayout extends ViewGroup { public ViewPropertiesLayout(Context context) { super(context); } public ViewPropertiesLayout(Context context, AttributeSet attrs) { super(context, attrs); } public ViewPropertiesLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected boolean checkLayoutParams(LayoutParams p) { boolean b = p instanceof LayoutParams; Log.i("AAA","checkLayoutParams "+b); return b; } //没调用,当在xml布局中加载的时候不会调用这个方法 @Override protected LayoutParams generateLayoutParams(LayoutParams p) { Log.i("AAA","generateLayoutParams p"); return new MyLayoutParam(p); } //这个方法是通过传入的属性集合生成相应的LayouParams .在viewgroup中是找不到调用的地方,我估计是xml解析的时候调用这个方法并赋予属性集合来生成params. //因为通过addview的流程和这里的打印log可以看到是先调用这个方法生成了params,再去checklayout方法,最后再把转换的这个对象赋予给了子view的params @Override public LayoutParams generateLayoutParams(AttributeSet attrs) { Log.i("AAA","generateLayoutParams attrs"); return new MyLayoutParam(getContext,attrs); } //onmeasure,在viewgroup中是没有对子view进行测量的处理的,所有在onlayout中是获取不到子view的宽高 @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { for (int i = 0 ; i < getChildCount ; i++){ View child = getChildAt(i); child.layout(l,t,r,100); //将子view的布局参数强行转换为本布局中自定义的LayoutParams,能这么做的原因是addview里面对子params进行了generate MyLayoutParam lp = (MyLayoutParam) child.getLayoutParams; child.setBackgroundColor(lp.color); } } public class MyLayoutParam extends LayoutParams{ private int color ; public MyLayoutParam(Context c, AttributeSet attrs) { super(c, attrs); TypedArray a = c.obtainStyledAttributes(attrs,R.styleable.custom); color = a.getColor(R.styleable.custom_layout_bg, Color.CYAN); a.recycle; } public MyLayoutParam(int width, int height) { super(width, height); } public MyLayoutParam(MyLayoutParam source) { super(source); this.color = source.color ; } public MyLayoutParam(LayoutParams source){ super(source); } }}
1 <?xml version="1.0" encoding="utf-8"?> 2 <com.example.administrator.viewproperties.ViewPropertiesLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:app="http://schemas.android.com/apk/res-auto" 4 android:id="@+id/activity_main" 5 android:layout_width="match_parent" 6 android:layout_height="match_parent" 7 > 8 9 <TextView10 android:layout_width="wrap_content"11 android:layout_height="wrap_content"12 app:layout_bg="@color/colorAccent"13 android:textSize="20sp"14 android:text="Hello World!" />15 </com.example.administrator.viewproperties.ViewPropertiesLayout>
这个布局只在xml中应用,所有会调用public 的generateLayoutParams(atters)方法来给子view生成自定义的布局参数MyLayoutParam.那么他的执行顺序如下:
只有当子view的layoutparams不是MyLayoutParams的实例时才会调用,generateLayoutParma(p)这个方法生成一个属于自定义布局属性
这样的话我的这自定义布局就有了自己布局参数。感觉比自定义view的自定义属性高大上了很多。
我的探索可能有些错误。希望大神盛情指导
本文为头条号作者发布,不代表今日头条立场。
- Android之探究viewGroup自定义子属性参数的获取流程
- 自定义ViewGroup获取子View参数
- Android自定义View或ViewGroup的流程
- 探究Android中通过继承ViewGroup自定义控件的原理
- 探究Android中通过继承ViewGroup自定义控件的原理
- android之自定义ViewGroup
- Android之自定义ViewGroup
- Android之自定义ViewGroup
- Android之自定义ViewGroup
- Android 自定义View、ViewGroup(二)之绘制流程
- Android自定义ViewGroup时子view的释放
- Android自定义ViewGroup添加组合控件的子view
- Android自定义ViewGroup的基本流程及用法演示
- ViewGroup之android:animateLayoutChanges属性
- Android 学习之--自定义ViewGroup
- Android学习之自定义ViewGroup
- Android之自定义属性简单使用-----获取自定义属性
- Android自定义ViewGroup的总结
- 商品系统设计(三):商品属性设计之固定属性
- linux 安装turnserver
- .Net导出Excel存在服务器端
- Tomcat的下载与安装以及配置到Eclipse中
- 使用QXDesigner可视化开发RIA系统(一)
- Android之探究viewGroup自定义子属性参数的获取流程
- Convolutional Neural Networks卷积神经网络
- Spring AOP 实现机制和原理详解
- TextView属性之行间距设置
- elasticsearch之watcher插件安装文档
- C++学习笔记3(From慕课网)
- ES 常用管理REST API (持续更新)
- Android解惑之Handler为什么需要是static的
- CorelDRAW怎么等分分割图片