Android中坐标体系知识超详细讲解

说来说去都不如画图示意简单易懂啊!!!真是的! 来吧先上张图!

(一)首先明确一下android 中的坐标系统:
屏幕的左上角是坐标系统原点(0,0)
原点向右延伸是X轴正方向,原点向下延伸是Y轴正方向


(二)关于Scroll: 屏幕显示的内容很多时,会有超出一屏的情况,于是就产生了Scroll的概念。
在View类中有个方法:

getScrollY() 英文原文描述是:
Return the scrolled top position of this view. This is the top edge of the displayed part of your
view....

其实理解起来仍然就是:就是这个view相对于“坐标系统原点”(见上图)在Y轴上的偏移量.
(getScrollX同理)
【哇哈,有了图就是好说明啊~ 省了多少语言描述啊,而且还不一定能说清楚~】
getScrollY()就是当前视图相对于屏幕原点在Y轴上的偏移量.


(三)MotionEvent类中getRowX()和getX()的区别:
event.getRowX():触摸点相对于屏幕原点的x坐标event.getX(): 触摸点相对于其所在组件
原点的x坐标
于是乎: view.getScrollY() + event.getY() 就得到了view中的触摸点在Y轴上的偏移量


(四)TextView类中
有个getLayout()方法:the Layout that is currently being used to display the text. This
can be null if the text or width has recently changes.
其返回类型是Layout ,也就是返回textView的布局。
然后重要的是通过这个layout调用一个方法:
getLineForVertical(int verticalPointPosition) //得到某点在垂直方向上的行数值
于是综上所述,在实际的触摸事件中可以这样使用:
Layout layout=textView.getLayout();
int line = layout.getLineForVertical(textView.getScrollY() + (int) event.getY());

//得到触摸点在textView中垂直方向上的行数值。参数是触摸点在Y轴上的偏移量
接下来继续介绍一个方法, 要用到上边的layout 和line:
layout.getOffsetForHorizontal( line , (int) event.getX() );
//得到触摸点在某一行水平方向上的偏移量。
参数分别是: 该行行数值和触摸点在该行X轴上的偏移量。
此方法得到的该值会根据该行上的文字的多少而变化,并不是横向上的像素大小;

整个坐标系是以手机屏幕左上角为原点(0,0),如果在屏幕没有滑动之前,这一理解肯定是ok
的,但在滑屏之后,就会产生很多歧义和混淆,原因在于使用过程当中,很多方法的参数并非是
参照屏幕,而是相对于父视图,对这整个过程和后面自定义控件的坐标变化带来的各个参数变化
来说理解起来就并不那么适合了,最开始给人的感觉是越来越不清楚这个坐标该怎么设置,好像
坐标系总在发生变化,后来才慢慢在思维当中构建起视图与视图容器以及屏幕之间的关系。


android.view.View.layout(int l, int t, int r, int b) layout的过程就是确定View在屏幕上显示的具体位
置,在代码中就是设置其成员变量mLeft,mTop,mRight,mBottom的值,这几个值构成的矩形
区域就是该View显示的位置, 不过这里的具体位置都是相对与父视图的位置。mLeft代表当前
view.layout的这个view的左边缘离它的父视图左边缘的距离,拿上面“子视图2.layout(int l, int t,
int r, int b) ”来说,它的父视图便是子视图1,2,3合起来形成的整个大矩形,那么这里将父视图的左
上角定为(0,0),那么可以确定mLeft为一个子视图宽度320,以此类推, mTop指当前view的上边
缘离父视图上边缘的距离。而以此为界, mRight所指的是当前view的右边缘离父视图左边缘的

距离,一眼可以看出值为640(mLeft+自己的宽度),mBottom也是指当前view的下边缘离父视
图的上边缘的距离。至于为何如此,大概是因为坐标系的缘故,坐标中的任何点都必须以(0,0)为
起点,XY轴为衡量。


视图左侧位置view.getLeft() 视图右侧位置view.getRight()
视图顶部位置view.getTop(); 视图底部位置view.getBottom(); 这四个方法所获取到的各个左上右
下的值与layout的四个参数代表的是一样的,都是相对父视图的左边缘与上边缘。
视图宽度view.getWidth(); 视图高度view.getHeight() ; 这两个方法获取的是该view的高和宽,仅
仅在滑动的情况下,或者说该view的大小如果不发生变化,它的值是不会变的。
getMeasuredWidth(); getMeasuredHeight(); 说到这里就不得不提getWidth()、getHeight()和
getMeasuredWidth()、getMeasuredHeight()这两对函数之间的区别,getMeasuredWidth()、
getMeasuredHeight()返回的是measure过程得到的mMeasuredWidth和mMeasuredHeight的值,
而getWidth()和getHeight()返回的是mRight - mLeft和mBottom - mTop的值。

一般情况下layout过程会参考measure过程中计算得到的mMeasuredWidth和mMeasuredHeight来安排子视图在父视图中显示的位置,但这不是必须的,measure过程得到的结果可能完全没有实际用处,特别是对于一些自定义的ViewGroup,其子视图的个数、位置和大小都是固定的,这时候我们可以忽略整个measure过程,只在layout函数中传入的4个参数来安排每个子视图的具体位置。
view.getX(); view.getY(); getX和getY获取到的值为相对于父视图而言的两个左边缘和上边缘的距
离。


view.getLocationOnScreen(location); 该方法可以获取到当前view与屏幕的关系,location(0)代表
X值,表示该view的左边缘与屏幕的左边缘之间的距离。可以想象,当滑屏产生,view开始移动该
值肯定会改变的。location(1)代表Y值,表示该view的上边缘与屏幕的上边缘之间的距离,该距离
肯定是包含标题栏的高度的。getLocationInWindow();
ps:View.getLocationInWindow()和View.getLocationOnScreen()在window占据全部screen时,
返回值相同,不同的典型情况是在Dialog中时。当Dialog出现在屏幕中间时,
View.getLocationOnScreen()取得的值要比View.getLocationInWindow()取得的值要大。
VelocityTracker.getXVelocity() 指滑动速度包括速率和方向两个方面,往左滑动小于0,值为负;
往右滑动大于0,值为正。


view.scrollTo (x,y) 将整个父视图的左上角定为(0,0),再移动这个屏幕的左上角到父视图的点(x,y)
处,注意此处的x和y是根据父视图的坐标系来定的。view.scrollBy(x,y) x代表横向移动的距离,y
代表纵向移动的距离
view.getScrollX view.getScrollY 将整个父视图的左上角定为(0,0),那么子view. getScrollX会获取
到屏幕左边缘减去父视图的左边缘为0的距离,特别当滑屏时,父视图会被迫隐藏一部分,因为屏
幕的大小是固定的。getScrollY以此类推。

event.getX() event.getY() 该方法是不受视图影响的,X和Y的值仅仅代表手指在以左上角(0,0)为原
点的屏幕触摸点的坐标值。
Scroller.getCurrY() Scroller.getCurrX() 该方法拿横轴来说,代表屏幕的左边缘离父视图的左边缘的
距离。


Scroller.startScroll( int startX, int startY, int dx, int dy) 四个参数分别表示起点的坐标和滑动的向
量,即从( startX, startY)开始滑动,横向滑动dx的距离,纵向滑动dy的距离(正值向左滑,负值向
右滑),而这里的startX, startY又是参照的父视图左上角为原点坐标的坐标系,滑屏时经常使用
getScrollX()和getScrollY()来代表屏幕左边缘和上边缘处于父视图坐标系的具体位置
TranslateAnimation() 参数参照:http://blog.sina.com.cn/s/blog_90b91bf10101ai3e.html
以上是在做滑屏控件经常用到的方法,一方面需要了解layout和measure的基本流程,更重要一方
面,当你想要实现某一个效果的时候,比如slidingmenu那样的控件,查看源码我们可以知道它是
继承的ViewGroup,该怎样入手去做呢。


首先,需要了解它的父视图是什么,slidingmenu为例,打开程序,第一眼,是一个很普通的视图
页面,当向右滑动手指,这个视图页面开始向右边移动,而从左边会慢慢移出来另一部分视图,
看上去像是抽出来的或者是隐藏的,事实上抛开阴影效果来讲,想象手机屏幕的左边有一部分我
们看不到的视图,它就是这个被抽出来的menu视图了。

概括来说,一个主view,一个menu其实
是并排于一个大视图上面的。找到了父视图,接下来就好办了,认定这个父视图的宽度就是主
view的宽度和menu的宽度之和(暂不考虑padding之类),高度就是屏幕的高度,那么在思维当中
这个二维平面就产生了,将它想成一张纸,然后对准主view将这张纸贴到手机屏幕上,左右滑
动,会看到其实slidingmenu也就是这么个效果。


然后,实现的思路会清晰很多。定义这个父视图为myview继承viewgroup,原因在于尽管主view
和menu并排在一个大view下,但毕竟两者的内容不同,后面需要放进不同的控件处理不同的事
件,这个父视图内包含着两个view,到时候处理起来会方便很多,setcontentview为这个父视
图,那么打开程序的第一眼就会看到它。再定义这两个view设置好两个内容布局,并将它们
addview添加到myview当中。外部工作基本就完成了,可以呈现父视图,并且父视图内有两个子
view。
接下来,需要去完善一些细节,父视图内的子view该如何放置,这是关乎成败的一环,也就是如
何将这张纸贴到我们希望的位置,这时就是onlayout的处理了,处理好屏幕,父视图子view之间
的位置关系,通过各自的layout参数设置来摆放妥当各个view,比如开始的时候menu是隐藏的,
这个就是通过位置的摆放设置的,然后它是从左边滑出来的,说明它处于父视图的左边位置,而
主view处于相对右边的位置,而屏幕刚好也处于父视图右边的位置,恰好能看到主view的全貌,
在脑海里如果能有清晰的画面出现,实现起来就会轻松很多。当实现了这个摆放,就可以理解
menudrawer里面上下左右都可以滑出menu的结构了。


最后,便是滑动效果,请相信这样的控件里面,任何处理肯定都会和view位置的摆放扯上关系,
滑动方向,滑动距离等等都涉及到坐标的处理。这也是为何上面列出那些常用的获取view坐标的方法。


总结下来,构建类似这样的控件,也就这三点,明确父子视图和屏幕的关系,通过坐标和位置参
数设置它们的关系,处理这些关系发生变化的情况。
当然,事实上slidingmenu远远没这么简单,其中为了方便后续开发,它内置了很多接口和处理,
大多数都是位置坐标和事件监听相关联,而万变不离其宗的是,它也肯定有这三个方面的构建,
理解了这些基本的东西,尝试做一些自己想象的效果,对自定义的理解来说,进步会非常大。

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

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

相关文章

泷羽sec学习打卡-brupsuite7搭建IP炮台

声明 学习视频来自B站UP主 泷羽sec,如涉及侵权马上删除文章 笔记的只是方便各位师傅学习知识,以下网站只涉及学习内容,其他的都 与本人无关,切莫逾越法律红线,否则后果自负 关于brupsuite的那些事儿-Brup-IP炮台搭建 搭建炮台服务端安装zmap1、更新系统和安装基础依赖&#xff…

【视频异常检测】Real-Time Anomaly Detection and Localization in Crowded Scenes 论文阅读

文章信息: 发表于:CVPR2015(workshop) 原文链接:https://www.cv-foundation.org/openaccess/content_cvpr_workshops_2015/W04/papers/Sabokrou_Real-Time_Anomaly_Detection_2015_CVPR_paper.pdf Real-Time Anomaly D…

Hive-4.0.1数据库搭建(可选配置用户名密码远程连接,涵盖切换为tez引擎)

一、hive搭建(所依赖的Hadoop集群参照文章:最新版hadoop-3.4.0集群安装和配置(目前论坛的都是老古董了,看我的准没错!!!)这里以三台服务器为例_hadoop 3.4安装-CSDN博客)…

YOLOv11改进,YOLOv11添加DLKA-Attention可变形大核注意力,WACV2024 ,二次创新C3k2结构

摘要 作者引入了一种称为可变形大核注意力 (D-LKA Attention) 的新方法来增强医学图像分割。这种方法使用大型卷积内核有效地捕获体积上下文,避免了过多的计算需求。D-LKA Attention 还受益于可变形卷积,以适应不同的数据模式。 理论介绍 大核卷积(Large Kernel Convolu…

Reactor 响应式编程(第二篇:Spring Webflux)

系列文章目录 Reactor 响应式编程(第一篇:Reactor核心) Reactor 响应式编程(第二篇:Spring Webflux) Reactor 响应式编程(第三篇:R2DBC) Reactor 响应式编程&#xff08…

keepalived的高可用集群

keepalived的概念 keepalived的工作原理 基于vrrp实现的调度器高可用方案 keepalived的配置实验 先在调度服务器上安装keepalived和ipvsadm apt -y install keepalived ipvsadm 复制keepalived的配置文件到/etc/keepalived/目录下 cp /usr/share/doc/keepalived/samples/keep…

Linux中输入和输出基本过程

1.文件内核级缓冲区 前面在如何理解Linux一切皆文件的特点中提到为了保证在Linux中所有进程访问文件时的方式趋近相 同,在f ile 结构体中存在一个 files_operations 结构体指针,对应的结构体保存所有文件操作的函 数指针(这个结构体也被称为…

shell编程2 永久环境变量和字符串显位

声明 学习视频来自B站UP主 泷羽sec 常见变量 echo $HOME (家目录 root用户) /root cd /root windows的环境变量可以去设置里去新建 为什么输入ls dir的命令的时候就会输出相应的内容呢 因为这些命令都有相应的变量 which ls 通过这个命令查看ls命令脚本…

如何对 Java 项目简化接口设计提升开发效率

文章目录 摘要引言简洁接口设计的原则示例代码OrderProcessor 接口StandardOrderProcessor 实现类Order 数据类调用方代码:OrderService 模块之间的协作QA 环节总结参考资料 摘要 简洁的接口设计可以有效降低代码依赖与耦合度,提高代码的可维护性和扩展…

Node.js安装配置+Vue环境配置+创建一个VUE项目

目录 安装Node.js搭建VUE环境 安装Node.js 下载 测试是否安装成功 在目录下新建两个文件夹 管理员打开cmd npm config set prefix "D:\Software\nodejs\node_global" npm config set cache "D:\Software\nodejs\node_cache"将默认的 C 盘下【 AppData\…

【Spring 全家桶】Spring MVC 快速入门,开始web 更好上手(上篇) , 万字解析, 建议收藏 ! ! !

本篇会加入个人的所谓鱼式疯言 ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. 🤭🤭🤭可能说的不是那么严谨.但小编初心是能让更多人…

【CSS in Depth 2 精译_080】 13.1:CSS 渐变效果(中)——不同色彩空间的颜色插值算法在 CSS 渐变中的应用

当前内容所在位置(可进入专栏查看其他译好的章节内容) 第四部分 视觉增强技术 ✔️【第 13 章 渐变、阴影与混合模式】 ✔️ 13.1 渐变 ✔️ 13.1.1 使用多个颜色节点(上)13.1.2 颜色插值方法(中) ✔️13.1…

JavaEE 【知识改变命运】06 多线程进阶(1)

文章目录 锁一常见的锁乐观锁和悲观锁轻量级锁和重量级锁自旋锁和挂起等待锁读写锁和普通互斥锁公平锁和不公平锁可重入锁和不可重入锁sycnchroized是什么锁 CAS什么是CASCAS伪代码CSA是怎么实现的CAS如何保证线程安全的呢实现自旋锁JDK中提供的使用自旋锁的方式处理锁竞争CAS …

Elasticsearch02-安装7.x

零、文章目录 Elasticsearch02-安装7.x 1、Windows安装Elasticsearch (1)JDK安装 Elasticsearch是基于java开发的,所以需要安装JDK。我们安装的Elasticsearch版本是7.15,对应JDK至少1.8版本以上。也可以不安装jdk,…

又要考试了

一、实现无名管道练习&#xff1a;父进程写入管道&#xff0c;子进程读取管道数据。 #include<myhead.h> int main(int argc, const char *argv[]) {int fd[2];char buff[1024]"王吕阳&#xff0c;崔庆权别卷了";char s[1024];if(pipe(fd)-1){perror("pi…

Unity添加newtonsoft-json

package name "com.unity.nuget.newtonsoft-json": "3.2.1",打开包管理器 输入包名称和版本 点击添加

HarmonyOS:多线程并发-Worker

Worker主要作用是为应用程序提供一个多线程的运行环境&#xff0c;可满足应用程序在执行过程中与宿主线程分离&#xff0c;在后台线程中运行一个脚本进行耗时操作&#xff0c;极大避免类似于计算密集型或高延迟的任务阻塞宿主线程的运行。具体接口信息及使用方法详情请见Worker…

JMeter配置原件-计数器

一、面临的问题&#xff1a; 由于本人的【函数助手对话框】中counter计数器每次加2&#xff0c;且只显示偶数(如下图所示)&#xff0c;因此借助【配置原件-计数器】来实现计数功能。 如果有大佬知道解决方式&#xff0c;麻烦评论区解答一下&#xff0c;谢谢。 二、配置原件-c…

系统可观测性——Logback日志框架

摘要 Logback是一种Java日志框架&#xff0c;可以提供高度可配置的日志记录功能&#xff0c;包括级别控制和事件过滤等功能。它基于SLF4J&#xff08;Simple Logging Facade for Java&#xff09;日志抽象层&#xff0c;可以与多种流行的Java日志框架兼容&#xff0c;如Log4j和…

【自然语言处理与大模型】使用llama.cpp将HF格式大模型转换为GGUF格式

llama.cpp的主要目标是在本地和云端的各种硬件上以最小的设置和最先进的性能实现LLM推理。是一个专为大型语言模型&#xff08;LLM&#xff09;设计的高性能推理框架&#xff0c;完全使用C和C编写&#xff0c;没有外部依赖&#xff0c;这使得它可以很容易地被移植到不同的操作系…