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

yizhihongxing

当我们继承自 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日

相关文章

  • bootstrap基础知识学习笔记

    下面我将详细讲解 bootstrap 基础知识的学习笔记。 1. 基础概念 1.1 什么是Bootstrap? Bootstrap 是 Twitter 公司开发的一个用于开发响应式布局、移动设备优先的前端框架,它基于 HTML、CSS 和 JavaScript。Bootstrap 提供了一个全面、强大的基础样式和组件,使得开发者能够快速搭建漂亮、直观的 We…

    other 2023年6月27日
    00
  • 深入分析C++中声明与定义的区别

    深入分析C++中声明与定义的区别 在C++中,声明和定义都是C++语言中的重要概念,它们指的是编程中使用变量、函数、类等元素时的两种不同的操作。这两个概念在程序中有着不同的作用,因此C++程序员需要清楚它们之间的区别。 声明和定义的区别主要体现在以下几个方面: 1.含义 声明:仅是向编译器声明某个变量、函数或类的存在,告诉编译器该变量、函数或类在当前代码文件…

    other 2023年6月26日
    00
  • Android Studio自定义万能注释模板与创建类,方法注释模板操作

    首先,我们需要了解什么是注释模板。注释模板就是在编写代码时,自动生成的注释文本模板。在Android Studio中,我们可以通过自定义注释模板来提高代码的可读性,减少注释时间。 一、自定义万能注释模板 Android Studio默认提供了一些常见注释模板,如类的注释,方法的注释等。但是,我们可以自定义更多的注释模板,以适应我们的实际开发需求。 打开And…

    other 2023年6月25日
    00
  • ASP.NET 动态写入服务器端控件第1/2页

    ASP.NET 动态写入服务器端控件是一种在服务器端动态生成和添加控件到网页的方法。这种方法可以实现更灵活的控制,使页面更具交互性和可操作性。本文将详细讲解如何实现动态写入服务器端控件。 准备工作 为实现动态写入服务器端控件,首先需要在网页中定义一个容器,例如一个 div 标签,用来添加动态生成的服务器端控件。 <div id="contai…

    other 2023年6月27日
    00
  • 目标跟踪之卡尔曼滤波—理解Kalman滤波的使用预测

    目标跟踪之卡尔曼滤波—理解Kalman滤波的使用预测 卡尔曼滤波是一种用于估计系统状态的算法,它可以通过观测数据和系统模型来预测未来的状态。在目标跟踪中,卡尔曼滤波可以用于预测目标的位置和速度,从而实现目标跟踪。本文将介绍卡尔曼滤波的基本概念、使用方法和两个示例说明。 基本概念 1. 状态空间模型 卡尔曼滤波是一种基于状态空间模型的算法,它将系统的状态表…

    other 2023年5月5日
    00
  • NestScrollView嵌套RecyclerView实现淘宝首页滑动效果

    NestScrollView嵌套RecyclerView实现淘宝首页滑动效果攻略 在实现淘宝首页滑动效果时,可以使用NestScrollView嵌套RecyclerView的方式来实现。下面是详细的攻略: 步骤一:布局文件 首先,在布局文件中定义一个NestScrollView,并在其中添加一个RecyclerView作为子项。示例代码如下: <and…

    other 2023年7月28日
    00
  • 二个android模拟器互发短信程序演示

    二个android模拟器互发短信程序演示攻略 简介 本攻略将详细讲解如何使用两个Android模拟器互相发送短信的程序演示。这个演示可以帮助你了解Android模拟器之间的通信机制,并且可以用于测试和开发短信相关的应用程序。 步骤 安装Android模拟器 首先,你需要安装两个Android模拟器。你可以选择使用Android Studio自带的模拟器,或者…

    other 2023年9月5日
    00
  • Bootstrap中的fileinput 多图片上传及编辑功能

    “Bootstrap中的fileinput 多图片上传及编辑功能”是一个非常有用的功能,它可以帮助我们在页面中实现上传、删除、编辑多张图片的功能。下面我将详细讲解在Bootstrap中如何实现这个功能。 使用Bootstrap中的fileinput插件 要实现多图片上传及编辑功能,我们需要使用Bootstrap中的fileinput插件。这个插件可以将一个i…

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