自定义View之重写onMeasure

一、重写onMeasure()来修改已有的View的尺寸

步骤

  1. 重写 onMeasure(),并调用 super.onMeasure() 触发原先的测量
  2. 用 getMeasuredWidth() 和 getMeasuredHeight() 取到之前测得的尺寸,利用这两个尺寸来计算出最终尺寸
  3. 使用 setMeasuredDimension() 保存尺寸

代码:

@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {//先执行原测量算法super.onMeasure(widthMeasureSpec, heightMeasureSpec);//获取原先的测量结果int measureWidth=getMeasuredWidth();int measureHeight=getMeasuredHeight();//利用原先的测量结果计算出新的尺寸if(measureWidth>measureHeight){measureWidth=measureHeight;}else{measureHeight=measureWidth;}//保存计算后的结果setMeasuredDimension(measureWidth,measureHeight);}
​

二、重写onMeasure()来全新计算自定义View的尺寸

步骤:

  1. 重写 onMeasure0) 把尺寸计算出来
  2. 把计算的结果用 resolveSize() 过滤一遍后保存

  @Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {...measuredWidth=...;measuredHeight=...;measuredWidth=resolveSize(measuredWidth,widthMeasureSpec);measuredHeight=resolveSize(measuredHeight,heightMeasureSpec);setMeasuredDimension(measuredWidth,measuredHeight);}

       onMeasure()方法的两个参数 widthMeasureSpec和heightMeasureSpec是父View对子View的尺寸限制,子View在计算自己尺寸的时候,需要遵守这两个参数所包含的限制MeasureSpec。

理解MeasureSpec

在 Android 中,View 的大小是由父容器和 View 自身的测量规格(MeasureSpec)共同决定的。

MeasureSpec 由大小和测量模式组成,测量模式有三种取值:

  1. UNSPECIFIED(未指定):父容器对子 View 没有施加任何限制,子 View 可以任意大小。

  2. EXACTLY(精确):父容器已经为子 View 精确指定了大小,子 View 应该匹配这个大小。

  3. AT_MOST(至多):子 View 可以是任何大小,但不能超过父容器指定的大小。

MeasureSpec 是通过静态方法 MeasureSpec.makeMeasureSpec() 创建的,该方法接受两个参数:大小和测量模式。在自定义 View 或者自定义布局中,我们通常会使用 MeasureSpec 来测量子 View 的大小,并根据测量模式来决定子 View 的大小。

在自定义 View 中,我们通常会在 onMeasure() 方法中使用 MeasureSpec 来测量 View 的大小。在这个方法中,我们可以通过 MeasureSpec.getMode() 和 MeasureSpec.getSize() 方法来获取测量模式和大小,然后根据这些信息来确定 View 的最终大小。

解释resolveSize()这个方法:

//代码简化,不是源码
public static int resolveSize(int size, int measureSpec) {final int specMode = MeasureSpec.getMode(measureSpec);final int specSize = MeasureSpec.getSize(measureSpec);switch (specMode) {case MeasureSpec.AT_MOST:if (specSize < size) {result = specSize | MEASURED_STATE_TOO_SMALL;} else {result = size;}break;case MeasureSpec.EXACTLY:result = specSize;break;case MeasureSpec.UNSPECIFIED:default:result = size;}
}

resolveSize()这个方法,父View传进来的尺寸限制measureSpec是由类型和尺寸值组成的,首先要调用MeasureSpec.getMode(measureSpec)方法和MeasureSpec.getSize(measureSpec)方法获取限制measureSpec的类型mode和size尺寸值。

限制的类型mode:

MeasureSpec.AT_MOST 限制上线

MeasureSpec.EXACTLY 限制固定尺寸

MeasureSpec.UNSPECIFIED 无限制

三、重写onMeasure()和onLayout()来全新计算自定义ViewGroup的内部布局

onMeasure()的重写,对于ViewGroup来说,包含三部分内容:

步骤:

  1. 调用每个子View的measure(),让子View自我测量
  2. 根据子View给出的尺寸,得出子View的位置,并保存它们的位置和尺寸
  3. 根据子View的位置和尺寸计算出自己的尺寸,并用setMeasuredDimension()保存

理解LayoutParams

       在父View里调用子View的getLayoutParams()方法,可以获得一个LayoutParams对象,它包含了xml文件里的layout_打头的参数的对应值,其中它的width和height这两个属性就分别对应了layout_width和layout_height的值,并且是转换过了的值。

    @Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
​for(int i=0;i<getChildCount();i++){View childView=getChildAt(i);LayoutParams lp=childView.getLayoutParams();//lp.height   lp.width}}

结合自己的可用空间来计算出对子View的宽度和高度的限制

可以根据layout_width和layout_height的值,分成三种情况:

第一种情况:固定值

不需要考虑可用空间的问题,直接用EXACTLY把子View尺寸限制为这个固定值就可以了。

第二种情况:match_parent

把子View的尺寸限制为固定值可用宽度或者高度

可用空间的判断方法:

根据自己的MeasureSpec中mode的不同:

1.EXACTLY/AT_MOST   可用空间:MeasureSpec中的size

2.UNSPECIFIED     可用空间:无限大

第三种情况:wrap_content

不能超过父View的边界的情况下,子View自己测量

public class SomeView extends ViewGroup {
...@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {...for(int i=0;i<getChildCount();i++){View childView=getChildAt(i);LayoutParams lp=childView.getLayoutParams();int selfwidthSpecMode=MeasureSpec.getMode(widthMeasureSpec);int selfwidthSpecSize=MeasureSpec.getSize(widthMeasureSpec);switch (lp.width){case MATCH_PARENT:if(selfwidthSpecMode==EXACTLY||selfwidthSpecMode==MeasureSpec.AT_MOST){childWidthSpec=MeasureSpec.makeMeasureSpec(selfwidthSpecSize-usedWidth,EXACTLY);}else{childWidthSpec=MeasureSpec.makeMeasureSpec(0,MeasureSpec.UNSPECIFIED);}break;case  WRAP_CONTENT:if(selfwidthSpecMode==EXACTLY||selfwidthSpecMode==MeasureSpec.AT_MOST){childWidthSpec=MeasureSpec.makeMeasureSpec(selfwidthSpecSize-usedWidth,MeasureSpec.AT_MOST);}else{childWidthSpec=MeasureSpec.makeMeasureSpec(0,MeasureSpec.UNSPECIFIED);}break;default:childWidthSpec=MeasureSpec.makeMeasureSpec(lp.width, EXACTLY);break;}}}
}

关于保存子View位置的两点说明

1.不是所有的Layout都需要保存子View的位置(因为有的Layout可以在布局阶段实时推导出子View的位置,例如LinearLayout)

2.有时候对某些子View需要重复测量两次或多次才能得到正确的尺寸和位置

重写onLayout()来摆放子View

    @Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {for(int i=0;i<getChildCount();i++){View childView=getChildAt(i);childView.layout(childLeft[i],childTop[i],childRight[i],childBottom[i]);}}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/603772.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

鱼类识别Python+深度学习人工智能+TensorFlow+卷积神经网络算法

一、介绍 鱼类识别系统。使用Python作为主要编程语言开发&#xff0c;通过收集常见的30种鱼类&#xff08;‘墨鱼’, ‘多宝鱼’, ‘带鱼’, ‘石斑鱼’, ‘秋刀鱼’, ‘章鱼’, ‘红鱼’, ‘罗非鱼’, ‘胖头鱼’, ‘草鱼’, ‘银鱼’, ‘青鱼’, ‘马头鱼’, ‘鱿鱼’, ‘鲇…

基于JAVA的中小学教师课程排课系统 开源项目

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 角色管理模块2.2 课程档案模块2.3 排课位置模块2.4 排课申请模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 角色表3.2.2 课程表3.2.3 排课位置表3.2.4 排课申请表 四、系统展示五、核心代码5.1 查询课程5.2 新增课…

CentOS-7安装Docker

0.安装Docker Docker 分为 CE 和 EE 两大版本。CE 即社区版&#xff08;免费&#xff0c;支持周期 7 个月&#xff09;&#xff0c;EE 即企业版&#xff0c;强调安全&#xff0c;付费使用&#xff0c;支持周期 24 个月。 Docker CE 分为 stable test 和 nightly 三个更新频道…

2.7 SUMMARY

本章提供了CUDA C编程模型的快速、简化的概述。CUDA扩展C语言以支持并行计算。在本章中&#xff0c;我们讨论了这些扩展的基本子集。为了您的方便&#xff0c;我们将本章中讨论的扩展总结如下&#xff1a; FUNCTION DECLARATIONS CUDA C扩展了C函数声明语法&#xff0c;以支持…

Open3D 读写并显示PLY文件 (2)

Open3D 读写并显示PLY文件 &#xff08;2&#xff09; 一、算法介绍二、算法实现1.代码2.注意 一、算法介绍 读取PLY文件中的点云坐标&#xff0c;写出到新的文件中&#xff0c;并显示在屏幕上。 二、算法实现 1.代码 import open3d as o3dprint("读取点云") pl…

深信服技术认证“SCSA-S”划重点:文件包含漏洞

为帮助大家更加系统化地学习网络安全知识&#xff0c;以及更高效地通过深信服安全服务认证工程师考核&#xff0c;深信服特别推出“SCSA-S认证备考秘笈”共十期内容&#xff0c;“考试重点”内容框架&#xff0c;帮助大家快速get重点知识~ 划重点来啦 *点击图片放大展示 深信服…

西电期末1028.信号解调

一.题目 二.分析与思路 题越来越水了 三.代码实现 #include<bits/stdc.h>//万能头 int main() {int n;int a,b;//坐标for(int i0;i<n;i){scanf("%d%d",&a,&b);if((a-4)*(a-4)(b-4)*(b-4)>(a4)*(a4)(b4)*(b4))printf("2 ");else pri…

小游戏实战丨基于PyGame的俄罗斯方块小游戏

文章目录 写在前面PyGame五子棋注意事项系列文章写在后面 写在前面 本期内容&#xff1a;基于pygame的俄罗斯方块小游戏 下载地址&#xff1a;https://download.csdn.net/download/m0_68111267/88700182 实验环境 python3.11及以上pycharmtkinter PyGame Pygame是一个非常…

GPT(Generative Pre-Training)论文解读及源码实现(二)

本篇为gpt2的pytorch实现&#xff0c;参考 nanoGPT nanoGPT如何使用见后面第5节 1 数据准备及预处理 data/shakespeare/prepare.py 文件源码分析 1.1 数据划分 下载数据后90%作为训练集&#xff0c;10%作为验证集 with open(input_file_path, r) as f:data f.read() n …

MySQL数据库主从复制和读写分离

目录 一、MySQL主从复制和读写分离理论 &#xff08;一&#xff09;读写分离 1.什么是读写分离 2.为什么要读写分离 3.什么时候要读写分离 4.读写分离原理 5.常见MySQL 读写分离 &#xff08;1&#xff09;基于程序代码内部实现 &#xff08;2&#xff09;基于中间代理…

react-hooks-kit v1 正式发布

evanpatchouli/react-hooks-kit - (npmjs.com) v1.0.0 正式发布&#xff01; 下载安装 npm i evanpatchouli/react-hooks-it -S官方文档 在 Gitee 阅读在 Github 阅读 概览 这是一个无依赖的轻量级 React Hooks 库&#xff0c;总共有 60 hooks。 它包含了一系列易于使用…

持续积累ThreadLocal技术【ThreadLocal原理 + ThreadLocal的坑 + ThreadLocal的最佳实践】

持续积累ThreadLocal技术的目录 一、先从使用ThreadLocal开始1、我看到的两种创建方式1.1 ThreadLocal<A> aThreadLocal new ThreadLocal<>();1.2 ThreadLocal<A> aThreadLocal ThreadLocal.withInitial(...)1.3 为啥需要1.2提到的创建方式&#xff1f;直接…

k8s的pod基础

pod概念 pod是k8s中最小的资源管理组件。 pod也是最小化运行容器化的应用的资源管理对象。 pod是一个抽象的概念&#xff0c;可以理解为一个或者多个容器化应用的集合。 在一个pod当中运行一个容器是最常用的方式。在一个pod当中同时运行多个容器&#xff0c;在一个pod当中…

算法练习Day29 (Leetcode/Python-动态规划)

基本概念&#xff1a; 代码随想录&#xff1a; Dynamic Programming&#xff0c;简称DP&#xff0c;如果某一问题有很多重叠子问题&#xff0c;使用动态规划是最有效的。 所以动态规划中每一个状态一定是由上一个状态推导出来的&#xff0c;这一点就区分于贪心&#xff0c;贪…

计算机网络 综合(习题)

【计算机网络习题】系列文章目录 计算机网络 第一章 绪论(习题) 计算机网络 第二章 计算机网络体系结构(习题) 计算机网络 第三章 应用层(习题) 计算机网络 第四章 运输层(习题) 计算机网络 第五章 网络层(习题) 计算机网络 第六章 数据链路层(习题) 计算机网络 第七章 物…

强化学习5——动态规划在强化学习中的应用

动态规划在强化学习中的应用 基于动态规划的算法优良 &#xff1a;策略迭代和价值迭代。 策略迭代分为策略评估和策略提升&#xff0c;使用贝尔曼期望方程得到一个策略的状态价值函数&#xff1b;价值迭代直接使用贝尔曼最优方程进行动态规划&#xff0c;得到最终的最优状态价…

Unity 一文掌握使用AddListener方法为组件事件添加监听器的方法

在Unity中&#xff0c;很多组件都带有事件&#xff0c;比如: Button组件&#xff1a;onClick() Toggle组件&#xff1a;On Value Changed(Boolean) Dropdown组件&#xff1a;On Value Changed(Int32) InputField组件&#xff1a;On Value Changed(String)、On End Edit(Stri…

CCC数字钥匙设计【NFC】--NFC通信之APDU TLV

CCC3.0&#xff0c;包含NFC、BLE、UWB技术。当采用NFC通信时&#xff0c;车端与手机端是通过APDU来进行交互的。而在APDU中的data数据段&#xff0c;又可能会嵌入TLV协议的数据&#xff0c;以完成车端与手机端的通信交互。 本文先介绍APDU及TLV的一些基础知识&#xff0c;再通…

断更后的故事1

文章目录 技术男为何开始写感悟博客&#xff1f;简单的自我介绍为什么断更了默默进化的日子琐碎的事情对阶段1的思索和总结 技术男为何开始写感悟博客&#xff1f; 其实我是一个偏感性的一个技术男&#xff0c;可能这样就有点违背技术男这个定义了&#xff0c;很多时候还是挺理…

全连接网络、卷积神经网络、递归神经网络 通俗的解释

全连接网络、卷积神经网络和递归神经网络是三种不同类型的神经网络&#xff0c;它们在结构和应用上有所不同。下面我将尽量用通俗易懂的语言来解释和对比这三种神经网络。 1.全连接网络 全连接网络是一种最常见的神经网络类型&#xff0c;它的每一层都由许多神经元组成&#…