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(绘制)三个阶段。下面将详细解释每个阶段的原理,并给出相应的代码示例。

  1. 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);
}
  1. 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);
}
  1. 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,并处理用户交互事件。

  1. 自定义View: - 创建一个继承自View的子类,并重写onMeasure()、onLayout()和onDraw()等方法。 - 在onMeasure()方法中,根据测量规格计算View的宽度和高度,并调用setMeasuredDimension()方法设置测量结果。 - 在onLayout()方法中,根据父容器传递的布局参数,计算View的位置,并调用layout()方法设置自己的位置。 - 在onDraw()方法中,使用Canvas对象进行绘制操作,包括绘制背景、文本、图像等。
  2. 自定义ViewGroup: - 创建一个继承自ViewGroup的子类,并重写onMeasure()、onLayout()等方法。 - 在onMeasure()方法中,遍历子View,测量每个子View的大小,并根据子View的测量结果计算自己的宽度和高度。 - 在onLayout()方法中,遍历子View,根据子View的布局参数,计算每个子View的位置,并调用layout()方法设置子View的位置。
  3. 处理用户交互事件: - 重写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表示已经处理该事件
}
  1. 处理点击事件: - 可以通过设置setOnClickListener()方法来处理View的点击事件。 - 在onClick()方法中,处理点击事件的逻辑。
    @Override    public void onClick(View v) {// 处理点击事件}
});
  1. 处理滑动事件: - 可以通过设置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表示已经处理该事件}
});
  1. 处理手势事件:
  • 可以通过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开发的核心内容进阶,可以点击主页查看详细内容进行学习。

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

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

相关文章

ubuntu20.04升级GLIBC高版本方法,解决:version `GLIBC_2.34‘ not found

检查版本 strings /lib/x86_64-linux-gnu/libc.so.6 |grep GLIBC_ 1 显示结果 GLIBC_2.2.5 GLIBC_2.2.6 GLIBC_2.3 GLIBC_2.3.2 GLIBC_2.3.3 GLIBC_2.3.4 GLIBC_2.4 GLIBC_2.5 GLIBC_2.6 GLIBC_2.7 GLIBC_2.8 GLIBC_2.9 GLIBC_2.10 GLIBC_2.11 GLIBC_2.12 GLIBC_2.13 GLIBC_2…

Neo4j之CALL基础

CALL 语句用于调用 Neo4j 数据库中预定义的函数、过程或者自定义的函数。它是用来执行一些特定操作或计算的重要工具。以下是一些常用的 CALL 语句示例和解释: 调用内置函数: CALL db.labels()这个示例中,调用了内置函数 db.labels() 来获取…

git分支

一、引言 分支的命名规范以及管理方式对项目的版本发布至关重要,为了解决实际开发过程中版本发布时代码管理混乱、冲突等比较头疼的问题,我们将在文中阐述如何更好的管理代码分支。 二、总览 从上图可以看到主要包含下面几个分支&#xff…

【是C++,不是C艹】 手把手带你实现Date类(附源码)

💞💞欢迎来到 Claffic 的博客💞💞 👉 专栏:《是C,不是C艹》👈 前言: 恍惚间,已经两个月没更新了 (;д`)ゞ 我忏…

css实现三角形的几种方法

css实现三角形的方法:1、使用边框实现三角形,利用透明边框和实色边框的组合,可以创建不同方向和大小的三角形;2、使用伪元素实现三角形,通过使用伪元素来创建一个占据父元素一半大小的实心三角形;3、使用tr…

网络安全面试题整理

目录标题 1.你常用的渗透工具有哪些?2.xss盲打到内网服务器的利用3.鱼叉式攻击和水坑攻击是什么?4.什么是虚拟机逃逸?5.中间人攻击的原理和防御?6.TCP三次握手过程?7.七层模型有哪七层?8.对云安全的理解&am…

Redis 持久化的手段有哪些 ?RDB 和 AOF 有什么区别 ?

目录 1. Redis 持久化的手段有哪些 2. RDB 和 AOF 有什么区别 2.1 RDB 持久化 2.2 AOF 持久化 2.2.1 AOF 持久化策略有哪些 3. 混合持久化是如何执行的(了解) 1. Redis 持久化的手段有哪些 Redis 持久化的手段有三种: 快照方式&#…

开源数据库Mysql_DBA运维实战 (总结)

开源数据库Mysql_DBA运维实战 (总结) SQL语句都包含哪些类型 DDL DCL DML DQL Yum 安装MySQL的配置文件 配置文件:/etc/my.cnf日志目录:/var/log/mysqld.log错误日志:/var/log/mysql/error.log MySQL的主从切换 查看主…

OpenCV(二)——图像基本处理(四)

目录 4.图像形态学操作 4.1 图像腐蚀 4.2 图像膨胀 4.3 开运算 4.4 闭运算

什么是程序化交易接口?执行三步曲是什么?

在股市中的发展过程中,通过不断的更新迭代,从手动交易到自动交易的过程就有了历史的蜕变,那么对于程序化交易接口(Application Programming Interface, API)其实就是指为程序化交易提供的一组定义和规范,允…

物联网工程应用实训室建设方案

一、物联网工程应用系统概述 1.1物联网工程定义 物联网工程(Internet of Things Engineering)是一种以信息技术(IT)来改善实体世界中人们生活方式的新兴学科,它利用互联网技术为我们的日常生活活动提供服务和增益&am…

前端面试:【CSS】盒模型、选择器、布局、响应式设计、Flexbox 与 Grid

CSS(层叠样式表)是用于控制网页外观和布局的重要语言。在这篇文章中,我们将深入探讨CSS的基础知识,包括盒模型、选择器、布局、响应式设计,以及弹性盒子(Flexbox)和网格布局(Grid&am…

hadoop2的集群数据将副本存储在hadoop3

在 Hadoop 集群中,HDFS 副本是分布式存储的,会存储在不同的节点上。因此,如果您的 HDFS 所在路径是在 Hadoop2 集群中,您可以在 Hadoop3 集群上添加新的节点,并向 Hadoop3 集群中添加这些新节点上的数据副本。 以下是…

时序预测 | MATLAB实现基于CNN-LSTM卷积长短期记忆神经网络的时间序列预测-递归预测未来(多指标评价)

时序预测 | MATLAB实现基于CNN-LSTM卷积长短期记忆神经网络的时间序列预测-递归预测未来(多指标评价) 目录 时序预测 | MATLAB实现基于CNN-LSTM卷积长短期记忆神经网络的时间序列预测-递归预测未来(多指标评价)预测结果基本介绍程序设计参考资料 预测结果 基本介绍 MATLAB实现基…

【C#】关于?的用法

1、可空类型修饰符(?) 如: int? x null;//可空类型默认值都是null,而值类型如int默认值为0、bool默认值为false等 bool? result true;2、三目运算符(?:) 如: bool…

线程面试题-1

看的博客里面总结的线程的八股文 1、线程安全的集合有哪些?线程不安全的呢? 线程安全的: Hashtable:比HashMap多了个线程安全。 ConcurrentHashMap:是一种高效但是线程安全的集合。 Vector:比Arraylist多了个同步化…

安装Vue_dev_tools

Vue控制台出现Download the Vue Devtools extension for a better development experience: 下载Vue_dev_tools,这里给出网盘链接,有Vue2和Vue3的,dev_tools 以Google浏览器为例 点击设置(就是那三个点)->扩展程序->管理扩…

C++开发知识树的阶段

系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 TODO:写完再整理 文章目录 系列文章目录前言第一阶段:C++工具使用的入门阶段1、C++的语言语法基础2、数据结构与算法(常用的几个数据结构)3、基础的linux命令第二阶段:C++代码核心思想的进…

游戏服务端性能测试

导语:近期经历了一系列的性能测试,涵盖了Web服务器和游戏服务器的领域。在这篇文章中,我将会对游戏服务端所做的测试进行详细整理和记录。需要注意的是,本文着重于记录,而并非深入的编程讨论。在这里,我将与…

NextJs - Middleware(中间件)

中间件允许您在请求完成之前运行代码。然后,根据传入的请求,您可以通过重写、重定向、修改请求或响应标头或直接响应来修改响应。 中间件在缓存内容和路由匹配之前运行。 使用规则 使用项目根目录中的文件 middleware.ts(或 .js&#xff09…