LayoutParams是ViewGroup的一个内部类,声明方式如下

public static class LayoutParams {public static final int MATCH_PARENT = -1;public static final int WRAP_CONTENT = -2;public int width;public int height;public LayoutParams(Context c, AttributeSet attrs) {TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.ViewGroup_Layout);setBaseAttributes(a,R.styleable.ViewGroup_Layout_layout_width, R.styleable.ViewGroup_Layout_layout_height);a.recycle();}public LayoutParams(int width, int height) {this.width = width;this.height = height;}public LayoutParams(LayoutParams source) {this.width = source.width;this.height = source.height;}}

可以分析到,系统默认为ViewGroup自定义了宽高属性width和height,将其获取方式封装在LayoutParams中,系统考虑所有的View肯定都有宽高,所以就直接统一定义了,有一个疑问为啥不定义在View中,因为子View定义的宽高都是layout_width,layout_height,都是相对于父容器的
接下来分析,系统是如何将这个统一的ViewGroup.LayoutParams宽高属性给到View的呢?

阅读源码布局中View的加载流程,主要分析LayoutInflater#inflate这一步

public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {final View temp = createViewFromTag(root, name, inflaterContext, attrs);ViewGroup.LayoutParams params = null;if (root != null) {params = root.generateLayoutParams(attrs);if (!attachToRoot) {temp.setLayoutParams(params);}}
}

分析关键代码,是root(ViewGroup)调用了generateLayoutParams(AttributeSet attrs);解析attrs中的layout_width和layout_height属性,将其值封装到了LayoutParams中,之后调用子View的setLayoutParams方法设置到子View中,之后子View就可以获取到width和height了

所以默认情况下父容器的generateLayoutParams只是解析layout_width和layout_height。如果子view需要支持margin属性,不重写父容器的generateLayoutParams的话,之后是子View是获取不到margin属性的

再分析下ViewGroup#generateDefaultLayoutParams,在上面我们分析了ViewGroup#generateLayoutParams它是作用在xml布局解析阶段为子View设置LayoutParams,那么ViewGroup#generateDefaultLayoutParams则是在代码中ViewGroup#addView中调用,我们看下源码

public void addView(View child, int index) {if (child == null) {throw new IllegalArgumentException("Cannot add a null child view to a ViewGroup");}LayoutParams params = child.getLayoutParams();if (params == null) {params = generateDefaultLayoutParams();if (params == null) {throw new IllegalArgumentException("generateDefaultLayoutParams() cannot return null");}}addView(child, index, params);
}

分析源码得知,generateDefaultLayoutParams的调用确实在动态addView中,同样的它也是默认创建的ViewGroup.LayoutParams,只支持width和height的

再分析下ViewGroup#generateLayoutParams(LayoutParams p),分析ViewGroup#addViewInner源码

private void addViewInner(View child, int index, LayoutParams params,boolean preventRequestLayout) {if (!checkLayoutParams(params)) {params = generateLayoutParams(params);}
}

分析可以知道,在addViewInner中会对params进行校验,如果不合法则调用generateLayoutParams(params)帮我们生成一个合法的LayoutParams.我们看下校验规则

protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {return  p != null;
}

ViewGroup默认的校验规则仅仅是不为空,相关宽松,LinearLayout等一般都会重写,有兴趣可以看源码

再分析下ViewGroup默认的generateLayoutParams(ViewGroup.LayoutParams p)实现

protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {return p;
}

仅仅是返回了这个不合法的params,这并不是我们期望的,所以这个用法一般是我们重写checkLayoutParams实现合法的校验规则,然后在重写generateLayoutParams创建合法的LayoutParams,看下LinearLayout的实现

@Override
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {return p instanceof LinearLayout.LayoutParams;
}
@Override
protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) {if (sPreserveMarginParamsInLayoutParamConversion) {if (lp instanceof LayoutParams) {return new LayoutParams((LayoutParams) lp);} else if (lp instanceof MarginLayoutParams) {return new LayoutParams((MarginLayoutParams) lp);}}return new LayoutParams(lp);
}

前面分析了ViewGroup默认的LayoutParams只是支持layout_width和layout_height属性的,因为它内部只有获取这两个属性的逻辑,但是我们实际很多子View都是需要支持margin属性的,怎么办呢?

ViewGroup还为我们定义了一个MarginLayoutParams,是不是相当的便利

public static class MarginLayoutParams extends ViewGroup.LayoutParams {public int leftMargin;public int topMargin;public int rightMargin;public int bottomMargin;public MarginLayoutParams(Context c, AttributeSet attrs) {super();...//省略若干获取margin属性操作代码}}

所以如果我们需要子View支持margin属性,那么我们就可以重写ViewGroup#generateLayoutParams(AttributeSet attrs)和ViewGroup#generateDefaultLayoutParams()返回MarginLayoutParams

问题来了,我如果还想让子View支持更多的属性呢?那么我们可以自定义LayoutParams继承自MarginLayoutParams,在构造方法中书写获取我们自定义属性的逻辑,同样重写上面两个方法,返回我们自定义的LayoutParams,这样子View就可以获取到了

ViewGroup的LayoutParams理解相关推荐

  1. LayoutParams理解和使用

    文章目录 LayoutParams的理解 ViewGroup.MarginLayoutParams 常见的添加View的方式 栗子1:动态修改布局 栗子2:RelativeLayout相对位置设置 栗 ...

  2. Layoutparams理解

    一. layoutparams是什么 LayoutParams继承于Android.View.ViewGroup.LayoutParams LayoutParams只是ViewGroup的一个内部类 ...

  3. android 自定义图片容器,Android应用开发中自定义ViewGroup视图容器的教程

    一.概述在写代码之前,我必须得问几个问题: 1.ViewGroup的职责是啥?ViewGroup相当于一个放置View的容器,并且我们在写布局xml的时候,会告诉容器(凡是以layout为开头的属性, ...

  4. View与ViewGroup

    文章目录 1. `View`和`ViewGroup`的关系 2. 坐标获取 3. View的滑动 3.1 案例`layout()` 3.2 案例`offsetLeftAndRight & of ...

  5. 对 AbsoluteLayout 的一点理解

    菜鸟记录一下,把之前的笔记抄到这里 /*** A layout that lets you specify exact locations (x/y coordinates) of its* chil ...

  6. 自定义控件知识储备-LayoutParams的那些事

    在上一篇文章里,我总结了一下自定义控件需要了解的基础知识:View的绘制流程--<自定义控件知识储备-View的绘制流程>.其中,在View的测量流程里,View的测量宽高是由父控件的Me ...

  7. Android LayoutParams详解

    提示:本文的源码均取自Android 7.0 前言 在平时的开发过程中,我们一般是通过XML文件去定义布局,所以对于LayoutParams的使用可能相对较少.但是在需要动态改变View的布局参数(比 ...

  8. Android之WindowManager.LayoutParams介绍

    image.png .. LayoutParams WindowManager.LayoutParams 是 WindowManager 接口的嵌套类:继承于 ViewGroup.LayoutPara ...

  9. Android 手把手教您自定义ViewGroup

    最近由于工作的变动,导致的博客的更新计划有点被打乱,希望可以尽快脉动回来~ 今天给大家带来一篇自定义ViewGroup的教程,说白了,就是教大家如何自定义ViewGroup,如果你对自定义ViewGr ...

  10. android 自定义控件央视,Android自定义ViewGroup之第一次接触ViewGroup

    整理总结自鸿洋的博客:http://blog.csdn.net/lmj623565791/article/details/38339817/ 一.com.cctvjiatao.customviewgr ...

最新文章

  1. mysql optimize_真正实现千人千面?教你用Optimize收割精准流量
  2. C++用数组和链表分别实现Queue
  3. 原创 | 专家对话:大数据助力健康管理面临的机遇与挑战
  4. AspectJ的实现机制
  5. position定位 响应式_使用 Vue3 实现双盒子定位 Overlay
  6. LeetCode 11. 盛最多水的容器(双指针)
  7. STL_算法_元素计数(count、count_if)
  8. C#设计模式---模板方法模式(Template Method Pattern)
  9. Application_Start 不执行
  10. git遇到的问题解决方案
  11. 磁力链接地址生成教程
  12. 结构化设计和模块设计
  13. 颜色代码:网页颜色代码大全及色彩搭配教程
  14. (MATLAB)错误使用 xlsread (line 260) 无法激活 Excel 工作表
  15. 二维码解析:使用 JavaScript 库reqrcode.js解析二维码
  16. 大数据-玩转数据-MaxCompute 字符串函数
  17. 普通石粉的用途_“石粉”的多种用途
  18. 低成本 低功耗2.4G无线SOC芯片 nRF51802 低功耗 高性价比芯片
  19. c++链表先进先出和先进后出的简单写法
  20. notepad++鼠标卡住,无法编辑文字

热门文章

  1. 详细介绍如何使用MATLAB中的机器人工具箱建立机器人模型(DH法建模)(机械臂)
  2. 【mysql】复制一张表的数据到另一张表
  3. 欧洲批准最强粒子对撞机计划,造价210亿欧元,全长100公里,耗资巨大引争议...
  4. 句法分析(成分句法分析)(依存句法分析)
  5. linux配置tp路由器,手把手图解教程tplink r402m路由器配置
  6. javascript动态插入html元素
  7. 8-2SpringDataJpa
  8. ADC噪声全面分析 -01- ADC噪声的类型以及ADC特性
  9. 域名抢注流程是什么?
  10. QT编译Python问题:During startup program exited with code 0xc0000135