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

相关文章

  • Ubuntu配置NFS的具体流程(推荐)

    下面是Ubuntu配置NFS的具体流程: 步骤一:安装NFS 首先需要确保你的Ubuntu已经安装了NFS。 sudo apt-get update sudo apt-get install nfs-kernel-server nfs-common 步骤二:创建共享目录 在这一步中,你需要创建一个共享目录,用来存放需要共享的文件。在这里,我们将创建一个名为“…

    other 2023年6月27日
    00
  • 孤岛惊魂5出现granite2000000怎么办 出现granite2000000错误代码解决办法

    当玩家在玩“孤岛惊魂5”这个游戏时,可能会遇到granite2000000错误代码的问题,导致游戏无法正常进行。下面是解决这个问题的完整攻略: 1. 什么是granite2000000错误代码 Granite2000000是“孤岛惊魂5”游戏中常见的错误代码之一。它通常在尝试进入游戏而由于某些原因无法启动时出现。Granite2000000的意思是 “无法访…

    other 2023年6月27日
    00
  • 一种简单的实现:Android一键换肤功能

    一种简单的实现:Android一键换肤功能 Android的一键换肤功能对于许多用户来说可以提供更好的使用体验,但是多数实现方式较为复杂,需要进行大量的代码修改和复制,使得实现过程相当麻烦。本篇文章将介绍一种简单的实现方式,帮助开发人员快速完成Android一键换肤功能。 实现原理 一种简单的实现Android一键换肤功能的方式包括以下几个步骤: 定义皮肤资…

    其他 2023年3月28日
    00
  • 【mybatis】mybatis中update更新操作 null字段不更新 有…

    【mybatis】mybatis中update更新操作 null字段不更新 有哪些解决方案? 在Mybatis中,我们经常需要使用update语句来更新数据库中的数据,但是在数据更新时,有时候我们并不想更新所有字段,比如某些字段的值为null,我们不希望将null值更新到数据库中。那么,在Mybatis中,该如何实现null字段不更新的功能呢?本文将为大家介…

    其他 2023年3月28日
    00
  • 正则表达式截取字符串的方法技巧

    正则表达式是一种强大的字符串处理工具,可以用于匹配、搜索、替换等各种操作。它的语法通常比较复杂,但在掌握了一些基本技巧后,使用起来也会变得相对简单。 在截取字符串时,正则表达式可以用于匹配需要的字符,然后从中提取出想要的部分。下面就让我们来看看具体的方法和技巧。 一、基本语法 正则表达式的基本语法包含了一些元字符和特殊字符,比如 []、{}、()、*、+、?…

    other 2023年6月20日
    00
  • MySql如何将查询的出来的字段进行转换

    MySQL提供了多种函数,可以对查询出来的字段进行转换。下面是一些常用的转换函数及其使用方法: 1. CONCAT() CONCAT() 用于将多个字符串连接成一个字符串。语法: CONCAT(string1, string2, …, stringN) 示例: SELECT CONCAT(‘Hello’, ‘ ‘, ‘World’); 结果为: ‘Hel…

    other 2023年6月25日
    00
  • VBS读取配置文件配置项的实现代码

    如何读取配置文件配置项的实现代码主要分为以下几个步骤: 读取配置文件名: ‘读取配置文件名 Dim configFile configFile = "config.ini" 首先,我们需要定义一个变量来存储配置文件的名字,这里我们将配置文件名设置为config.ini。config.ini文件正确放置在VBS文件的同一目录下。 读取配置项…

    other 2023年6月25日
    00
  • 删除pycharm鼠标右键快捷键打开项目的操作

    要删除PyCharm鼠标右键快捷键打开项目的操作,可以按照以下步骤进行: 步骤 1:打开 PyCharm 设置 打开 PyCharm 时,可以在菜单栏中点击 “File”,然后选择 “Settings” 或者按下快捷键 “Ctrl+Alt+S” 打开 PyCharm 设置。 步骤 2:进入 Keymap 设置 在 PyCharm 设置中,打开 Keymap …

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