View体系——View的滑动

系统提供获取坐标值的方法

View提供的获取坐标值方法:

getTop():View本身顶部到其父布局顶部的距离
getLeft():View本身左边到其父布局左边的距离
getRight():View本身右边到其父布局左边的距离
 getBottom():View本身底部到其父布局顶部的距离 

MotionEvent提供的获取坐标值方法:

getX():点击事件距离View本身左边的距离
getY():点击事件距离View本身顶部的距离
getRawX():点击事件距离屏幕左边的距离
getRawY():点击事件距离屏幕顶部的距离

实现滑动的七种方法

1、layout方法

重写onTouchEvent()方法,通过MotionEvent的getX()、getY()获取当前触摸点的坐标值,在MotionEvent.ACTION_MOVE判断里面计算偏移量并调用layout()方法重新调整View的位置。注意当使用getRawX()、getRawY()方法获取当前触摸点的坐标值时,需要重新设置初始坐标。

getX()、getY()
getRawX()、getRawY() 

2、offsetLeftAndRight()和offsetTopAndBottom()

这个方法相当于系统提供的一个对左右、上下移动的API封装,当计算出偏移量后,只需要调用该方法并传入偏移量参数即可,效果与layout()一样。

offsetLeftAndRight()和offsetTopAndBottom()

3、LayoutParams

使用 getLayoutParams() 方法获取 LayoutParams 时,需要根据 View 所在父布局的类型
来设置不同的类型进行强制转换,如果没有父布局是无法获取 LayoutParams 参数的。或者
可以直接使用 ViewGroup.MarginLayoutParams 直接改变 View 的 Margin 属性。

LayoutParams

4、scrollTo()、scrollBy()

scrollTo(x, y)表示移动到一个具体的坐标点(x, y);scrollBy(dx, dy)表示移动的增量为dx、dy;
特别注意:
(1)scrollTo()、scrollBy()方法移动的是View的content内容,例如TextView的content就是文本,ImageView的content就是Drawable对象;如果在ViewGroup中使用scrollTo()、scrollBy()方法,那么移动的就是所有的子View。
(2)如果从左往右滑动,那么mScrollX为负值,反之为正值。

scrollTo()、scrollBy()

5、Scroller类

通过Scroller类可以实现平滑移动的效果,而不再是瞬间完成的移动。

具体使用方法如下:

(1)通过构造方法初始化一个Scroller对象;
(2)重写computeScroll()方法,实现模拟滑动;
(3)调用startScroll()方法开启滑动;

注意点:

(1)View类的computeScroll()方法是使用Scroller类的核心,系统在绘制View的时候会在draw()方法中调用;computeScroll()方法在View中是一个空实现,需要我们自己实现它,一般在该方法里调用scrollTo()实现模拟滑动。但是computeScroll()方法不会自动调用,只能通过invalidate() -> draw() -> computeScroll()来间接调用,所以一般需要在该方法最后添加invalidate()方法进行重绘。
(2)Scroller类的computeScrollOffset()方法用于判断是否完成整个滑动,如果完成了滑动则返回false,否则返回true。
(3)Scroller类提供getCurrX()和getCurrY()方法来获取当前的滑动坐标。
(4)Scroller类的startScroll()方法有两个重载方法,可以设置duration参数来确定滑动时间(默认是250ms);前两个参数表示起始坐标,后两个参数表示偏移量,在获取坐标时通常可以使用getScrollX()和getScrollY()方法来获取父视图中View所滑动到的点的坐标。

Scroller的工作原理:

Scroller本身并不能实现滑动效果,必须结合View的computeScroll()方法才能完成弹性滑动的效果,它不断让View重绘,而每一次重绘距离滑动起始时间会有一个时间间隔(duration),通过这个时间间隔Scroller 就可以得出View当前的滑动位置,知道了滑动位置就可以通过scrollTo() 方法来实现滑动。就这样,View的每一次重绘都会导致View进行小幅度的滑动,而多次小幅度滑动在视觉上就形成了弹性滑动。

Scroller的源码解析:

Scroller类的startScroll()方法并没有调用类似开启滑动的方法,而是保存了传进来的各种参数:startX和startY表示滑动开始的起点,dx和dy表示滑动的距离,duration表示滑动持续的时间。所以 startScroll()方法只是用来做前期准备的,并不能使View进行滑动。关键在于我们在 startScroll()方法后面调用了invalidate()方法,这个方法会导致View重绘,而View的重绘会调用draw()方法,draw()方法又会调用View的computeScroll()方法。

startScroll()

我们在computeScroll()方法中通过Scroller来获取当前的ScrollX和ScrollY,然后调用scrollTo()方法进行真正的滑动,接着调用invalidate()方法让View进行重绘,而重绘又会调用 computeScroll()方法实现View的滑动,这样通过不断移动一个小的距离并连贯起来就实现了平移滑动的效果。

但是如何获取当前的ScrollX和ScrollY呢?在 computeScrollOffset()方法中,首先会计算动画持续的时间timePassed,如果动画持续的时间小于我们设置的滑动持续时间mDuration,就会进入switch语句,由于startScroll()方法设置的mMode为SCROLL_MODE,所以只会执行分支语句SCROLL_MODE,然后根据插值器Interpolator来计算出在该段时间内的移动距离,并赋值给mCurrX和mCurrY。所以可以直接通过Scroller的getCurrX()和getCurrY()方法获取当前的ScrollX和ScrollY。

computeScroll()
computeScrollOffset()

6、属性动画

7、ViewDragHelper

通过ViewDragHelper基本可以实现各种不同的滑动、拖放需求,因此这个方法也是各种滑动解决方案中的终极绝招,但是使用起来比较复杂。Google在其support库中为我们提供了DrawerLayout和SlidingPaneLayout两个布局来帮助开发者实现侧边栏滑动的效果,这两个布局底层就是使用ViewDragHelper来实现的。

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

推荐阅读更多精彩内容