自定义View之onLayout方法学习
来源:互联网 发布:手机用的中文编程软件 编辑:程序博客网 时间:2024/05/23 00:10
关于onLayout的学习,也是在基于View视图树的递归调用实现。
本篇想说明的是,不去深究View源码关于onLayout,以及layout方法的实现原理。知道大概,目的是在会用。但是需要了解并掌握View内部关于onLayout方法的相关API使用。
在ViewGroup中,onLayout是一个抽象方法,所以如果继承了ViewGroup类,除了添加构造方法外,还必须要重写onLayout方法。
/** * 当这个view和其子view被分配一个大小和位置时,被layout调用。 * @param changed 当前View的大小和位置改变了 * @param left 左部位置(相对于父视图) * @param top 顶部位置(相对于父视图) * @param right 右部位置(相对于父视图) * @param bottom 底部位置(相对于父视图) */ protected void onLayout(boolean changed, int left, int top, int right, int bottom)此方法是在ViewGroup中的layout方法所调用:
@Override public final void layout(int l, int t, int r, int b) { if (!mSuppressLayout && (mTransition == null || !mTransition.isChangingLayout())) { if (mTransition != null) { mTransition.layoutChange(this); } super.layout(l, t, r, b); } else { // record the fact that we noop'd it; request layout when transition finishes mLayoutCalledWhileSuppressed = true; } }而ViewGroup中的layout方法,是继承自View类当中的layout方法,然后在看一下
View类中layout的方法实现。
/** * 给View和其所有子View分配大小和位置 * * 这是布局的第二个阶段(第一个阶段是测量)。在这个阶段中,每个父视图需要去调用layout去为他所有的子视图确定位置 * 派生的子类不应该重写layout方法,应该重写onLayout方法,在onlayout方法中应该去调用每一个view的layout */ public void layout(int l, int t, int r, int b) { // 将当前视图的左上右下记录为old值(参数中传入的为新的l,t,r,b值) int oldL = mLeft; int oldT = mTop; int oldB = mBottom; int oldR = mRight; // setFrame方法的作用就是将新传入的ltrb属性赋值给View,然后判断当前View大小和位置是否发生了变化并返回 boolean changed = setFrame(l, t, r, b); if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) { // 调用onLayout回调方法,具体实现由重写了onLayout方法的ViewGroup的子类去实现(后面详细说明) onLayout(changed, l, t, r, b); mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED; // 调用所有重写了onLayoutChange监听的方法,通知View大小和位置发生了改变 ListenerInfo li = mListenerInfo; if (li != null && li.mOnLayoutChangeListeners != null) { ArrayList<OnLayoutChangeListener> listenersCopy = (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone(); int numListeners = listenersCopy.size(); for (int i = 0; i < numListeners; ++i) { listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB); } } } mPrivateFlags &= ~PFLAG_FORCE_LAYOUT; }在这里边也有onLayout()方法,在View中的onLayout();中是一个实现了个空方法。
protected void onLayout(boolean changed, int left, int top, int right, int bottom) { }
关于layout,onLayout在View与ViewGroup中就这四个。
我们在ViewGroup中重写onLayout的目的:
就是设置当前View与其所有的子View,在ViewGroup(或其继承ViewGroup的Layout)父布局当中的位置。
在onLayout方法中,我们可以获取当前布局,在父布局当中的位置:
getLeft();//子View左边界到父view左边界的距离getTop();//子View上边界到父view上边界的距离getRight();//子View右边界到父View左边界距离getBottom();//子View下边界到父View上边界距离。
还可以在onMeasure()方法执行后在onLayout方法中,测量出当前布局View,在父布局中的
宽度:getWidth();//在onLayout()方法中取得相对在父布局中的宽、高
高度:getHeight();//取值在getMeasuredHeight()方法之后。
此处要注意区分子View的
childView.getMeasuredWidth();//在onMeasure()方法之后取得View的实际宽、高
childView.getMeasuredHeight();
两个方法取值的区别就在如果View的大小没有超过父布局View的大小,二者是相等的。getWidth() == childView.getMeasuredWidth();
如果childView宽、高大于了父布局的宽、高 则:getWidth() + 超出区域 = childView.getMeasuredWidth();
来源:官方文档。详见jafsldkfj博客。
而计算viewChild在父布局中的位置,可以通过:
viewChild.layout();方法实现View的布局定位。
在ViewGroup中重写onLayout方法,在onLayout方法中对子View,viewChild.layout();布局定位,而layout中又调用了onLayout()方法
所以实现了View视图树递归调用的原理。跟onMeasure类似。
(在ViewGroup中,layout()方法是个final类型,所以不能被子类调用。在ViewGroup中,没有measure,onMeasure方法。)
(在View中,measure()方法是个final类型,也不能被子类调用。但是layout是一个普通方法,onLayout是一个实现了空方法。)
添加点一Tip:
① 在代码注释文档中/**{@hide}*/ 表示该方法不向子类开发,不提供外部使用。顺便可以学习下Java doc注释。
最终的学习,还是为了在项目中灵活运用,实践。
- 自定义View之onLayout方法学习
- 自定义view之layout()与onLayout()方法
- 自定义View(三) 之 onMeasure() onLayout() onDraw()
- 自定义View之onMeasure(),onLayout(),onDraw()
- Android自定义View基础之onLayout详解
- Android 自定义 View 之 onLayout 源码分析
- 自定义view之onMeasure,onLayout,onDraw
- 自定义view中的onLayout
- 自定义view onLayout
- 自定义View中的方法onMeasure,onLayout,onDraw作用
- 自定义View的onMeasure、onLayout
- 自定义View-3-重写onLayout
- 自定义View初探-onLayout详解
- 自定义控件之onLayout()
- 自定义View学习笔记之onMeasure()方法
- 自定义View之OnMeasure方法学习
- 自定义View中的onMeasure,onLayout,onDraw
- 自定义View中的onMeasure,onLayout,onDraw
- MySQL 操作数据表
- [Extjs6]随记 store本地过滤数据显示
- 真正好用的RPC框架rest_rpc正式发布第一个版本
- hdu 4781 Assignment For Princess(构造法)
- PLSQL 设置 里面timestamp显示的格式
- 自定义View之onLayout方法学习
- MySQL 约束
- 微信小程序把玩(二十七)audio组件
- 轮询 长连接
- InnoDB多版本(MVCC)实现简要分析
- ios10 推送读取本地音频文件无效
- MySQL 修改数据表
- Linux-系统管理-ipmitool
- Audroid-studio2.2安装1%与windows不兼容和Error occurred during initialization of VM 的问题