View體系——View的滑動(dòng)

系統(tǒng)提供獲取坐標(biāo)值的方法

View提供的獲取坐標(biāo)值方法:

getTop():View本身頂部到其父布局頂部的距離
getLeft():View本身左邊到其父布局左邊的距離
getRight():View本身右邊到其父布局左邊的距離
?getBottom():View本身底部到其父布局頂部的距離?

MotionEvent提供的獲取坐標(biāo)值方法:

getX():點(diǎn)擊事件距離View本身左邊的距離
getY():點(diǎn)擊事件距離View本身頂部的距離
getRawX():點(diǎn)擊事件距離屏幕左邊的距離
getRawY():點(diǎn)擊事件距離屏幕頂部的距離

實(shí)現(xiàn)滑動(dòng)的七種方法

1贪惹、layout方法

重寫onTouchEvent()方法,通過MotionEvent的getX()、getY()獲取當(dāng)前觸摸點(diǎn)的坐標(biāo)值甘穿,在MotionEvent.ACTION_MOVE判斷里面計(jì)算偏移量并調(diào)用layout()方法重新調(diào)整View的位置撑螺。注意當(dāng)使用getRawX()、getRawY()方法獲取當(dāng)前觸摸點(diǎn)的坐標(biāo)值時(shí)监憎,需要重新設(shè)置初始坐標(biāo)庆揩。

getX()、getY()
getRawX()洽洁、getRawY()?

2痘系、offsetLeftAndRight()和offsetTopAndBottom()

這個(gè)方法相當(dāng)于系統(tǒng)提供的一個(gè)對(duì)左右、上下移動(dòng)的API封裝饿自,當(dāng)計(jì)算出偏移量后汰翠,只需要調(diào)用該方法并傳入偏移量參數(shù)即可,效果與layout()一樣昭雌。

offsetLeftAndRight()和offsetTopAndBottom()

3复唤、LayoutParams

使用 getLayoutParams() 方法獲取 LayoutParams 時(shí),需要根據(jù) View 所在父布局的類型
來設(shè)置不同的類型進(jìn)行強(qiáng)制轉(zhuǎn)換烛卧,如果沒有父布局是無法獲取 LayoutParams 參數(shù)的佛纫。或者
可以直接使用 ViewGroup.MarginLayoutParams 直接改變 View 的 Margin 屬性总放。

LayoutParams

4呈宇、scrollTo()、scrollBy()

scrollTo(x, y)表示移動(dòng)到一個(gè)具體的坐標(biāo)點(diǎn)(x, y)局雄;scrollBy(dx, dy)表示移動(dòng)的增量為dx攒盈、dy;
特別注意:
(1)scrollTo()哎榴、scrollBy()方法移動(dòng)的是View的content內(nèi)容型豁,例如TextView的content就是文本,ImageView的content就是Drawable對(duì)象尚蝌;如果在ViewGroup中使用scrollTo()迎变、scrollBy()方法,那么移動(dòng)的就是所有的子View飘言。
(2)如果從左往右滑動(dòng)衣形,那么mScrollX為負(fù)值,反之為正值姿鸿。

scrollTo()谆吴、scrollBy()

5、Scroller類

通過Scroller類可以實(shí)現(xiàn)平滑移動(dòng)的效果苛预,而不再是瞬間完成的移動(dòng)句狼。

具體使用方法如下:

(1)通過構(gòu)造方法初始化一個(gè)Scroller對(duì)象;
(2)重寫computeScroll()方法热某,實(shí)現(xiàn)模擬滑動(dòng)腻菇;
(3)調(diào)用startScroll()方法開啟滑動(dòng)胳螟;

注意點(diǎn):

(1)View類的computeScroll()方法是使用Scroller類的核心,系統(tǒng)在繪制View的時(shí)候會(huì)在draw()方法中調(diào)用筹吐;computeScroll()方法在View中是一個(gè)空實(shí)現(xiàn)糖耸,需要我們自己實(shí)現(xiàn)它,一般在該方法里調(diào)用scrollTo()實(shí)現(xiàn)模擬滑動(dòng)丘薛。但是computeScroll()方法不會(huì)自動(dòng)調(diào)用嘉竟,只能通過invalidate() -> draw() ->?computeScroll()來間接調(diào)用,所以一般需要在該方法最后添加invalidate()方法進(jìn)行重繪洋侨。
(2)Scroller類的computeScrollOffset()方法用于判斷是否完成整個(gè)滑動(dòng)周拐,如果完成了滑動(dòng)則返回false,否則返回true凰兑。
(3)Scroller類提供getCurrX()和getCurrY()方法來獲取當(dāng)前的滑動(dòng)坐標(biāo)妥粟。
(4)Scroller類的startScroll()方法有兩個(gè)重載方法,可以設(shè)置duration參數(shù)來確定滑動(dòng)時(shí)間(默認(rèn)是250ms)吏够;前兩個(gè)參數(shù)表示起始坐標(biāo)勾给,后兩個(gè)參數(shù)表示偏移量,在獲取坐標(biāo)時(shí)通彻可以使用getScrollX()和getScrollY()方法來獲取父視圖中View所滑動(dòng)到的點(diǎn)的坐標(biāo)播急。

Scroller的工作原理:

Scroller本身并不能實(shí)現(xiàn)滑動(dòng)效果,必須結(jié)合View的computeScroll()方法才能完成彈性滑動(dòng)的效果售睹,它不斷讓View重繪桩警,而每一次重繪距離滑動(dòng)起始時(shí)間會(huì)有一個(gè)時(shí)間間隔(duration),通過這個(gè)時(shí)間間隔Scroller 就可以得出View當(dāng)前的滑動(dòng)位置昌妹,知道了滑動(dòng)位置就可以通過scrollTo() 方法來實(shí)現(xiàn)滑動(dòng)捶枢。就這樣,View的每一次重繪都會(huì)導(dǎo)致View進(jìn)行小幅度的滑動(dòng)飞崖,而多次小幅度滑動(dòng)在視覺上就形成了彈性滑動(dòng)烂叔。

Scroller的源碼解析:

Scroller類的startScroll()方法并沒有調(diào)用類似開啟滑動(dòng)的方法,而是保存了傳進(jìn)來的各種參數(shù):startX和startY表示滑動(dòng)開始的起點(diǎn)固歪,dx和dy表示滑動(dòng)的距離蒜鸡,duration表示滑動(dòng)持續(xù)的時(shí)間。所以 startScroll()方法只是用來做前期準(zhǔn)備的牢裳,并不能使View進(jìn)行滑動(dòng)逢防。關(guān)鍵在于我們在 startScroll()方法后面調(diào)用了invalidate()方法,這個(gè)方法會(huì)導(dǎo)致View重繪蒲讯,而View的重繪會(huì)調(diào)用draw()方法忘朝,draw()方法又會(huì)調(diào)用View的computeScroll()方法。

startScroll()

我們在computeScroll()方法中通過Scroller來獲取當(dāng)前的ScrollX和ScrollY伶椿,然后調(diào)用scrollTo()方法進(jìn)行真正的滑動(dòng)辜伟,接著調(diào)用invalidate()方法讓View進(jìn)行重繪,而重繪又會(huì)調(diào)用 computeScroll()方法實(shí)現(xiàn)View的滑動(dòng)脊另,這樣通過不斷移動(dòng)一個(gè)小的距離并連貫起來就實(shí)現(xiàn)了平移滑動(dòng)的效果导狡。

但是如何獲取當(dāng)前的ScrollX和ScrollY呢?在 computeScrollOffset()方法中偎痛,首先會(huì)計(jì)算動(dòng)畫持續(xù)的時(shí)間timePassed旱捧,如果動(dòng)畫持續(xù)的時(shí)間小于我們設(shè)置的滑動(dòng)持續(xù)時(shí)間mDuration,就會(huì)進(jìn)入switch語句踩麦,由于startScroll()方法設(shè)置的mMode為SCROLL_MODE枚赡,所以只會(huì)執(zhí)行分支語句SCROLL_MODE,然后根據(jù)插值器Interpolator來計(jì)算出在該段時(shí)間內(nèi)的移動(dòng)距離谓谦,并賦值給mCurrX和mCurrY贫橙。所以可以直接通過Scroller的getCurrX()和getCurrY()方法獲取當(dāng)前的ScrollX和ScrollY。

computeScroll()
computeScrollOffset()

6反粥、屬性動(dòng)畫

7卢肃、ViewDragHelper

通過ViewDragHelper基本可以實(shí)現(xiàn)各種不同的滑動(dòng)、拖放需求才顿,因此這個(gè)方法也是各種滑動(dòng)解決方案中的終極絕招莫湘,但是使用起來比較復(fù)雜。Google在其support庫中為我們提供了DrawerLayout和SlidingPaneLayout兩個(gè)布局來幫助開發(fā)者實(shí)現(xiàn)側(cè)邊欄滑動(dòng)的效果郑气,這兩個(gè)布局底層就是使用ViewDragHelper來實(shí)現(xiàn)的幅垮。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市尾组,隨后出現(xiàn)的幾起案子忙芒,更是在濱河造成了極大的恐慌,老刑警劉巖讳侨,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件匕争,死亡現(xiàn)場離奇詭異,居然都是意外死亡爷耀,警方通過查閱死者的電腦和手機(jī)甘桑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來歹叮,“玉大人跑杭,你說我怎么就攤上這事∨毓ⅲ” “怎么了德谅?”我有些...
    開封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長萨螺。 經(jīng)常有香客問我窄做,道長愧驱,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任椭盏,我火速辦了婚禮组砚,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘掏颊。我一直安慰自己糟红,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開白布乌叶。 她就那樣靜靜地躺著盆偿,像睡著了一般。 火紅的嫁衣襯著肌膚如雪准浴。 梳的紋絲不亂的頭發(fā)上事扭,一...
    開封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音乐横,去河邊找鬼句旱。 笑死,一個(gè)胖子當(dāng)著我的面吹牛晰奖,可吹牛的內(nèi)容都是我干的谈撒。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼匾南,長吁一口氣:“原來是場噩夢啊……” “哼啃匿!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蛆楞,我...
    開封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤泪漂,失蹤者是張志新(化名)和其女友劉穎监婶,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡嘉抓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年话原,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了告材。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片齿拂。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖孩等,靈堂內(nèi)的尸體忽然破棺而出艾君,到底是詐尸還是另有隱情,我是刑警寧澤肄方,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布冰垄,位于F島的核電站,受9級(jí)特大地震影響权她,放射性物質(zhì)發(fā)生泄漏虹茶。R本人自食惡果不足惜逝薪,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蝴罪。 院中可真熱鬧董济,春花似錦、人聲如沸洲炊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽暂衡。三九已至,卻和暖如春崖瞭,著一層夾襖步出監(jiān)牢的瞬間狂巢,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來泰國打工书聚, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留唧领,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓雌续,卻偏偏與公主長得像斩个,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子驯杜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • 導(dǎo)語 滑動(dòng)算是Android比較常用的效果了受啥,滑動(dòng)的操作具有很好的用戶體驗(yàn)性。 主要內(nèi)容 滑動(dòng)效果是如何產(chǎn)生的 實(shí)...
    一個(gè)有故事的程序員閱讀 6,436評(píng)論 3 11
  • 內(nèi)容是博主照著書敲出來的鸽心,博主碼字挺辛苦的滚局,轉(zhuǎn)載請注明出處,后序內(nèi)容陸續(xù)會(huì)碼出顽频。 當(dāng)了解了Android坐標(biāo)系和觸...
    Blankj閱讀 6,626評(píng)論 3 61
  • 一滑動(dòng)效果的產(chǎn)生 滑動(dòng)一個(gè)View藤肢,本質(zhì)區(qū)別就是移動(dòng)一個(gè)View。改變當(dāng)前View所在的坐標(biāo)糯景,原理和動(dòng)畫相似不斷改...
    猿萬閱讀 9,849評(píng)論 0 14
  • 什么是View View 是 Android 中所有控件的基類嘁圈。 View的位置參數(shù) View 的位置由它的四個(gè)頂...
    acc8226閱讀 1,151評(píng)論 0 7
  • 一、為什么要學(xué)會(huì)Scroll 我們在寫自定義View的時(shí)候蟀淮,避免不了要讓用戶能夠和這個(gè)View進(jìn)行交互丑孩,而因?yàn)锳n...
    逝水比喻時(shí)光閱讀 678評(píng)論 0 10