自定义 ViewGroup 的时候,关于 LayoutParams 有哪些注意事项?

本文探讨在自定义ViewGroup时如何正确处理LayoutParams。内容包括LayoutParams的作用,如何创建并重写相关方法,如generateDefaultLayoutParams、checkLayoutParams和onMeasure。同时,讲解了如何自定义LayoutParams属性,以及在构造函数中获取这些属性的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原始网页直通车


LayoutParams

子View 通过 LayoutParams 告诉 ViewGroup 应该如何放置自己,主要用来协助 ViewGroup 进行布局。

在自定义 ViewGroup 的过程中,如果需要定义 LayoutParams 的话,首先要创建一个类(通常是静态内部类),并继承自 ViewGroup.LayoutParams 或其子类。

ViewGroup 中,我们需要重写几个方法:

  1. generateDefaultLayoutParams()
  2. generateLayoutParams(ViewGroup.LayoutParams p)
  3. checkLayoutParams(ViewGroup.LayoutParams p)
  • 第一个方法,顾名思义,是生成默认的 LayoutParams 。这个方法会在往 ViewGroup 中添加 子View 时被调用(如果该 子ViewLayoutParams 为空,或者没有直接调用有 LayoutParams 参数的 addView() 方法的话)。
  • 第二个方法,在 ViewGroup 添加 子View 的过程中,往往和第三个方法 checkLayoutParams() 配合使用, 这个 checkLayoutParams() 就是检查传进来的 LayoutParams 是否合法。怎么样算合法,就要看怎么重写了。默认的实现是做个非空检查。如果检查到传进来的 LayoutParams 不合法,接着就会调用这个 generateLayoutParams() 方法。
  • 第三个方法, 虽说不重写,在一般情况下也不会报错,但还是建议重写,并且在里面判断这个传进来的 LayoutParams 是不是你自定义的 LayoutParams

自定义 LayoutParams 属性

自定义 LayoutParams 就像自定义 View 属性那样,在 attrs.xml 中去定义一些需要用到的属性,这个 styleable 的命名格式一般为: ViewGroup名_Layout

<resources>
    <declare-styleable name="SimpleViewGroup_Layout">
        <!-- 自定义的属性 -->
        <attr name="layout_simple_attr" format="integer" />
        <!-- 使用系统预置的属性 -->
        <attr name="android:layout_gravity" />
    </declare-styleable>
</resources>

回到自定义 LayoutParams 中,找到 (Context c, AttributeSet attrs) 这个构造方法,在这里面就可以获取到自定义的属性了。

public static class SimpleLayoutParams extends ViewGroup.MarginLayoutParams {

    public int simpleAttr;
    public int gravity;

    public SimpleLayoutParams(Context c, AttributeSet attrs) {
        super(c, attrs);
        // 解析布局属性
        TypedArray typedArray = c.obtainStyledAttributes(attrs, R.styleable.SimpleViewGroup_Layout);
        simpleAttr = typedArray.getInteger(R.styleable.SimpleViewGroup_Layout_layout_simple_attr, 0);
        gravity=typedArray.getInteger(R.styleable.SimpleViewGroup_Layout_android_layout_gravity, -1);
				//释放资源
        typedArray.recycle();
    }

    // ...
}

最后回到 ViewGroup 中,重写 generateLayoutParams(AttributeSet attrs) 方法(该方法主要用于 inflate 处理)。

@Override
public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) { 
    return new SimpleViewGroup.SimpleLayoutParams(getContext(), attrs);
}
/**
 * 解析XML文件中的View
 * @param parser 解析器
 * @param root 父容器(可能为null)
 * @param attachToRoot View是否需要附加到父容器中
 */
public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {
    // ...
    View result = root;
    // ...
    final String name = parser.getName();

    if (TAG_MERGE.equals(name)) { // 针对<merge>标签
        // ...
    } else { // 针对普通标签
        // ...
        ViewGroup.LayoutParams params = null;
        if (root != null) {
            // 通过XML中的布局参数生成对应的LayoutParams
            params = root.generateLayoutParams(attrs);
            // ...
        }
				// ...
    }
    // ...
    return result;
}

参考

Android LayoutParams详解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值