解析:继承ViewGroup后的子类如何重写onMeasure方法

当我们继承自 ViewGroup 后,需要重写 onMeasure() 方法来计算并设置该布局的子 View 布局参数,在该方法中,会通过 MeasureSpec 来获取父布局传递的测量模式和大小值,我们需要根据这些值来确定子 View 的大小和位置。

下面是重写 onMeasure() 方法的步骤:

1.实现该方法

我们需要在子类中重写该方法并在其中编写测量布局的代码。例如下面这个示例中:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    // 根据传递过来的测量模式和大小值计算子 View 的大小和位置
    // ...
    super.onMeasure(widthMeasureSpec, heightMeasureSpec); // 调用父类方法保存测量大小
}

2.测量子 View 大小和位置

我们需要在该方法内根据测量模式和大小值计算并设置子 View 的大小和位置。测量子 View 的大小和位置可以通过 MeasureSpec 的静态方法进行,分 3 种:

  • MeasureSpec.EXACTLY:如果指定该模式,则子 View 的大小将完全按照指定大小进行测量。
  • MeasureSpec.AT_MOST:如果指定该模式,则子 View 的大小不能超过指定大小,否则会进行缩放。
  • MeasureSpec.UNSPECIFIED:如果指定该模式,则子 View 大小没有限制。

3.设置子 View 的布局参数

在计算子 View 的大小和位置之后,我们需要设置他们的布局参数以便进行布局,需要使用 ViewGroup.LayoutParams 构造方法创建一个 LayoutParams 对象,并设置参数值,例如:

childView.setLayoutParams(new LayoutParams(width, height));

下面是一个完整的例子,它是一个简单的自定义 ViewGroup,它包含了两个子 View,并将其排列在一行中:

public class MyViewGroup extends ViewGroup {
    // 子 View 的宽和高
    private int childWidth = 200;
    private int childHeight = 50;

    public MyViewGroup(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = 0;
        int height = 0;
        int count = getChildCount();
        // 测量所有子 View 的最大宽度和高度
        for (int i = 0; i < count; i++) {
            View child = getChildAt(i);
            measureChild(child, widthMeasureSpec, heightMeasureSpec);
            LayoutParams lp = (LayoutParams) child.getLayoutParams();
            width += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
            height = Math.max(height, child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);
        }
        // 使用测量得到的最大宽度和高度,设置自身 View 的布局参数
        setMeasuredDimension(resolveSize(width, widthMeasureSpec),
                             resolveSize(height, heightMeasureSpec));
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        // 将子 View 竖向排列
        int count = getChildCount();
        int left = 0;
        int top = 0;
        for (int i = 0; i < count; i++) {
            View child = getChildAt(i);
            LayoutParams lp = (LayoutParams) child.getLayoutParams();
            left += lp.leftMargin;
            top += lp.topMargin;
            child.layout(left, top, left + child.getMeasuredWidth(), top + child.getMeasuredHeight());
            left += child.getMeasuredWidth() + lp.rightMargin + lp.leftMargin;
        }
    }

    @Override
    protected LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    }

    @Override
    protected LayoutParams generateLayoutParams(LayoutParams p) {
        return new LayoutParams(p);
    }

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new LayoutParams(getContext(), attrs);
    }

    @Override
    protected boolean checkLayoutParams(LayoutParams p) {
        return p instanceof LayoutParams;
    }

    public static class LayoutParams extends MarginLayoutParams {

        public LayoutParams(Context c, AttributeSet attrs) {
            super(c, attrs);
        }

        public LayoutParams(int width, int height) {
            super(width, height);
        }

        public LayoutParams(MarginLayoutParams source) {
            super(source);
        }

        public LayoutParams(LayoutParams source) {
            super(source);
        }
    }
}

在上面的例子中,我们通过继承 ViewGroup 并实现 onMeasure()onLayout() 方法,来计算并布局子 View。在 onMeasure() 方法中,我们测量了子 View 的最大宽度和高度,然后将计算结果设置为自身 View 的布局参数,最后在 onLayout() 方法中将子 View 水平排列。我们还重写了其他几个方法以便支持 ViewGroup 参数。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:解析:继承ViewGroup后的子类如何重写onMeasure方法 - Python技术站

(0)
上一篇 2023年6月26日
下一篇 2023年6月26日

相关文章

  • 好人共享的一个万能Ghost系统制作教程附相关软件下载第3/3页

    首先,感谢您对我们网站的关注。我们的Ghost系统制作教程涉及了以下内容: 第一步:准备工作 在开始制作Ghost系统之前,我们需要做以下准备工作: 下载Ghost系统安装包 准备一个可引导的U盘或DVD 下载Ghost系统制作软件 第二步:制作Ghost系统 接下来,我们将逐步制作Ghost系统: 使用Ghost系统制作软件,选择要制作的镜像文件。 选择要…

    other 2023年6月27日
    00
  • CAD怎么创建块和分解块?

    以下是在CAD软件中创建块和分解块的完整攻略: 创建块 打开CAD软件,并打开您要创建块的绘图文件。 选择要创建块的对象,可以是单个对象或多个对象。 在CAD软件的菜单栏中,找到“编辑”或“修改”等选项,点击打开下拉菜单。 在下拉菜单中,找到“创建块”或类似的选项,点击进入块创建界面。 在块创建界面中,输入块的名称,并根据需要设置其他属性,如插入点、旋转角度…

    other 2023年10月16日
    00
  • xnconvert图片转换工具

    XnConvert图片转换工具的完整攻略 XnConvert是一款免费的图片转换工具,支持多种图片格式的转换和批量处理。本文将详细介绍XnConvert的使用方法,并提供两个示例说明以帮助您更好地了解和应用这个工具。 下载和安装 访问XnConvert官网(https://www.xnview.com/en/xnconvert/)。 点击“Download”…

    other 2023年5月7日
    00
  • JAVA Stack详细介绍和示例学习

    JAVA Stack详细介绍和示例学习 什么是JAVA Stack 在JAVA编程中,Stack表示“堆栈”的数据结构,是一种先进后出(Last In First Out, LIFO)的数据集合。堆栈是一种限制性的线性结构,限制仅在堆栈的一端进行插入和删除操作。插入操作称为入栈(Push),删除操作称为出栈(Pop),即堆栈的访问是只能在一个端口进行。 JA…

    other 2023年6月26日
    00
  • ubuntu怎么查询网关

    在Ubuntu中,可以使用ip命令来查询网关。以下是使用Ubuntu查询网关的完整攻略: 步骤1:打开终端 首先,需要打开终。可以使用快捷键Ctrl + Alt + T打开终端,也可以应用程序菜单中找到终端并打开。 步骤2:查询网关 在终端中,使用以下命令查询网关: ip route | grep default 上面的命令使用ip命令查询路由表,并使用gr…

    other 2023年5月7日
    00
  • js判断数组中是否包含某个元素(转载)

    JS判断数组中是否包含某个元素(转载) 在JavaScript中,我们经常需要判断一个数组中是否包含某个指定的元素,本文将介绍几种实现该功能的方法。 方法一:使用indexOf方法 JavaScript提供了indexOf方法,该方法返回要查找的元素在数组中第一次出现的位置,如果找不到,返回-1。我们可以利用这个特性来实现判断一个数组中是否包含某个元素的功能…

    其他 2023年3月29日
    00
  • vmware网络设置详解

    VMware网络设置详解 在VMware虚拟机中,网络设置非常关键。正确的网络配置可以确保虚拟机与外部网络之间的通信正常,并能实现更多的功能。本文将详细介绍VMware网络设置的各种选项和配置,以帮助您更好地理解和配置VMware网络。 虚拟网络介绍 在VMware中,虚拟网络是连接虚拟机和外部网络的接口。VMware提供了三种不同类型的虚拟网络: 桥接模式…

    其他 2023年3月28日
    00
  • word2016替换文字时怎么区分大小写?

    当使用Word 2016替换文字时,可以通过以下步骤区分大小写: 打开Word 2016并打开要编辑的文档。 点击顶部菜单栏中的“编辑”选项。 在下拉菜单中选择“查找”选项,或者使用快捷键Ctrl + F打开查找对话框。 在查找对话框中,输入要查找的文字,并点击“查找下一个”按钮。 如果要区分大小写,点击查找对话框中的“更多”按钮。 在弹出的更多选项中,勾选…

    other 2023年8月16日
    00
合作推广
合作推广
分享本页
返回顶部