解析:继承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日

相关文章

  • vue中设置、获取、删除cookie的方法

    Vue中设置、获取、删除Cookie的方法 在Vue中,可以使用document.cookie来设置、获取和删除Cookie。下面是详细的攻略: 设置Cookie 要设置Cookie,可以使用document.cookie属性。Cookie是一个字符串,它由键值对组成,每个键值对之间使用分号和空格进行分隔。以下是设置Cookie的方法: // 设置Cooki…

    other 2023年7月29日
    00
  • centos修改host配置

    CentOS修改host配置攻略 在CentOS中,修改host配置可以帮助我们实现域名解析和网络连接。本攻略将详细介绍如何在CentOS中修改host。 步骤 以下是在CentOS中修改host配置的步骤: 打开终端:在CentOS中,可以通过按下Ctrl+Alt+T组合键打开终端。 2.换到root用户:在终端中输入以下命令,切换到root用户: bas…

    other 2023年5月6日
    00
  • java技巧:反射判断field类型的操作

    Java技巧: 反射判断Field类型的操作 简介 在Java中,反射是一个非常有用的工具,它可以在运行时获取和操作类、方法、字段等的信息。在某些情况下,我们可能需要判断一个字段(Field)的类型,以便进行进一步的操作。本文将介绍如何使用反射来判断Field的类型。 步骤 以下是判断Field类型的操作步骤: 步骤1:获取类的Class对象 首先,我们需要…

    other 2023年6月28日
    00
  • SpringBoot集成Jasypt敏感信息加密的操作方法

    下面我将详细讲解“SpringBoot集成Jasypt敏感信息加密的操作方法”的完整攻略。这份攻略分为以下几个部分: Jasypt简介和使用场景 集成Jasypt加密到SpringBoot应用 添加加密注解和使用示例 修改配置文件中的敏感信息为加密的值 1. Jasypt简介和使用场景 Jasypt是一个用于加密和解密敏感数据的Java框架,其提供了各种加密…

    other 2023年6月26日
    00
  • 详细了解java监听器和过滤器

    详细了解Java监听器和过滤器攻略 1. Java监听器 Java监听器是一种用于监听特定事件并采取相应行动的机制。它们广泛应用于Java Web应用程序中,用于处理用户请求、会话管理、错误处理等。下面是详细了解Java监听器的步骤: 步骤1:创建监听器类 首先,您需要创建一个实现特定监听器接口的Java类。常见的监听器接口包括ServletContextL…

    other 2023年7月27日
    00
  • c#数组的排序

    C#数组的排序 在C#中,排序算法是最常用的算法之一,因为它可以用于操作各种类型的数据结构。 数组是其中一种最常见的数据结构,因此在本文中,我们将重点介绍如何在C#中对数组进行排序。 排序算法 在介绍如何对数组进行排序之前,我们需要先了解一下排序算法。 排序算法是计算机科学中最重要的算法之一。 它是指将一组元素按照特定的顺序排列的过程。 有多种不同的排序算法…

    其他 2023年3月28日
    00
  • JSON 数字排序多字段排序介绍

    JSON 数字排序多字段排序介绍 简介 JSON是一种基于键值对的轻量级数据交换格式,常用于前后端数据传输。在实际应用中,我们经常需要对JSON数据进行排序,例如对用户信息按照年龄和姓名进行排序,这时就需要使用多字段排序。 数字排序 升序和降序 对于仅包含数字的JSON数据,我们可以使用JavaScript内置的sort()方法进行排序。sort()的默认顺…

    other 2023年6月25日
    00
  • Python中IP地址处理IPy模块的方法

    Python中IP地址处理IPy模块的方法 IPy是一个用于处理IP地址的Python模块,它提供了一些方便的方法来解析、操作和比较IP地址。下面是使用IPy模块的详细攻略。 安装IPy模块 在开始之前,首先需要安装IPy模块。可以使用pip命令来安装: pip install IPy 导入IPy模块 在使用IPy模块之前,需要先导入它: from IPy …

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