RecyclerView使用技巧-自動滾動

今天跟大家分享下RecyclerView怎么使它的條目自動滾動


其實做這個也是項目中有個需求需要用到,但是在網(wǎng)上找遍了也沒有找到專門講解這個知識點的文章。
所以這段時間自己研究懂了后 分享給大家。

再次更新下,找到了一個新的解決辦法,那就是 RecyclerView 的smoothScrollToPosition方法。其實這個方法之前用過,也是可以平滑滾動,但是速度太快,沒辦法自定義時間。所以就沒有說 ,但是昨天晚上經(jīng)過簡友的提醒,我又細心的找了一遍,發(fā)現(xiàn)這個方法確實是可以改變時間的 而且不用像下面那么麻煩而且解決了所有問題,簡直棒到?jīng)]朋友,那么下面是解決方法。
[RecyclerView調(diào)用smoothScrollToPosition() 控制滑動速度]


一想到條目自動滾動,讓我想起了ListView有一個方法叫做setSelection(int position) 可以設(shè)置一個位置 然后他就會自動滾動到指定的位置,但是現(xiàn)在這都什么年代了 果斷拋棄了LisView 使用RecyclerView來做 至于RecyclerView有什么好處 為什么使用它 大家自行Google吧。

那么我們回到RecyclerView中想想該怎么實現(xiàn)這個呢 找了找RecyclerView中方法 發(fā)現(xiàn)有這么一個方法scrollToPosition(int position)這個方法跟ListView的一樣也是傳入進去一位置 自動給你跳到指定的位置 ,這會兒 你可能心想 我去這不是直接就實現(xiàn)了么,但是 你用下看效果 那個條目跟瞬移是的 直接就干到最底部了! (如果你們產(chǎn)品能接受 那就當我沒說) 既然這樣不行 那就換,突然想到谷歌給我們提供了一個叫做Scroller的類 看描述!

Scroller是一個專門用于處理滾動效果的工具類,可能在大多數(shù)情況下,我們直接使用Scroller的場景并不多,但是很多大家所熟知的控件在內(nèi)部都是使用Scroller來實現(xiàn)的,如ViewPager、ListView等。

不熟悉的可以看下這篇博客[Android Scroller完全解析,關(guān)于Scroller你所需知道的一切]


其實說到底他也就還是個工具類 也就是說其實最后能讓Item滾動并不是他 這時候就要介紹下我們的另外兩個方法 scrollTo()和scrollBy()這兩個方法 這兩個才是主角 就是這個兩個方法才能讓我們的View滑動 他們的使用也很簡單 就是傳入 一個x坐標 和一個 y坐標 他就會照著你給的位置去移動 他倆不一樣的地方無非就是 scrollTo 是以當前View的初始位置開始移動 而scrollBy是根據(jù)當前位置來進行移動 而其他的特性大家也可以看上面的博客 這里就不絮叨了,

那么大家知道scrollTo()和scrollBy()的移動方式 就是移動他的內(nèi)容 而不是他自己本身,那這里正好 我們不就是想移動RecyclerView的Item么?但是用過你會發(fā)現(xiàn),我去,這家伙怎么跟之前用的那個設(shè)置位置移動的方法一個德行 ,也嗖的一下就干過去了 .不過他并不是移動到底 如果是上下滑動的話 是根據(jù)你的y值而決定的 。

那么下面就要用到Scroller這個類了
使用startScroll(int startX, int startY, int dx, int dy)開始啟動滑動 并且重寫computeScroll()方法完成值得過度 并且調(diào)用invalidate();方法請求View數(shù)重新繪制 這個一定要記得調(diào)用 不要會沒有效果

@Override public void computeScroll() { //重寫computeScroll()方法,并在其內(nèi)部完成平滑滾動的邏輯 if (mScroller.computeScrollOffset()) { scrollBy(mScroller.getCurrX(), mScroller.getCurrY()); invalidate(); } }
看下效果

GIF.gif

使用后你會發(fā)現(xiàn),哎確實是自動滾動了,而且也不是嗖的一下在就沒了。 好像這樣確實是已經(jīng)實現(xiàn)了,但是如果我想讓他滾動的在慢一點怎么辦?或者說我想他的滾動速度是可以調(diào)的,那怎么辦 ? 其實這個startScroll 還有一個重載的方法 startScroll(int startX, int startY, int dx, int dy, int duration) 可以再添加一個時間,單位是毫秒。

但是這里還有一個問題就是RecyclerView是不讓使用scrollTo方法 如果使用了是沒有效果的 而且還會打Log提醒

  RecyclerView does not support scrolling to an absolute position "Use scrollToPosition instead

第二種方法

到現(xiàn)在就已經(jīng)是實現(xiàn)RecyclerView 的自動滾動效果了,但是有沒有其他方法可以實現(xiàn)呢?當然有 ,那就是使用屬性動畫來實現(xiàn)。

屬性動畫我們大家都知道,分為兩種重要的類,分別為ValueAnimator 和 ObjectAnimator,ValueAnimator 就是來計算我們給的初始值和結(jié)束值說白了就是對值進行計算來完成數(shù)值之間的過度動畫 ,而ObjectAnimator不僅會對值進行計算還會通過反射的方式把計算出來的值賦值給做動畫對象的屬性,這里我只是說個大概,但是你有沒有發(fā)現(xiàn)其實之前的Scroller也是我們給個開始位置 和結(jié)束為止 他來給我們計算數(shù)值 然后我們在scrollBy過去 你會發(fā)現(xiàn)這個計算值的過程跟上面的ValueAnimator 是不是老像了? 好 那我們就來試試 看看行不行。

//默認從0-200 valueAnimator = ValueAnimator.ofInt(200); valueAnimator.setDuration(5000); valueAnimator.setInterpolator(new LinearInterpolator());valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override publicvoidonAnimationUpdate(ValueAnimatoranimation) { //獲取估值器給我們的返回值 int animatedValue = (int) animation.getAnimatedValue(); //調(diào)用RecyclerView的scrollBy執(zhí)行滑動 recyclerView.scrollBy(0, animatedValue); Log.e("TAG", "animatedValue:" + animatedValue); } } ); valueAnimator.start();

你會發(fā)現(xiàn)效果是一樣一樣的 ,但是實驗到這里 我想悲哀的告訴大家,這里面有個Bug,細心的可能發(fā)現(xiàn)了,當我們不論是用上面那種方法,當你的Item內(nèi)容比較少,而我們的結(jié)束值又是隨便設(shè)置的,執(zhí)行時間稍微長一點 你就會發(fā)現(xiàn),哎?我怎么不能往上面滑動了,但等一會又可以滑動了,其實是這個scrollBy還沒有執(zhí)行完, 還在往下滑動,只不過是滑動到頭了,你看不見罷了 ,那又怎么決解這個問題呢 ?其實RecyclerView有一個監(jiān)聽 addOnScrollListener 如果你沒有這個方法 說明你該更新了RecyclerView了 這個監(jiān)聽有兩個回掉。

  1. onScrollStateChanged 滑動狀態(tài) 兩個參數(shù)一個View 一個狀態(tài) 分為按下滑動 和抬起 和MotionEvent 是一樣的 。
  2. onScrolled 三個參數(shù) View 和 x,y軸滑動的量。

其實通過這兩個回掉很簡單的就能解決這個問題 就是我們只要能判斷出當前這個RecyclerView 是不是滑動到底部就行了 在onScrollStateChanged中判斷? 當滑動的狀態(tài)為抬起的時候我們判斷 不行 因為我們是使用scrollBy方法進行的滑動 妹的 這個方法根本就不會執(zhí)行 他只有你手指滑動的時候才會執(zhí)行,那咋辦 只有在onScrolled 中判斷了 這個方法才不會管你什么滑動呢 只要我動了 他就執(zhí)行 那怎判斷呢?
(直接圖片了 代碼這個格式真心沒弄好 怎么弄都不行 ?。?/p>

Paste_Image.png
Paste_Image.png
Paste_Image.png

大概的過程就是 ,我開始執(zhí)行動畫 ,然后不斷判斷是否達到最底部 ,不是得話就繼續(xù)執(zhí)行滑動。這時候呢,因為我監(jiān)聽了RecyclerVIew的滑動 一滑動我就判斷。
怎么判斷呢?得到當前顯示的最后一個item的view,通過這個View 得到他的bottom坐標值,然后在獲得RecyclerView的bottom坐標值,在拿到最后View的position,在拿到RecyclerView item的總數(shù)-1,他們四個進行比較。 都滿足了,就能說明,當前已經(jīng)滑動到最底部了,這時候給isBottom賦值為True ,接著動畫監(jiān)聽里面我們之前不是做了判斷么!滿足else條件 取消動畫,就不會在執(zhí)行了,那個Bug也就解決了。
  但是現(xiàn)在這個方法還有效率問題,滑動就執(zhí)行判斷,而且還是獲取View的各種信息,想辦法在優(yōu)化吧。還有一個就是,如果我們能知道具體移動到什么位置就好了 ,我們上面設(shè)置的是200,因為這個參數(shù)是坐標,而RecyclerView的內(nèi)容其實已經(jīng)超過屏幕坐標系了,這個問題待解決。。。。

好了 以上就是我總結(jié)的一些開發(fā)中的經(jīng)驗 如果有誰能知道解決這個辦法 和寫的不對的地方 歡迎指教 。。。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,733評論 25 709
  • 簡介: 提供一個讓有限的窗口變成一個大數(shù)據(jù)集的靈活視圖。 術(shù)語表: Adapter:RecyclerView的子類...
    酷泡泡閱讀 5,358評論 0 16
  • 簡介 RecyclerView在24.2.0版本中新增了SnapHelper這個輔助類,用于輔助RecyclerV...
    辰之貓閱讀 155,905評論 66 618
  • 這篇文章分三個部分,簡單跟大家講一下 RecyclerView 的常用方法與奇葩用法;工作原理與ListView比...
    LucasAdam閱讀 4,687評論 0 27
  • 在真正進入寺廟核心之前,我們被幻影迷惑了,真相還在遠方。如果“迷”是過程,我們似乎離“悟”還遠…… ...
    斜月三星洞_心容閱讀 486評論 0 1

友情鏈接更多精彩內(nèi)容