Android自定义View知识体系
View的概念、作用和基本属性
View是Android中的基本UI组件,用于构建用户界面。它可以是按钮、文本框、图像等可见元素,也可以是容器,用于组织其他View。View的作用是展示数据和接收用户的输入。它可以显示文本、图片、动画等内容,并响应用户的点击、滑动、手势等操作。
View属性包括:
- ID:每个View都可以有一个唯一标识符,用于在代码中查找和操作View。
- Width和Height:View的宽度和高度,可以使用具体的像素值或者特定的布局参数(如wrap_content、match_parent)。
- Background:View的背景,可以是颜色、图片或者其他可绘制对象。
- Padding:View的内边距,用于设置View内容与边界之间的空白区域。
- Margin:View的外边距,用于设置View与其他View之间的空白区域。
View的层次结构和视图树是指Android中的View组织方式。每个Activity或Fragment都有一个根View,称为根布局,它可以包含其他View。这些View可以再次包含其他View,形成一个层次结构,即视图树。
视图树的顶层是Window,它包含了整个屏幕上的所有View。每个View都有一个唯一的父View,除了根View外,每个View也可以有多个子View。
View的生命周期包括方法:
- onCreate:在View创建时调用,用于初始化View的状态和属性。
- onMeasure:在View测量时调用,用于确定View的宽度和高度。
- onLayout:在View布局时调用,用于确定View在父View中的位置。
- onDraw:在View绘制时调用,用于绘制View的内容。
- onDestroy:在View销毁时调用,用于释放资源和清理工作。
View的绘制原理
View的绘制过程主要包括measure(测量)、layout(布局)和draw(绘制)三个阶段。下面将详细解释每个阶段的原理,并给出相应的代码示例。
- Measure(测量)阶段: - 在这个阶段,系统会通过调用View的measure()方法来测量View的大小。在测量过程中,View会确定自己的宽度和高度,并为其子View提供测量规格。 - View的测量规格通过MeasureSpec来表示,包括三种模式:EXACTLY、AT_MOST和UNSPECIFIED。 - EXACTLY模式表示View的大小已经确定,如设置了具体的数值或match_parent属性。 - AT_MOST模式表示View的大小不能超过某个边界,如设置了wrap_content属性。 - UNSPECIFIED模式表示View的大小没有限制,如在ScrollView中的子View。 - 在measure()方法中,View会根据测量规格计算自己的测量宽度和高度,并通过setMeasuredDimension()方法设置测量结果。
super.onMeasure(widthMeasureSpec, heightMeasureSpec);// 获取测量规格 int widthMode = MeasureSpec.getMode(widthMeasureSpec);int widthSize = MeasureSpec.getSize(widthMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);// 根据测量规格计算宽度和高度 int measuredWidth = 0;int measuredHeight = 0;if (widthMode == MeasureSpec.EXACTLY) {measuredWidth = widthSize;} else if (widthMode == MeasureSpec.AT_MOST) {measuredWidth = Math.min(desiredWidth, widthSize);}if (heightMode == MeasureSpec.EXACTLY) {measuredHeight = heightSize;} else if (heightMode == MeasureSpec.AT_MOST) {measuredHeight = Math.min(desiredHeight, heightSize);}// 设置测量结果setMeasuredDimension(measuredWidth, measuredHeight);
}
- Layout(布局)阶段: - 在这个阶段,系统会通过调用View的layout()方法来确定View在父容器中的位置。每个View都有自己的布局参数(LayoutParams),父容器会根据这些参数来摆放子View。 - 在layout()方法中,View会根据父容器传递的布局参数,计算自己的左上角坐标和右下角坐标,然后通过setFrame()方法设置自己的位置。
super.onLayout(changed, left, top, right, bottom);// 计算自己的位置int selfLeft = ...;int selfTop = ...;int selfRight = ...;int selfBottom = ...;// 设置自己的位置layout(selfLeft, selfTop, selfRight, selfBottom);
}
- Draw(绘制)阶段: - 在这个阶段,系统会通过调用View的draw()方法来绘制View的内容。绘制过程是在View的Canvas对象上进行的,可以使用画笔(Paint)来设置绘制的样式和颜色。 - 在draw()方法中,View会调用自己的onDraw()方法来绘制自己的内容,包括背景、文本、图像等。 - 如果View有子View,系统会递归地调用子View的draw()方法,按照View的层级顺序进行绘制。 super.onDraw(canvas); // 绘制背景 canvas.drawRect(0, 0, getWidth(), getHeight(), backgroundPaint); // 绘制文本 canvas.drawText(“Hello, World!”, 0, 0, textPaint); // 绘制图像 canvas.drawBitmap(bitmap, 0, 0, null); } 为了优化View的绘制性能,可以考虑以下几个方面:
- 减少绘制区域
- 避免过度绘制
- 使用硬件加速
- 使用缓存
- 异步绘制
自定义View
自定义View和ViewGroup是Android开发中常见的需求,可以通过继承View或ViewGroup类来实现。下面将详细介绍如何自定义View和ViewGroup,并处理用户交互事件。
- 自定义View: - 创建一个继承自View的子类,并重写onMeasure()、onLayout()和onDraw()等方法。 - 在onMeasure()方法中,根据测量规格计算View的宽度和高度,并调用setMeasuredDimension()方法设置测量结果。 - 在onLayout()方法中,根据父容器传递的布局参数,计算View的位置,并调用layout()方法设置自己的位置。 - 在onDraw()方法中,使用Canvas对象进行绘制操作,包括绘制背景、文本、图像等。
- 自定义ViewGroup: - 创建一个继承自ViewGroup的子类,并重写onMeasure()、onLayout()等方法。 - 在onMeasure()方法中,遍历子View,测量每个子View的大小,并根据子View的测量结果计算自己的宽度和高度。 - 在onLayout()方法中,遍历子View,根据子View的布局参数,计算每个子View的位置,并调用layout()方法设置子View的位置。
- 处理用户交互事件: - 重写onTouchEvent()方法,处理用户的点击、滑动、手势等事件。 - 在onTouchEvent()方法中,根据事件类型(如MotionEvent.ACTION_DOWN、MotionEvent.ACTION_MOVE、MotionEvent.ACTION_UP等)进行相应的处理。 - 可以通过getX()和getY()方法获取触摸点的坐标,通过getAction()方法获取事件类型。
switch (event.getAction()) {case MotionEvent.ACTION_DOWN:// 处理按下事件 break;case MotionEvent.ACTION_MOVE:// 处理滑动事件 break;case MotionEvent.ACTION_UP:// 处理抬起事件 break;}return true; // 返回true表示已经处理该事件
}
- 处理点击事件: - 可以通过设置setOnClickListener()方法来处理View的点击事件。 - 在onClick()方法中,处理点击事件的逻辑。
@Override public void onClick(View v) {// 处理点击事件}
});
- 处理滑动事件: - 可以通过设置setOnTouchListener()方法来处理View的滑动事件。 - 在onTouch()方法中,根据触摸点的坐标和滑动距离,处理滑动事件的逻辑。
javaview.setOnTouchListener(new@Override public boolean onTouch(View v, MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:// 处理按下事件 break;case MotionEvent.ACTION_MOVE:// 处理滑动事件 break;case MotionEvent.ACTION_UP:// 处理抬起事件
break;}return true; // 返回true表示已经处理该事件}
});
- 处理手势事件:
- 可以通过GestureDetector类来处理手势事件,包括单击、长按、滑动、双击等。
- 创建一个GestureDetector对象,并重写onTouchEvent()方法,在方法中将触摸事件传递给GestureDetector对象进行处理。
- 在GestureDetector的回调方法中,处理相应的手势事件。
java// 创建GestureDetector对象GestureDetector gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
@Override public boolean onSingleTapConfirmed(MotionEvent e) {// 处理单击事件return true;}@Override public void onLongPress(MotionEvent e) {// 处理长按事件}@Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {// 处理滑动事件 return true;}@Override public boolean onDoubleTap(MotionEvent e) {// 处理双击事件return true;}
});
// 在onTouchEvent方法中将触摸事件传递给GestureDetector对象处理
@Overridepublic boolean onTouchEvent(MotionEvent event) {return gestureDetector.onTouchEvent(event);
}
通过以上方法,可以自定义View和ViewGroup,并处理用户的点击、滑动和手势等交互事件,实现丰富的用户界面交互体验。更多有关Android开发的核心内容进阶,可以点击主页查看详细内容进行学习。
相关文章:
Android自定义View知识体系
View的概念、作用和基本属性 View是Android中的基本UI组件,用于构建用户界面。它可以是按钮、文本框、图像等可见元素,也可以是容器,用于组织其他View。View的作用是展示数据和接收用户的输入。它可以显示文本、图片、动画等内容,…...
Springboot 自定义 Mybatis拦截器,实现 动态查询条件SQL自动组装拼接(玩具)
前言 ps:最近在参与3100保卫战,战况很激烈,刚刚打完仗,来更新一下之前写了一半的博客。 该篇针对日常写查询的时候,那些动态条件sql 做个简单的封装,自动生成(抛砖引玉,搞个小玩具&a…...
Go 1.21新增的 slices 包详解(三)
Go 1.21新增的 slices 包提供了很多和切片相关的函数,可以用于任何类型的切片。 slices.Max 定义如下: func Max[S ~[]E, E cmp.Ordered](x S) E 返回 x 中的最大值,如果 x 为空,则 panic。对于浮点数 E, 如果有元素为 NaN&am…...
Python 在logging.config.dictConfig()日志配置方式下,使用自定义的Handler处理程序
文章目录 一、基于 RotatingFileHandler 的自定义处理程序二、基于 TimedRotatingFileHandler 的自定义处理程序 Python logging模块的基本使用、进阶使用详解 Python logging.handlers模块,RotatingFileHandler、TimedRotatingFileHandler 处理器各参数详细介绍 …...
Anaconda, Python, Jupyter和PyCharm介绍
目录 1 Anaconda, Python, Jupyter和PyCharm介绍 2 macOS通过Anaconda安装Python, Jupyter和PyCharm 3 使用终端创建虚拟环境并安装PyTorch 4 安装PyCharm并导入Anaconda虚拟环境 5 Windows操作系统下Anaconda与PyCharm安装 6 通过 Anaconda Navigator 创建 TensorFlow 虚…...
axios 各种方式的请求 示例
GET请求 示例一: 服务端代码 GetMapping("/f11") public String f11(Integer pageNum, Integer pageSize) {return pageNum " : " pageSize; }前端代码 <template><div class"home"><button click"getFun1…...
基于开源模型搭建实时人脸识别系统(四):人脸质量
续人脸识别实战之基于开源模型搭建实时人脸识别系统(三):人脸关键点、对齐模型概览与模型选型_CodingInCV的博客-CSDN博客 不论对于静态的人脸识别还是动态的人脸识别,我们都会面临一个问题,就是输入的人脸图像的质量可…...
【开发笔记】ubuntu部署指定版本的前后端运行环境(npm nodejs mysql)
目录 1 背景2 环境要求3 部署流程3.1 npm的安装3.2 nodejs的安装3.3 MySQL的安装 4 可能的问题 1 背景 在远程服务器上的Ubuntu系统中,部署指定版本的前后端项目的运行环境 2 环境要求 npm 9.5.1Nodejs v18.16.1MySQL 8.0.33 3 部署流程 3.1 npm的安装 通过安…...
用于优化开关性能的集成异质结二极管的4H-SiC沟道MOSFET
标题:4H-SiC Trench MOSFET with Integrated Heterojunction Diode for Optimizing Switching Performance 摘要 本研究提出了一种新型的4H-SiC沟道MOSFET,其在栅槽底部集成了异质结二极管(HJD-TMOS),并通过TCAD模拟进…...
优化个人博客总结
前面学习完怎么搭建个人博客,后面要做的就是排版优化自己的博客了,今天通过教程学习到了然后更爱美化其中的效果,还通过改写代码来带到基本的效果展示,同时也把最开始学习的计算速成课的笔记输出在上面,这也是一个很好…...
从零构建深度学习推理框架-9 再探Tensor类,算子输入输出的分配
再探Tensor类: 第二节中我们编写的Tensor类其实并不能满足我们的使用需要,我们将在这一节以代码阅读的方式来看看一个完全版本的Tensor应该具备怎样的要素,同时我们对Tensor类的分析来看看在C中一个设计好的类应该是怎么样的。 Tensor<fl…...
Vue使用element-ui
main.js配置 //引入Vue import Vue from vue //引入App import App from ./App.vue//完整引入 //引入ElementUI组件库 // import ElementUI from element-ui; //引入ElementUI全部样式 // import element-ui/lib/theme-chalk/index.css;//按需引入 import { Button,Row,DatePi…...
使用ApplicationRunner简化Spring Boot应用程序的初始化和启动
ApplicationRunner这个接口,我们一起来了解这个组件,并简单使用它吧。🤭 引言 在开发Spring Boot应用程序时,应用程序的初始化和启动是一个重要的环节。ApplicationRunner是Spring Boot提供的一个有用的接口,可以帮助…...
Vue 2.x 项目升级到 Vue 3详细指南【修改清单】
文章目录 前言0.迁移过程1. 安装 Vue 32. 逐一处理迁移中的警告3. 迁移全局和内部 API4. 迁移 Vue Router 和 Vuex5. 处理其他的不兼容变更 1. Vue3特性1. Composition API2. 更好的性能3. 更好的 TypeScript 支持4. 多个根元素5. Suspense 组件6. Teleport 组件7. 全局 API 的…...
【算法日志】贪心算法刷题:重叠区问题(day31)
代码随想录刷题60Day 目录 前言 无重叠区间(筛选区间) 划分字母区间(切割区间) 合并区间 前言 今日的重点是掌握重叠区问题。 无重叠区间(筛选区间) int eraseOverlapIntervals(vector<vector<in…...
基于Jenkins构建生产CICD环境、jenkins安装
目录 Jenkins简介 安装配置Jenkins Jenkins简介 Jenkins是一个用Java编写的开源的持续集成工具。在与Oracle发生争执后,项目从Hudson项目独立。官方网站:https://jenkins.io/。 Jenkins提供了软件开发的持续集成服务。它运行在Servlet容器中ÿ…...
基于Java SpringBoot+vue+html 的地方美食系统(2.0版本)
博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W,csdn、博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 文章目录 1 简介2 技术栈3 系统流程的分析3.1 用户管理的流程3.2个人中心管理流程3.3登录流程 4系统设计…...
opencv-gpu版本编译(添加java支持,可选)实现硬解码
目录 opencv gpu版本编译,实现硬解码,加速rtsp视频流读取1、准备文件2、复制 NVCUVID 头文件到 cuda 安装目录 include3、安装相关依赖4、 执行cmake5、编译安装6、测试 opencv gpu版本编译,实现硬解码,加速rtsp视频流读取 前置条…...
数据分析问答总结
一、SQL窗口函数 1.是什么 OLAP(Online Anallytical Processing联机分析处理),对数据库数据进行实时分析处理。 2.基本语法: <窗口函数>OVER (PARTITION BY <用于分组的列名> ORDER BY <用于排序的…...
Python学习笔记_实战篇(二)_django多条件筛选搜索
多条件搜索在很多网站上都有用到,比如京东,淘宝,51cto,等等好多购物教育网站上都有,当然网上也有很多开源的比楼主写的好的多了去了,仅供参考,哈哈 先来一张效果图吧,不然幻想不出来…...
Pixel Mind Decoder 参数调优实战:平衡推理速度与识别准确率
Pixel Mind Decoder 参数调优实战:平衡推理速度与识别准确率 1. 为什么需要参数调优 当你第一次使用Pixel Mind Decoder时,可能会发现同样的输入有时会产生不同的输出质量。这就像开车时需要在速度和油耗之间找到平衡点一样,AI模型的参数调…...
Linux驱动工程师面试技术要点与开发实践
Linux驱动工程师面试技术要点解析 1. 面试技术问题深度剖析 1.1 基础驱动开发能力考察 面试中关于驱动开发的基础问题主要考察候选人对底层通信协议的理解程度。I2C总线作为嵌入式系统中最常用的通信接口之一,其起始信号(START Condition)的…...
工业自动化实战:如何用IEEE 802.1AS实现微秒级时间同步(附Linux配置)
工业自动化实战:如何用IEEE 802.1AS实现微秒级时间同步(附Linux配置) 在工业4.0和智能制造浪潮下,毫秒级时间同步已无法满足高端装备协同控制的需求。某汽车生产线曾因500微秒的时间偏差导致机械臂碰撞,直接造成数百万…...
FaceFusion镜像部署全攻略:开箱即用,轻松开启换脸之旅
FaceFusion镜像部署全攻略:开箱即用,轻松开启换脸之旅 想体验电影特效级别的AI换脸,但被复杂的Python环境、CUDA配置和模型下载劝退?今天,你只需要一个浏览器,就能开启这段神奇之旅。FaceFusion࿰…...
Qwen3-TTS声音克隆部署全攻略:简单3步,开启你的语音克隆之旅
Qwen3-TTS声音克隆部署全攻略:简单3步,开启你的语音克隆之旅 想不想让一段普通的文字,用你指定的声音说出来?比如,用你自己的声音给视频配音,用朋友的声音讲个笑话,或者用某个角色的声音朗读一…...
8个Illustrator自动化脚本解决方案,彻底改变设计师工作流程
8个Illustrator自动化脚本解决方案,彻底改变设计师工作流程 【免费下载链接】illustrator-scripts Adobe Illustrator scripts 项目地址: https://gitcode.com/gh_mirrors/il/illustrator-scripts illustrator-scripts项目提供了一套专业的Adobe Illustrator…...
从单颗粒到多相流:OpenFOAM+LIGGGHTS耦合参数调优心得与性能分析
从单颗粒到多相流:OpenFOAMLIGGGHTS耦合参数调优实战指南 在颗粒-流体耦合模拟领域,OpenFOAM与LIGGGHTS的组合已成为工业级仿真的黄金标准。但当我们从教学案例转向真实工程场景时,参数敏感性、计算效率与物理真实性之间的平衡往往成为困扰研…...
OWL ADVENTURE快速上手:10分钟完成本地部署与第一个识别Demo
OWL ADVENTURE快速上手:10分钟完成本地部署与第一个识别Demo 你是不是也对那些能看懂图片、能回答图片问题的AI模型感到好奇?OWL ADVENTURE就是这样一个模型,它能理解图片里的内容,然后和你聊天。听起来很酷,但会不会…...
从CORS到自定义,让你的API更健壮
一、中间件是啥?咱用“餐厅”打个比方想象一下,你的FastAPI应用是个高级餐厅。👉 顾客(客户端请求)来到门口。- 迎宾(CORS中间件):先看你是不是从允许的街区(域名&#x…...
AI Agent:从定义到分类,带你深入理解智能体的核心奥秘!
本文首先明确了AI Agent的定义,即结合深度学习技术(尤其是大模型技术)并能执行任务的下游应用。接着,文章列举了AI Agent的实际案例,如美团小美、AI Coding工具、SlidevAI和deepwiki,并区分了哪些应用不属于…...
