Android:如何绘制View

点击查看Android 如何绘制视图官网

一、简介

Android 框架会在 Activity 获得焦点时请求 Activity 绘制其布局。Android 框架会处理绘制流程,但该 Activity 必须提供其布局层次结构的根节点。

Android 框架会绘制布局的根节点,并测量和绘制布局树。它会通过遍历布局树并渲染与无效区域相交的每个 View 进行绘制。每个 ViewGroup 负责请求绘制其每个子级(使用 draw() 方法),而每个 View 负责绘制其本身。由于布局树已经过系统预先遍历,因此该框架会在子级之前(即后方)绘制父级,而其同级会按照它们在布局树中出现的顺序进行绘制。

注意:该框架不会绘制有效区域之外的 View 对象,也不会负责为您绘制 View 背景。您可以通过调用 invalidate() 来强制绘制 View。

Android 框架绘制布局包含两个遍历流程一个测量遍历和一个布局遍历。该框架会在 measure(int, int) 中执行测量遍历,并执行 View 树的自上而下遍历。在递归过程中,每个 View 都会将维度规范下推到布局树。测量遍历结束时,每个 View 都会存储其测量值。该框架会在 layout(int, int, int, int) 中执行第二次遍历,也是自上而下遍历。在此次遍历中,每个父级负责使用测量遍历中计算的尺寸来定位其所有的子级。

以下各部分更详细地介绍了布局流程的两个遍历。

二、启动测量遍历

当返回 View 对象的 measure() 方法时,请设置其 getMeasuredWidth() 和 getMeasuredHeight() 值,以及 View 对象的所有后代的值。View 对象的测量宽度值和测量高度值必须遵守 View 对象的父级所施加的限制。这有助于保证在测量遍历结束时,所有父级都会接受其子级的所有测量值。

父级 View 可以对其子级多次调用 measure()。例如,父级可以使用未指定的维度测量子级一次,以确定它们的首选尺寸。如果子级的不受限尺寸的总和过大或过小,则父级可以使用限制子级尺寸的值再次调用 measure()。

测量遍历使用两个类来传达维度。View 对象使用 ViewGroup.LayoutParams 来传达其首选尺寸和位置。基本 ViewGroup.LayoutParams 类描述了 View 的首选宽度和高度。针对每个维度,它可以指定以下某一项:

  • 一个确切的尺寸。
  • MATCH_PARENT,此参数意味着 View 的首选尺寸是其父级的尺寸(负填充)。
  • WRAP_CONTENT,此参数意味着 View 的首选尺寸恰好足以容纳其内容(正填充)。

有适用于 ViewGroup 的不同子类的 ViewGroup.LayoutParams 子类。例如,RelativeLayout 有自己的 ViewGroup.LayoutParams 子类,其中包括可使子级 View 对象水平居中和垂直居中的功能。

MeasureSpec 对象用于在树中将要求从父级下推到子级。MeasureSpec 可以是下述三种模式之一:

  • UNSPECIFIED:父级使用此模式来确定子级 View 的目标维度。例如,LinearLayout 可对高度设置为 UNSPECIFIED 且宽度设置为 EXACTLY 240 的子级调用 measure(),以确定给定宽度为 240 像素的子级 View 所需的高度。
  • EXACTLY:父级使用此模式来强制子级使用某个确切尺寸。子级必须使用此尺寸,并保证其所有的后代都能放入此尺寸。
  • AT MOST:父级使用此模式来强制规定子级的最大尺寸。子级必须保证它及其所有的后代都能放入此尺寸。

三、启动布局遍历

如需启动布局,请调用 requestLayout()。当 View 认为自己无法再放入当前范围时,通常会调用此方法。

四、实现自定义测量和布局逻辑

如果您要实现自定义测量或布局逻辑,请替换实现该逻辑的方法:onMeasure(int, int) 和 onLayout(boolean, int, int, int, int)。 这些方法分别由 measure(int, int) 和 layout(int, int, int, int) 调用。请勿尝试替换 measure(int, int) 或 layout(int, int) 方法 - 这两种方法都是 final,因此无法被替换。

以下示例展示了如何在 WindowManager 示例应用的“SplitLayout”类中执行此操作。如果 SplitLayout 具有两个或更多子视图,并且显示屏具有折叠边,则它会将两个子视图放置在折叠边的任一侧。以下示例展示了用于替换测量和布局的用例,但对于生产环境,请使用 SlidingPaneLayout(如果您希望出现此行为)。

/*** An example of split-layout for two views, separated by a display* feature that goes across the window. When both start and end views are* added, it checks whether there are display features that separate the area* in two—such as a fold or hinge—and places them side-by-side or* top-bottom.*/
class SplitLayout : FrameLayout {private var windowLayoutInfo: WindowLayoutInfo? = nullprivate var startViewId = 0private var endViewId = 0private var lastWidthMeasureSpec: Int = 0private var lastHeightMeasureSpec: Int = 0...fun updateWindowLayout(windowLayoutInfo: WindowLayoutInfo) {this.windowLayoutInfo = windowLayoutInforequestLayout()}override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {val startView = findStartView()val endView = findEndView()val splitPositions = splitViewPositions(startView, endView)if (startView != null && endView != null && splitPositions != null) {val startPosition = splitPositions[0]val startWidthSpec = MeasureSpec.makeMeasureSpec(startPosition.width(), EXACTLY)val startHeightSpec = MeasureSpec.makeMeasureSpec(startPosition.height(), EXACTLY)startView.measure(startWidthSpec, startHeightSpec)startView.layout(startPosition.left, startPosition.top, startPosition.right,startPosition.bottom)val endPosition = splitPositions[1]val endWidthSpec = MeasureSpec.makeMeasureSpec(endPosition.width(), EXACTLY)val endHeightSpec = MeasureSpec.makeMeasureSpec(endPosition.height(), EXACTLY)endView.measure(endWidthSpec, endHeightSpec)endView.layout(endPosition.left, endPosition.top, endPosition.right,endPosition.bottom)} else {super.onLayout(changed, left, top, right, bottom)}}/*** Gets the position of the split for this view.* @return A rect that defines of split, or {@code null} if there is no split.*/private fun splitViewPositions(startView: View?, endView: View?): Array

在这里插入图片描述

五、SlidingPaneLayout

5.1 创建双窗格布局

SlidingPaneLayout 组件支持在较大的设备和可折叠设备上并排显示两个窗格,同时自动进行调整,以便在手机等较小的设备上一次仅显示一个窗格。

5.2 添加依赖

如需使用 SlidingPaneLayout,请在应用的 build.gradle 文件中添加以下依赖项:

dependencies {implementation "androidx.slidingpanelayout:slidingpanelayout:1.2.0"
}
5.4 XML 布局配置

SlidingPaneLayout 提供一种水平的双窗格布局,可在界面的顶层使用。在这种布局中,第一个窗格用作内容列表或浏览器,从属于另一个窗格中用于显示内容的主要详细信息视图。

在这里插入图片描述

六、SlidingPaneLayout 示例

点击查查GitHub 上的 SlidingPaneLayout 示例

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

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

相关文章

React@16.x(51)路由v5.x(16)- 手动实现文件目录参考

作为前面几篇文章的参考: 实现 Router实现 Route实现 Switch实现 withRouter实现 Link 和 NavLink 以上。

一.4 处理器读并解释储存在内存中的指令

此刻,hello.c源程序已经被编译系统翻译成了可执行目标文件hello,并被存放在硬盘上。要想在Unix系统上运行该可执行文件,我们将它的文件名输入到称为shell的应用程序中: linux>./hello hello, world linux> shell是一个命令…

深度优先搜索和广度优先搜索 使用场景

深度优先搜索(Depth-First Search, DFS)和广度优先搜索(Breadth-First Search, BFS)是图和树结构中常用的遍历算法。两者适用于不同的场景。 深度优先搜索 优点 较低的空间复杂度(只需保存当前路径)&…

JS实现当前元素的同级元素 以及父元素的同级元素

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>实现当前元素的同级元素 以及父元素的同级元素</t…

一.2.(4)放大电路静态工作点的稳定;

1.Rb对Q点及Au的影响 输入特性曲线&#xff1a;Rb减少&#xff0c;IBQ&#xff0c;UBEQ增大 输出特性曲线&#xff1a;ICQ增大&#xff0c;UCEQ减少 AUUO/Ui分子减少&#xff0c;分母增大&#xff0c;但由于分子带负号&#xff0c;所以|Au|减少 2.Rc对Q点及Au的影响 输入特性曲…

用Vue3和Plotly.js绘制交互式3D小提琴图

本文由ScriptEcho平台提供技术支持 项目地址&#xff1a;传送门 Vue 中使用 Plotly.js 创建小提琴图 应用场景介绍 小提琴图是一种统计图&#xff0c;用于显示数据的分布和中心趋势。它结合了箱线图和密度图的特点&#xff0c;可以直观地展示数据的分散性和形状。 代码基本…

【网络协议】OSPF

OSPF OSPF&#xff08;Open Shortest Path First&#xff09;协议是一种广泛使用的动态路由协议&#xff0c;它属于链路状态路由协议&#xff0c;在单一自治系统&#xff08;AS&#xff09;内部工作。以下是关于OSPF协议的详细解析&#xff1a; 一、基本概念 定义&#xff1…

使用Keil 点亮LED灯 F103ZET6

1.新建项目 不截图了 2.startup_stm32f10x_hd.s Keil\Packs\Keil\STM32F1xx_DFP\2.2.0\Device\Source\ARM 搜索startup_stm32f10x_hd.s 复制到项目路径&#xff0c;双击Source Group 1 3.项目文件夹新建stm32f10x.h&#xff0c; 新建文件main.c #include "stm32f10x…

windows sshkeygen 多平台添加配置

文章目录 .ssh目录生成新的ssh配置添加公钥到仓库验证 .ssh目录 windows下一般为&#xff1a;C:\Users\15237.ssh &#xff0c;其中“15237”为当前登录用户 生成新的ssh .ssh目录下打开“Git Bash Here”&#xff08;如果没有&#xff0c;先安装 Git 软件&#xff09; 执行…

android perfetto使用技巧梳理

1 抓取方法 根据不同的配置参数&#xff0c;会显示不同的功能。 比如有的trace文件就无法显示线程状态信息&#xff0c;有的无法显示锁依赖信息等等&#xff0c;要看你的参数&#xff0c;我这个是很全的&#xff0c;基本够了&#xff0c;如果还想添加&#xff0c;可以命令行看…

腾讯发布2024大模型十大最新趋势!

近日&#xff0c;在2024世界人工智能大会上&#xff0c;腾讯正式发布了《2024大模型十大趋势——走进“机器外脑”时代》报告。目前&#xff0c;这一报告正在AI产业界各大社群快速传播。 报告中&#xff0c;腾讯研究院试图通过10个关键性的趋势&#xff0c;去理解全世界范围内正…

移远BC28_opencpu方案_开发环境搭建

OPEN CPU 代码采用的是 Python 脚本写的 scons 自动化构建工具。从构建这个角度说&#xff0c;它与 GNU make 是同一类的工具。它是一种改进&#xff0c;并跨平台的 gnu make 替代工具&#xff0c;其集成功能类似于 autoconf/automake。 这里给出简单安装方式

[软件安装]linux下安装steam

1、下载安装包到linux系统 SteamTools 发行版 - Gitee.com 2、选择对应的版本 3、解压安装包steam &#xff08;1&#xff09;在opt路径下新建一个文件夹 sudo mkdir steam &#xff08;2&#xff09;进入压缩包路径下&#xff0c;打开终端&#xff0c;执行以下代码进行解压…

Docker容器 为MySQL创建新用户和授权

当您需要为 MySQL 数据库创建一个新用户并配置其访问权限时&#xff0c;可以按照以下步骤操作。我将创建一个名为 newuser 的新用户&#xff0c;并为其授予在任何主机上访问所有数据库的权限。 创建新用户和授权步骤&#xff1a; 登录到 MySQL 服务器 首先&#xff0c;使用具有…

python特征相关性可视化分析 - sns.pairplot

seaborn 是一个基于 matplotlib 的 Python 数据可视化库&#xff0c;提供了更高层次的接口来绘制有吸引力的统计图形。pairplot 是 seaborn 中的一个函数&#xff0c;用于绘制数据集中多个变量之间的成对关系图。 基本用法 pairplot 函数可以快速地对数据集中的所有数值变量进…

volatile和static的区别

作用范围和变量类型&#xff1a; static关键字用于创建类级别的变量或方法&#xff0c;所有类的实例共享同一个static变量的副本。它还可以用于方法、初始化块和内部类。相比之下&#xff0c;volatile仅用于声明变量&#xff0c;确保在多线程环境中的可见性&#xff0c;使所有线…

Day1--每日一练

&#x1f341; 个人主页&#xff1a;爱编程的Tom&#x1f4ab; 本篇博文收录专栏&#xff1a;每日一练-算法篇&#x1f449; 目前其它专栏&#xff1a;c系列小游戏 c语言系列--万物的开始_ Java专栏等 &#x1f389; 欢迎 &#x1f44d;点赞✍评论⭐收藏&…

向量动态量化

背景介绍 量化&#xff08;Quantization&#xff09;是向量检索技术中一种常用的优化方法&#xff0c;通过一定程度的精度&#xff08;召回率&#xff09;损失&#xff0c;来换取性能的大幅度提升&#xff0c;以及内存占用&#xff08;索引文件大小&#xff09;大幅度降低。 …

一个parquet-go例子

一个parquet-go例子 使用go读写parquet&#xff0c;使用到了框架github.com/xitongsys/parquet-go 代码: package mainimport ("log""time""github.com/xitongsys/parquet-go-source/local""github.com/xitongsys/parquet-go/parquet&qu…

Echarts 实现数据可视化

Echarts 简介 Echarts 是一个开源的、免费的、成熟的、商业级图表可视化框架&#xff0c;是 Apache 开源社区的顶级项目之一&#xff0c;也是国内使用最多和最为广泛的可视化图表框架之一。 数据可视化图表框架并没有一个统一的行业标准&#xff0c;比较常见的有 D3、Highchart…