Android View系列 - 坐标系

Android系统中有两种坐标系, Android坐标系和View坐标系. 

Android坐标系

Android坐标系对应于屏幕左上角原点(0,0)坐标, X轴向右递增, Y轴向下递增. getRawX()和getRawY()用于获取屏幕坐标. getRawX()于getRawY()获得相对于屏幕的触摸事件位置坐标. 如下图:


Android坐标系

View坐标系

其次,还有View坐标系. View坐标系与Android坐标系相辅相成. View坐标系中坐标使用getX() 和 getY()获得. 它与系统坐标系的区别在于View坐标系的以View的左上角作为坐标原点,X轴向右递增,Y轴向下递增.getX()与getY()获得触摸事件(MotionEvent)的坐标, 即相对于View的触摸位置坐标. 如下图:


View坐标系

View的位置

一个View的位置由View的(左上右下)四个顶点决定,分别通过getLeft(), getTop(), getRight()和getBottom()方法获得.  该方法分别返回View的mLeft, mTop, mRight, mBottom.

其中Android官方文档对以上属性的注释分别为:

mLeft: Left position of this view relative to its parent.

mTop:  Top position of this view relative to its parent.

可见View的坐标位置是相对于其父View的.  getLeft() 得到的是 View的左边界到父 View左边界的距离, getRight得到的是View的右边界到父 View的左边界的距离. getTop()则是View的上边界到父 View上边界的距离, getBottom()是View的底部边界到父 View上边界的距离.


View的位置

触控事件

MotionEvent继承自InputEvent, 是Android系统中关于用户交互重要的类. 内部封装了常用的事件常量:

ACTION_DOWN

ACTION_UP

ACTION_MOVE

ACTION_CANCEL  

ACTION_OUTSIDE

ACTION_SCROLL

......

ACTION_CANCEL

官方对ACTION_CANCEL事件的解释是当前手势被中断,你将不会收到关于它的任何点. 且你应该认为它是一个UP事件,但是不执行任何操作. Android的事件体系中 DOWN 到 UP所有的事件称为一次完整的事件序列, 当一个事件序列正在执行, 父View拦截其中一个事件时,当前View将会收到一个CANCEL事件, 当前事件之后的事件序列将不会被执行. 详细可在ViewGroup中查看关于CANCEL的处理.

ACTION_OUTSIDE

手势超出View元素边界时,将会发出该事件. 默认情况下该事件不会分发给ViewGroup的任何子 View,且应当在根布局中处理. 对于该事件可以参考Android对Dialog的处理.

ACTION_SCROLL

scroll事件不是touch事件,因此不会被分发给onTouchEvent,而是由onGenericMotionEvent()处理.此操作始终传递到指针下的窗口或视图. 和scroll事件一样,还有其他很多事件交给onGenericMotionEvent()处理. 

MotionEvent通过getX()/getY() 或者 getRawX()/getRawY()获得用户输入事件的View坐标或屏幕坐标.

View坐标补充

1. View.getX()...

     据官方定义getX()方法返回的是以像素为单位,View的可视x轴位置. 相当于View的translationX + mLeft 之和. 也就是说View的mLeft加当前View的X轴的偏移量. 假定一个View初始坐标(View坐标系)是(100,100), 且宽高均为100. 那么其mLeft也就是100, 而其translationX偏移量初始值是0, View.getX()返回0. 但是如果通过属性动画ObjectAnimator.ofFloat(view,translationX...使得View的坐标发生改变50个像素,那么View的getX()就是mLeft(100) + translationX(50) = 150.

2. View.getTranslationX()...

      getTranslationX()返回当前View相对于mLeft属性在X轴方向的偏移量, 当然使用属性动画使View发生平移,即改变View的TranslationX属性,但并未改变View的原始坐标.

3. View.getScrollX()...

      scrollX反应的是scrollTo()和scrollBy()函数的影响,它是View的内容水平移动的的偏移量.  scrollTo()和scrollBy()会改变View的内容位置. 手机的屏幕可以视为一个窗口,窗口内部的内容可以无限的移动变化.  见图:


scrollX

这张图来源网上,只是觉得用来描述scrollX偏移量在合适不过就拿来使用.

橙色方框可以视为屏幕窗口, 蓝色方块就是屏幕展示的内容, 蓝色区域在窗口左边界的初始x坐标是0,当向右推动,其值变为-100, getScrollX()返回-100. 当向左边推动,蓝色区域在窗口左边界的X坐标为100, getScrollX()返回100.

View的滑动方式

View的滑动主要是操作View的坐标,View的滑动方式有6种:

1. layout(left,top,right,bottom)

        layout方式是通过不断更新View的mLeft,mTop等属性更新View的位置, 内部通过setFrame()方法进行位置更新.

2. offsetLeftAndRight(offsetX) 和 offsetTopAndBottom(offsetY)

         offsetLeftAndRight()传入的是一个偏移量,即要平移的距离.

3. 通过layoutParams设置margin值改变View的位置实现滑动

       LayoutParam中封装了View的宽高等信息,View也可以通过LayoutParam来设置margin来实现移动,如leftMargin,topMargin等.

4. View动画和属性动画

       View动画底层采用Matrix(矩阵)实现,现在先不说Matrix的具体原理. 虽然View动画可以实现平移,但实际上却更像是一个假象. View的位置并不会平移,如果View有点击事件,那么只有动画开始之前的位置会触发事件.

       属性动画改变了View动画的缺点, 内部通过改变View的相关属性实现View的滑动. 

5. scrollTo()和scrollBy()

scrollTo(x,y) 传入的一个坐标位置,scrollBy()实际上仍然调用scrollTo()函数,scrollBy()则传入一个偏移量. 需要注意的是,无论scrollTo()还是scrollBy(),滑动的都是View的内容, 如果是ViewGroup,则会滑动ViewGroup内的全部子 View. 

6. 结合Scroller实现滑动

Scroller本身并不会实现滑动, 需要结合View自身的一些方法实现滑动. 使用layout,scrollTo等方法实现滑动,效果比较生硬.使用方法如下:

 1. 初始化一个Scroller

      Scroller scroller = new Scroller();

2. 调用startScroller(),该方法并非要开始滑动,而是要设置View滑动的相关参数

     scroller.startScroll(..); postInvalidate(); //赋值后使View重绘

3. 在View的回调方法onCompute()方法中实现滑动

if(scroller.computeScrollOffset()){

 // 返回true,view的滑动未完成.该方法内部计算了View坐标随时间发生的变化

     scrollTo(x,y); //使View滑动

     postInvalidate(); //继续重绘

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容