当前位置: 首页 > news >正文

android 怎么自定义view

首先了解view的绘制流程:

所以onmeasure ---测量view  

onlayout---确定view大小----》所以继承ViewGroup必须要重写onlayout,确定子view

而onDraw----是继承view时候需要操作的。

所以:自定义ViewGroup一般是利用现有的组件根据特定的布局方式来组成新的组件。

              自定义View,一般是没有现成的view

序列化,大概有这个意思,不一定对。
自定义序列化: IOT
协议比如:物联网:蓝牙:传递的数据 串口 协议:

onmeasure的测量 是先从子布局开始还是先从父布局开始的?

----根据算法来控制的,比如view pageer就是父布局开始

MeasureSpec是什么

public static class MeasureSpec {private static final int MODE_SHIFT = 30;private static final int MODE_MASK  = 0x3 << MODE_SHIFT;/** @hide */@IntDef({UNSPECIFIED, EXACTLY, AT_MOST})@Retention(RetentionPolicy.SOURCE)public @interface MeasureSpecMode {}

----是view里面的一个类---我们知道int 是32位

------上面代码里的30,就是高两位是00,后面30位---》所以这组成里MeasureSpec

-------高两位表示UNSPECIFIED,EXACTLY,AT_MOST

关于getChildMeasureSpec(int spec, int padding, int childDimension)算法

第一个参数,父亲给的,

第二个参数,父亲的

第三个参数,孩子需要的

-----》根据UNSPECIFIED,EXACTLY,AT_MOST来计算

 public static int getChildMeasureSpec(int spec, int padding, int childDimension) {int specMode = MeasureSpec.getMode(spec);int specSize = MeasureSpec.getSize(spec);int size = Math.max(0, specSize - padding);int resultSize = 0;int resultMode = 0;switch (specMode) {// Parent has imposed an exact size on uscase MeasureSpec.EXACTLY:if (childDimension >= 0) {resultSize = childDimension;resultMode = MeasureSpec.EXACTLY;} else if (childDimension == LayoutParams.MATCH_PARENT) {// Child wants to be our size. So be it.resultSize = size;resultMode = MeasureSpec.EXACTLY;} else if (childDimension == LayoutParams.WRAP_CONTENT) {// Child wants to determine its own size. It can't be// bigger than us.resultSize = size;resultMode = MeasureSpec.AT_MOST;}break;// Parent has imposed a maximum size on uscase MeasureSpec.AT_MOST:if (childDimension >= 0) {// Child wants a specific size... so be itresultSize = childDimension;resultMode = MeasureSpec.EXACTLY;} else if (childDimension == LayoutParams.MATCH_PARENT) {// Child wants to be our size, but our size is not fixed.// Constrain child to not be bigger than us.resultSize = size;resultMode = MeasureSpec.AT_MOST;} else if (childDimension == LayoutParams.WRAP_CONTENT) {// Child wants to determine its own size. It can't be// bigger than us.resultSize = size;resultMode = MeasureSpec.AT_MOST;}break;// Parent asked to see how big we want to becase MeasureSpec.UNSPECIFIED:if (childDimension >= 0) {// Child wants a specific size... let them have itresultSize = childDimension;resultMode = MeasureSpec.EXACTLY;} else if (childDimension == LayoutParams.MATCH_PARENT) {// Child wants to be our size... find out how big it should// beresultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size;resultMode = MeasureSpec.UNSPECIFIED;} else if (childDimension == LayoutParams.WRAP_CONTENT) {// Child wants to determine its own size.... find out how// big it should beresultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size;resultMode = MeasureSpec.UNSPECIFIED;}break;}//noinspection ResourceTypereturn MeasureSpec.makeMeasureSpec(resultSize, resultMode);}

下面是一个流式布局的例子:

 * desc   : 官方FlexboxLayout 流式布局*/
class FlowLayout(context: Context) : ViewGroup(context) {private val mHorizontalSpacing = dp2px(16f) //每个item横向间距private val mVerticalSpacing = dp2px(8f) //每个item竖向间距private  var allLines:MutableList<MutableList<View>> = ArrayList<MutableList<View>>() //记录所有的行,一行一行保存,用于layoutvar lineHeights:ArrayList<Int> = ArrayList()//记录每一行的行高,用于layoutconstructor(context: Context,attrs:AttributeSet):this(context){// 在这里处理从 XML 布局 --序列化格式--建值对}constructor(context: Context, attrs: AttributeSet, defStyle: Int) : this(context, attrs) {// 在这里处理从 XML 布局文件中传入的属性和样式}//初始化,因为是onMeasure递归的方式,所以要放在onMeasureprivate fun clearMeasureParams(){
//        allLines =ArrayList<MutableList<View>>()
//        lineHeights = ArrayList()allLines.clear()lineHeights.clear()}override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {clearMeasureParams()// 内存抖动
//        super.onMeasure(widthMeasureSpec, heightMeasureSpec)//先度量孩子val childCount =childCount//ViewGroup解析父控件给我的宽高val selfWidth = MeasureSpec.getSize(widthMeasureSpec)val selfHeight =MeasureSpec.getSize(heightMeasureSpec)//measure过程中 子view要求的父viewgroup的宽高var parentNeededWidth =0;var parentNeededHeight =0;val linView = ArrayList<View>()var lineWidthUsed =0 //记录这一行的以及使用了多宽的sizevar lineHeight =0 //一行的杭高for (i in 0 until childCount){val childview = getChildAt(i)val childlayoutParams = childview.layoutParamsif (childview.visibility != GONE) {val childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,paddingLeft + paddingRight,childlayoutParams.width)val childHeightMeasureSpec1 = getChildMeasureSpec(heightMeasureSpec,paddingTop + paddingBottom,childlayoutParams.height)childview.measure(childWidthMeasureSpec, childHeightMeasureSpec1)//获取子view的度量高度val childMeasureWidth = childview.measuredWidthval childmeasuredHeight = childview.measuredHeightlinView.add(childview)//是否药换行if (childMeasureWidth + lineWidthUsed + mHorizontalSpacing > selfWidth) {//换行判断当前行所需要的宽和高,所以要记录下来allLines.add(linView)lineHeights.add(lineHeight) //行高。。这个if语句会缺少最后一行,parentNeededHeight = parentNeededHeight + lineHeight + mVerticalSpacingparentNeededWidth =Math.max(parentNeededWidth, lineWidthUsed + mHorizontalSpacing)linView.clear()lineWidthUsed = 0lineHeight = 0}//每行自己的宽高lineWidthUsed = lineWidthUsed + childMeasureWidth + mHorizontalSpacinglineHeight = Math.max(lineHeight, childmeasuredHeight)//最后一行,if (i == childCount - 1) {allLines.add(linView)lineHeights.add(lineHeight)parentNeededHeight = parentNeededHeight + lineHeight + mVerticalSpacingparentNeededWidth =Math.max(parentNeededWidth, lineWidthUsed + mHorizontalSpacing)}}}//度量自己//根据子view的度量结果,来重新度量自己的viewGroup//作为一个viewgroup,他自己也是个view,他的大小也需要根据他的父亲提供的宽高来度量var withmode: Int = MeasureSpec.getMode(widthMeasureSpec)var heightmode: Int = MeasureSpec.getMode(heightMeasureSpec)//确切的值 EXACTLYval realWidth =if(withmode  ==MeasureSpec.EXACTLY) selfWidth else parentNeededWidthval realHeight =if(heightmode  ==MeasureSpec.EXACTLY) selfHeight else parentNeededWidthsetMeasuredDimension(realWidth,realHeight)}override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {val lineCount =allLines.sizevar curl =paddingLeft //左边届var curT= paddingTop //上边界for(i in 0 until lineCount){val Lineviews = allLines.get(i)val lineHeight = lineHeights.get(i)for (j in 0 until Lineviews.size){//其中一行val view = Lineviews.get(j)//这一行的view//计算边界val left =curl //左边届val top= curT //上边界val right = left+measuredWidth//左边届val botton = top +measuredHeight  //上边界view.layout(left,top,right,botton)curl =right+mHorizontalSpacing//下一个左边}curT =curT +lineHeight+mVerticalSpacing //下一个topcurl = paddingLeft //每一个新的行要重制左边届}//        view.layout(left,top,right,bottom)}
}

相关文章:

android 怎么自定义view

首先了解view的绘制流程&#xff1a; 所以onmeasure ---测量view onlayout---确定view大小----》所以继承ViewGroup必须要重写onlayout&#xff0c;确定子view 而onDraw----是继承view时候需要操作的。 所以&#xff1a;自定义ViewGroup一般是利用现有的组件根据特定的布局…...

JavaScript的事件

JavaScript的事件 先写一个test测试函数以查看事件是否触发 function test(){var ddocument.getElementById("tid");console.log("测试成功"d) //控制台输出 }onclick 鼠标单击事件&#xff1a; <input type"button" id"tid" va…...

android 简单快速 自定义dialog(简单好用,不需要设置样式)

1.MyDialog代码&#xff1a; public class MyDialog{private Activity activity;private ViewGroup contentView;private View view;public MyDialog(Activity activity) {this.activityactivity;contentView activity.findViewById(android.R.id.content);viewLayoutInflate…...

JAVA代理模式梳理

什么是代理模式 代理模式&#xff1a;为其他对象提供一种代理&#xff0c;用以控制对这个对象的访问&#xff1b; 我们使用代理对象&#xff0c;可以在不修改目标对象的基础上&#xff0c;增强主业务逻辑&#xff1b;比如说我们的系统中有一个登录接口&#xff0c;我们要对这个…...

推荐几个线上兼职,每天两小时收入几十到一百

在当今数字化时代&#xff0c;居家兼职成为越来越多人的选择。借助互联网和技术的进步&#xff0c;我们能够轻松利用自己的时间和技能在网上赚取额外的收入。本文将为您介绍几个简单而有潜力的居家网上兼职小项目&#xff0c;帮助您实现财务自由。 1.千金宝库做任务赚钱 千金…...

excel封装和ddt D17

1&#xff09;excel封装 openpyxl的操作 2&#xff09;ddt 数据驱动测试 ## openpyxl的操作 1.安装&#xff1a;pip install openpyxl 2.导入 openpyxl&#xff1a; import openpyxl 3.workbook对象&#xff1a;工作簿&#xff0c;openpyxl.load_workbook() 4.sheet对象&a…...

PHP8编译安装

CentOS8编译安装PHP8 PHP&#xff0c;全称Hypertext Preprocessor&#xff08;超文本预处理器&#xff09;&#xff0c;是一种通用开源脚本语言。它特别适合于web开发&#xff0c;并能嵌入HTML中。现在主要用于PHP网站中实现动态网站功能&#xff0c;常规我们使用nginx、apache…...

3D Gaussian Splatting for Real-Time Radiance Field Rendering(慢慢啃,还是挺复杂的)

三个关键要素 从相机配准的过程中得到的稀疏点云开始&#xff0c;使用3D Gaussian表示场景; 3D Gaussian: 是连续体积辐射场能够防止不必要的空空间优化。对 3D Gaussion进行交叉优化和密度控制: 优化各向异性血方差对场景精确表示。使用快速可视感知渲染算法来进行快速的训练…...

二叉树<II>:二叉树的四种遍历方式代码实现Python3

今天我们来介绍的是二叉树的「前序」、「中序」、「后序」、「层序」四种遍历方式如何用代码实现。 还不知道这四种遍历方式原理的可以看另一篇文章&#xff1a;二叉树&#xff1c;I&#xff1e;&#xff1a;概念及二叉树的前序遍历、中序遍历、后序遍历原理 1. 相关题目 这…...

vite ts vue 项目提示 . Projects must list all files or use an include pattern.

vite ts vue 项目提示 . Projects must list all files or use an include pattern. 在引用一个 ts 的时候&#xff0c;提示如下&#xff1a; 需要在 tsconfig.node.json 文件中添加&#xff1a; {"compilerOptions": {"composite": true,"skipLibC…...

鲸鱼优化算法改进风储机组一次调频出力分配系数,以频率偏差最小为目标优化函数,结合鲸鱼算法WOA捕食过程,改进风储出力分配系数simulink与matlab联合

simulink与matlab联合 风机模糊控制 改善后的系统频率 simulink.采用风储联合数学模型...

C语言经典面试题目(七)

1、C语言中如何进行内存对齐和字节对齐&#xff1f; 在C语言中&#xff0c;内存对齐和字节对齐是为了优化内存访问速度和提高系统性能而进行的一种策略。内存对齐是指数据在内存中的存放位置必须是某个值的倍数&#xff0c;通常是数据类型的大小。字节对齐是指数据在内存中的存…...

2024华为春招Django面试题大全,最全知识点揭秘,面试必备!

为了帮助广大求职者更好地准备即将到来的面试&#xff0c;本文精心编撰了一系列涵盖InnoDB存储引擎关键知识点的面试题。这些问题不仅覆盖了InnoDB的基础知识&#xff0c;如其ACID特性、索引设计、锁机制等&#xff0c;还涵盖了性能优化、备份恢复策略等高级话题&#xff0c;旨…...

搜维尔科技:使用SenseGlove Nova手套操纵其“CAVE”投影室中的虚拟对象

创造了一种基于 PC 的创新型多边沉浸式环境&#xff0c;让参与者完全被虚拟图像和声音包围。 需要解决的挑战&#xff1a; 传统的 VR 系统往往缺乏真实的触摸反馈&#xff0c;限制了用户的沉浸感。AVR Japan 旨在通过将触觉技术融入到他们的 CAVE 系统中来应对这一挑战&#x…...

独立服务器的优势

独立服务器的优势 高性能 独立服务器提供了卓越的性能&#xff0c;因为它们不与其他用户共享资源。这使得您的网站或应用程序能够快速响应访问请求&#xff0c;并处理大量数据。 安全性 由于没有其他租户在同一服务器上&#xff0c;独立服务器的安全性更高。您可以更好地控制…...

前端框架vue的样式操作,以及vue提供的属性功能应用实战

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…...

【自动化测试】如何在jenkins中搭建allure

相信大家在做自动化测试过程中&#xff0c;都会用到自动化测试环境&#xff0c;目前最常见的就是通过容器化方式部署自动化测试环境&#xff0c;但对于一些测试小白&#xff0c;不是很会搭建持续集成环境&#xff0c;特别是从0-1的过程&#xff0c;需要自行搭建很多依赖环境&am…...

2.域控如何强制转移操作主机角色?使用命令如何强制转移域控的操作角色?

1.实验环境介绍 实验1:模拟5种操作主机都在DC01上的域控宕机了 (1)实验先决条件 (2)测试的方向 实验2:域控夺权实验操作 方式1:AD用户和计算机工具转移操作主机角色 (1)RID角色转移: (2)PDC角色转移 (3)基础结构操作主机角色转移 方式2:powshell命令强制…...

C# event的使用

在C#中&#xff0c;事件&#xff08;Event&#xff09;是一种特殊的成员&#xff0c;它允许类或对象以类型安全的方式向外界发出通知&#xff0c;表明某个特定的行为或状态变化已经发生。 订阅该事件的其他类可以定义处理方法来响应这些通知。 事件主要基于委托机制实现&…...

外包干了9天,技术退步明显。。。。。

先说一下自己的情况&#xff0c;本科生&#xff0c;2018年我通过校招踏入了南京一家软件公司&#xff0c;开始了我的职业生涯。那时的我&#xff0c;满怀热血和憧憬&#xff0c;期待着在这个行业中闯出一片天地。然而&#xff0c;随着时间的推移&#xff0c;我发现自己逐渐陷入…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销&#xff0c;平衡网络负载&#xff0c;延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

【单片机期末】单片机系统设计

主要内容&#xff1a;系统状态机&#xff0c;系统时基&#xff0c;系统需求分析&#xff0c;系统构建&#xff0c;系统状态流图 一、题目要求 二、绘制系统状态流图 题目&#xff1a;根据上述描述绘制系统状态流图&#xff0c;注明状态转移条件及方向。 三、利用定时器产生时…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)

目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关&#xff0…...

Mac下Android Studio扫描根目录卡死问题记录

环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中&#xff0c;提示一个依赖外部头文件的cpp源文件需要同步&#xff0c;点…...

JVM虚拟机:内存结构、垃圾回收、性能优化

1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...

Windows安装Miniconda

一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...

Spring Security 认证流程——补充

一、认证流程概述 Spring Security 的认证流程基于 过滤器链&#xff08;Filter Chain&#xff09;&#xff0c;核心组件包括 UsernamePasswordAuthenticationFilter、AuthenticationManager、UserDetailsService 等。整个流程可分为以下步骤&#xff1a; 用户提交登录请求拦…...

多元隐函数 偏导公式

我们来推导隐函数 z z ( x , y ) z z(x, y) zz(x,y) 的偏导公式&#xff0c;给定一个隐函数关系&#xff1a; F ( x , y , z ( x , y ) ) 0 F(x, y, z(x, y)) 0 F(x,y,z(x,y))0 &#x1f9e0; 目标&#xff1a; 求 ∂ z ∂ x \frac{\partial z}{\partial x} ∂x∂z​、 …...

海云安高敏捷信创白盒SCAP入选《中国网络安全细分领域产品名录》

近日&#xff0c;嘶吼安全产业研究院发布《中国网络安全细分领域产品名录》&#xff0c;海云安高敏捷信创白盒&#xff08;SCAP&#xff09;成功入选软件供应链安全领域产品名录。 在数字化转型加速的今天&#xff0c;网络安全已成为企业生存与发展的核心基石&#xff0c;为了解…...