Android點(diǎn)擊列表后彈出輸入框,所點(diǎn)擊項(xiàng)自動(dòng)滾動(dòng)到輸入框上方
使用微信的朋友圈會(huì)發(fā)現(xiàn),點(diǎn)擊某一條評(píng)論后輸入框會(huì)彈出來,然后所點(diǎn)擊的那一項(xiàng)會(huì)自動(dòng)地滾動(dòng)到輸入框上方的位置,這樣如果開始所點(diǎn)擊的評(píng)論在屏幕很下方的話,就不會(huì)被輸入框遮住,雖然微信這一點(diǎn)在我的MX2頻繁點(diǎn)幾次后滾動(dòng)的位置就完全錯(cuò)誤了,但據(jù)說在有些機(jī)型上效果還不錯(cuò),還有其他地方可能會(huì)有類似的需求,比如登錄時(shí)軟鍵盤可能會(huì)把登錄按鈕遮住。
要實(shí)現(xiàn)這個(gè)功能需要注意的地方主要有兩點(diǎn):
- 什么時(shí)候進(jìn)行滾動(dòng)操作,以及有可能還需要在輸入框消失時(shí)回滾回去。
- 輸入框彈出后所點(diǎn)擊的項(xiàng)要滾動(dòng)到輸入框上方,這就需要我們計(jì)算要滾動(dòng)的距離。
針對(duì)第一點(diǎn),評(píng)論框出現(xiàn)在軟鍵盤的上方,一般情況下軟鍵盤出來后評(píng)論框的位置會(huì)移動(dòng),也就是會(huì)出現(xiàn)Layout操作,所以可以在Layout時(shí)計(jì)算滾動(dòng)距離,時(shí)機(jī)就是:
view.getViewTreeObserver().addOnGlobalLayoutListener
評(píng)論框Layout時(shí)的回調(diào),在這里計(jì)算需要滾動(dòng)的距離。
接下來就是滾動(dòng)距離的計(jì)算。
滾動(dòng)距離=所點(diǎn)擊的項(xiàng)底部的Y坐標(biāo) - 軟鍵盤彈出后輸入框頂部的Y坐標(biāo)
所以只要知道這兩個(gè)坐標(biāo)就可以知道需要滾動(dòng)的距離,獲得坐標(biāo)以很簡(jiǎn)單,通過getGlobalVisibleRect就可以了,當(dāng)然還有其他方法,但由于是計(jì)算的差值,保證兩次計(jì)算坐標(biāo)時(shí)用同一個(gè)就可以了。獲得坐標(biāo)后直接smoothScrollBy。
原理就是這么簡(jiǎn)單,不過要實(shí)現(xiàn)起來,細(xì)節(jié)問題搞得人惡心。
比如說輸入框初始的可見性可能是GONE,也可能是Visible,如果是GONE,那么軟鍵盤彈出時(shí)可能會(huì)有兩個(gè)過程,1.從GONE到Visible會(huì)layout一次,2.軟鍵盤彈出又layout一次,隱藏時(shí)一樣。界面剛顯示時(shí)也會(huì)layout,所以這就需要判斷在onGlobalLayout時(shí)是否需要過濾事件。
在MX2上實(shí)驗(yàn),smoothScrollBy有兩個(gè)參數(shù),第二個(gè)是duration,如果duration過小,可能你傳入的distance是600,系統(tǒng)卻可能只會(huì)滾動(dòng)500。
有時(shí)可能也需要在輸入框的onFocusChange中滾動(dòng)。
如果到了列表底部,計(jì)算出的距離可能和實(shí)際滾動(dòng)的距離也不一樣,這種情況也可以用setSelectionFromTop的方法讓所點(diǎn)擊的Item在屏幕最上方,當(dāng)然也可以再計(jì)算偏移,總之異常繁瑣。
如果是像登錄這種情況,UI簡(jiǎn)單的,要加個(gè)ScrollView,也比較好處理,軟鍵盤彈出時(shí)直接滾動(dòng)到底部,隱藏時(shí)滾動(dòng)到頂部。
總之,要實(shí)現(xiàn)自動(dòng)滾動(dòng),首先就要有一個(gè)控件隨著軟鍵盤的彈出消失而移動(dòng)位置,軟鍵盤彈出后出現(xiàn)在軟鍵盤的上方,哪怕它看不見只是作為一個(gè)anchor。
其次,需要計(jì)算滾動(dòng)距離,看情況有所不同,也是最麻煩的,可能需要知道輸入框的狀態(tài)是隱藏,顯示在屏幕底部而軟鍵盤沒出來,還是軟鍵盤出來了。不過在輸入框初始隱藏在布局最下方的情況下,這三種情況輸入框的坐標(biāo)也只有3個(gè)值,也可以根據(jù)這個(gè)值判斷輸入框的狀態(tài),當(dāng)然不排除有些輸入法可以調(diào)整軟鍵盤高度而用戶又很配合地在輸入時(shí)調(diào)整。
反正如果有這需求就惡心死吧。在項(xiàng)目三個(gè)地方實(shí)現(xiàn),大致方法都是一樣的,細(xì)節(jié)都有差異。

浙公網(wǎng)安備 33010602011771號(hào)