記一次失敗的RecycleView滑動(dòng)定位

前段時(shí)間開的新項(xiàng)目,現(xiàn)在終于開始動(dòng)工了静汤,我和另一個(gè)小伙伴一起做居凶,由于他還在處理另一個(gè)項(xiàng)目的尾巴侠碧,所以前期只有我一個(gè)人來做。之后我也會(huì)圍繞著這個(gè)項(xiàng)目來講一些我遇到的一些問題弄兜,和聯(lián)想發(fā)散的一些問題瓷式。

動(dòng)機(jī)

這是UI給的圖

“精品話題”板塊贸典,這部分我用recycleview做了個(gè)橫向滑動(dòng),然后讓女朋友試用腾夯。
問題就出在我女朋友試用后說體驗(yàn)不好:

  1. 滑動(dòng)速度太快了蔬充。
  2. 滑動(dòng)結(jié)束沒有item在中間位置。


    滑動(dòng)速率太快榨呆,沒有定位庸队。

滑動(dòng)速率

找了一圈可調(diào)用的方法,卻沒有看到可以直接設(shè)置速度的竿拆。
卒宾尚!
只有從相關(guān)代碼里面找找看了。RecycleView提供了兩個(gè)滑動(dòng)監(jiān)聽:OnScrollListenerOnFlingListener

public abstract static class OnScrollListener {
       //SCROLL_STATE_IDLE御板、SCROLL_STATE_DRAGGING、SCROLL_STATE_SETTLING三個(gè)狀態(tài)
        public void onScrollStateChanged(RecyclerView recyclerView, int newState){}
        //滑動(dòng)過程中一直會(huì)被調(diào)用
        public void onScrolled(RecyclerView recyclerView, int dx, int dy){}
    }

看了下被調(diào)用場(chǎng)景怠肋,并沒有什么卵用笙各。

 public abstract static class OnFlingListener {
        //Override this to handle a fling given the velocities in both x and y directions.
        public abstract boolean onFling(int velocityX, int velocityY);
    }

這個(gè)接口就比較有意思了,重寫onFling可以處理拋投(手指快速滑動(dòng)引起的屏幕慣性滑動(dòng))酪惭,velocityX,velocityY就是x軸春感,Y軸上的速率啊。順藤摸瓜嫩实,看看在哪設(shè)置的具體的數(shù)值窥岩。
在唯一調(diào)用onFling()的地方,我找到了這樣一段代碼:

 public boolean fling(int velocityX, int velocityY) {
        //其他邏輯
        if (!dispatchNestedPreFling(velocityX, velocityY)) {
            //其他邏輯
            if (canScroll) {
                //其他邏輯
                velocityX = Math.max(-mMaxFlingVelocity, Math.min(velocityX, mMaxFlingVelocity));
                velocityY = Math.max(-mMaxFlingVelocity, Math.min(velocityY, mMaxFlingVelocity));
                mViewFlinger.fling(velocityX, velocityY);
                return true;
            }
        }
        return false;
  }

可見晃洒,最后先判斷能否滑動(dòng)朦乏,然后通過Math.max()確定具體數(shù)值的。
參數(shù)里的velocityX, velocityY是函數(shù)傳過來的吃引,mMaxFlingVelocity是啥肮舸浮?庐氮?


去特喵的旭愧!是個(gè)private final屬性。初始值是8000dp,最終數(shù)值根據(jù)屏幕分辨率轉(zhuǎn)換成px后確定议泵。
木有辦法,雖然不能通過set直接設(shè)置型奥,好歹也找到了屬性名,那就通過反射來做厢汹。

  //設(shè)定RecyclerView最大滑動(dòng)速度
    private void setMaxFlingVelocity(RecyclerView recycleview, int velocity) {
        try{
            Field field = recycleview.getClass().getDeclaredField("mMaxFlingVelocity");
            field.setAccessible(true);
            field.set(recycleview, velocity);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

設(shè)置個(gè)2000,走你=缁 (設(shè)置4000使用起來比較舒服)


監(jiān)聽

定位這一步肯定是在滑動(dòng)快結(jié)束或者結(jié)束的時(shí)候經(jīng)過判斷來決定停在哪的搭综。上面寫到的兩個(gè)滑動(dòng)監(jiān)聽中,OnFlingListener 恕本人無能条获,暫時(shí)沒有想到什么辦法去使用velocityX, velocityY 兩個(gè)參數(shù)蒋歌。所以只有考慮用OnScrollListener。

onScrollStateChanged() 和 onScrolled()

onScrolled()是在視圖滾動(dòng)的過程中堂油,一直會(huì)被調(diào)用的方法∑笺玻肯定不能在這里面做判斷寓免。
onScrollStateChanged()是在滑動(dòng)狀態(tài)改變時(shí)候回調(diào)的方法。并且參數(shù)傳回來一個(gè)newState撕予。這參數(shù)代表著當(dāng)前RV的狀態(tài)。這個(gè)狀態(tài)有三個(gè)实抡。

public static final int SCROLL_STATE_IDLE = 0;
public static final int SCROLL_STATE_DRAGGING = 1;
public static final int SCROLL_STATE_SETTLING = 2;

0代表滑動(dòng)停止欢策;1代表正在被拖動(dòng);2代表當(dāng)前在慣性滑動(dòng)啄清;
當(dāng)我們拖拽view的時(shí)候有兩種情況:1→0 或者 1→2→0
所以我們就在view停止滑動(dòng)的時(shí)候再去定位就好俺孙。

定位

      recyclerView.scrollBy(int x, int y);
      recyclerView.scrollTo(int x, int y);
      recyclerView.scrollToPosition(int position);
      recyclerView.smoothScrollBy(int dx, int dy);
      recyclerView.smoothScrollToPosition(int position);

嘿嘿嘿掷贾!
看到position就開心荣茫。要算寬度dp什么的最麻煩了,實(shí)在不行再去算寬度嘛港准。
現(xiàn)在就去找怎么得到當(dāng)前的position了票罐。
scrollToPosition是直接顯示position的item。
smoothScrollToPosition是平滑到position的item该押。
當(dāng)然選擇第smooth啦。

      linearLayoutManager.findFirstVisibleItemPosition();
      linearLayoutManager.findLastVisibleItemPosition();
      linearLayoutManager.findFirstCompletelyVisibleItemPosition();
      linearLayoutManager.findLastCompletelyVisibleItemPosition();

前面兩個(gè)方法是找到屏幕顯示到的第一個(gè)/最后一個(gè)item(有可能只顯示了一半)的position烟具。
后面兩個(gè)方法是找到屏幕顯示到的第一個(gè)/最后一個(gè)完整的item(有可能它兩邊還有沒顯示完整的item)的position奠蹬。

我還是太年輕了!嚶嚶嚶冀痕!

這尼瑪什么沙雕效果

當(dāng)我們使用前兩個(gè)position時(shí)狸演,永遠(yuǎn)會(huì)遇到定位不到第一個(gè)或者最后一個(gè)的問題。
當(dāng)時(shí)候后面兩個(gè)position的時(shí)候腊尚,90%你滑出來的position因?yàn)関iew顯示不全返回-1满哪,眼睜睜看著她崩潰。而且這個(gè)smoothscroll效果也太不好了哨鸭!
上面這四種定位的方式不適合當(dāng)前情況,只適合屏幕能顯示整數(shù)個(gè)的情況勘高,也就是recycleView在最邊緣的時(shí)候,屏幕不會(huì)有顯示不全的view。從一開始的方向就錯(cuò)誤了仅乓。
點(diǎn)題,失敗的滑動(dòng)定位夸楣!

解決辦法

后來前輩給我說了這么一段代碼:
new LinearSnapHelper().attachToRecyclerView(recycleview);

我當(dāng)時(shí)的表情

用了一次之后豫喧,發(fā)現(xiàn)這玩意兒SnapHelper,真香紧显!

最后

之前都是寫設(shè)計(jì)模式,一直也沒有寫過啥有深度的話題(我認(rèn)為的有深度應(yīng)該就是會(huì)涉及到源碼的分析涉兽,或者一個(gè)很難的課題)篙程,這一次想寫有深度文章的嘗試,正如題目所說拥诡,應(yīng)該是失敗了鸣峭。唉~ 還是太弱了。本篇文章唯一有價(jià)值的信息诅岩,大概是:我有女朋友吧宾娜。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末前塔,一起剝皮案震驚了整個(gè)濱河市承冰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌困乒,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,576評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件迁霎,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡秘豹,警方通過查閱死者的電腦和手機(jī)昌粤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來凄贩,“玉大人,你說我怎么就攤上這事疲扎±耄” “怎么了?”我有些...
    開封第一講書人閱讀 168,017評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵瓜挽,是天一觀的道長(zhǎng)征绸。 經(jīng)常有香客問我,道長(zhǎng)管怠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,626評(píng)論 1 296
  • 正文 為了忘掉前任祝拯,我火速辦了婚禮她肯,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘晴氨。我一直安慰自己,他們只是感情好亭珍,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,625評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著肄梨,像睡著了一般。 火紅的嫁衣襯著肌膚如雪峭范。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,255評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音菜秦,去河邊找鬼。 笑死球昨,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的嚣州。 我是一名探鬼主播,決...
    沈念sama閱讀 40,825評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼该肴,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼藐不!你這毒婦竟也來了匀哄?” 一聲冷哼從身側(cè)響起雏蛮,我...
    開封第一講書人閱讀 39,729評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤挑秉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后犀概,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,271評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡刁憋,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,363評(píng)論 3 340
  • 正文 我和宋清朗相戀三年木蹬,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了若皱。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片尘颓。...
    茶點(diǎn)故事閱讀 40,498評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖互广,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情惫皱,我是刑警寧澤,帶...
    沈念sama閱讀 36,183評(píng)論 5 350
  • 正文 年R本政府宣布旅敷,位于F島的核電站颤霎,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏友酱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,867評(píng)論 3 333
  • 文/蒙蒙 一锤躁、第九天 我趴在偏房一處隱蔽的房頂上張望壮吩。 院中可真熱鬧,春花似錦鸭叙、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽嗡善。三九已至学歧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間枝笨,已是汗流浹背揭蜒。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工剔桨, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人洒缀。 一個(gè)月前我還...
    沈念sama閱讀 48,906評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像萨脑,于是被迫代替她去往敵國(guó)和親饺饭。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,507評(píng)論 2 359

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