Android雙列表聯(lián)動(dòng)和固定頭部ScrollView效果實(shí)現(xiàn)

引文:之前在寫一個(gè)stickScrollView的時(shí)候?qū)Σ簧偃擞幸欢ǖ膯⑹咀饔茫@次針對(duì)stickScrollView再實(shí)現(xiàn)雙列表的聯(lián)動(dòng)效果洛二,希望對(duì)后續(xù)的開(kāi)發(fā)者要實(shí)現(xiàn)同樣的效果能有一定的啟示,可能在實(shí)現(xiàn)的思路上比較簡(jiǎn)單婆翔,但是還是碰到了性能的問(wèn)題础米,也會(huì)針對(duì)我優(yōu)化的過(guò)程中提出自己優(yōu)化的思路矫渔,讓后面有遇到類似的問(wèn)題的伙伴少走點(diǎn)彎路。

一.首先貼下效果圖吧:

image

如圖的效果圖是左邊列表點(diǎn)擊之后让禀,會(huì)滾動(dòng)到左列表對(duì)應(yīng)的右邊字類目列表挑社;當(dāng)滑動(dòng)右邊的列表的時(shí)候,又可以反過(guò)來(lái)作用于左邊列表巡揍,實(shí)現(xiàn)勾選上對(duì)應(yīng)的左邊列表滔灶。

1.實(shí)現(xiàn)思路,當(dāng)左邊列表點(diǎn)擊的時(shí)候:

 mLlRight.scrollToPositionWithOffset(scrollIndex, 0);

網(wǎng)上一直有思路是根據(jù)滑動(dòng)的postion是否在第一個(gè)可見(jiàn)的item之前吼肥,可見(jiàn)item之后和最后可見(jiàn)item之前录平,最后的可見(jiàn)item之后三種情況來(lái)處理:

   if (scrollIndex <= firstItem) {
       //當(dāng)要置頂?shù)捻?xiàng)在當(dāng)前顯示的第一個(gè)項(xiàng)的前面時(shí)
       mChildRecyclerviewRight.smoothScrollToPosition(scrollIndex);
       } else if (scrollIndex <= lastItem) {
           //當(dāng)要置頂?shù)捻?xiàng)已經(jīng)在屏幕上顯示時(shí),計(jì)算它離屏幕原點(diǎn)的距離
           int top = mChildRecyclerviewRight.getChildAt(scrollIndex - firstItem).getTop();
           mChildRecyclerviewRight.smoothScrollBy(0, top);
       } else {
       //當(dāng)要置頂?shù)捻?xiàng)在當(dāng)前顯示的最后一項(xiàng)的后面時(shí)
       mChildRecyclerviewRight.smoothScrollToPosition(scrollIndex);
       //記錄當(dāng)前需要在RecyclerView滾動(dòng)監(jiān)聽(tīng)里面繼續(xù)第二次滾動(dòng)
       move = true;
   }

但是我發(fā)現(xiàn)這樣的處理的話缀皱,能實(shí)現(xiàn)右邊的定位的效果斗这,但是會(huì)觸發(fā)右邊列表的二次滾動(dòng),這個(gè)會(huì)導(dǎo)致右邊列表的二次滾動(dòng)觸發(fā)左邊列表的重新定位啤斗,雖然做了各種判斷表箭,但是在我的暴力測(cè)試下,還是會(huì)有這樣的情況出現(xiàn)钮莲,很頭疼免钻,經(jīng)測(cè)試LiearLayoutManager的方法比較靠譜,就是有個(gè)問(wèn)題數(shù)據(jù)量多的時(shí)候崔拥,左邊列表點(diǎn)擊的時(shí)候會(huì)很卡极舔,當(dāng)然了,這個(gè)在后邊有我的優(yōu)化之路链瓦。

2.當(dāng)右邊的列表滑動(dòng)的時(shí)候拆魏,給recyclerview設(shè)置滾動(dòng)監(jiān)聽(tīng)就可以了:

    @Override
    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);
        //在這里進(jìn)行第二次滾動(dòng)(最后的距離)
        if (recyclerView.getScrollState() == RecyclerView.SCROLL_STATE_IDLE) {
            if (!mIsLeftTouch) {
                leftLocation();
               }
           }
       }

雖然這樣聯(lián)動(dòng)的效果實(shí)現(xiàn)了盯桦,但是個(gè)人發(fā)現(xiàn)整體界面的流暢性有很大問(wèn)題,綜合原因是因?yàn)橐淮涡约虞d了右邊的列表渤刃,右邊的列表數(shù)據(jù)量太過(guò)龐大了拥峦,而且有三個(gè)tab加載這樣就導(dǎo)致整個(gè)界面異常卡頓卖子,下面就這個(gè)提下我的優(yōu)化方案:

二.其實(shí)在整體的實(shí)現(xiàn)當(dāng)中略号,真實(shí)情況是每個(gè)fragment的右側(cè)列表數(shù)據(jù)都會(huì)很龐大,我們以前在列表上面可以用分頁(yè)洋闽,但是現(xiàn)在必須一次性加載這么多數(shù)據(jù)璃哟,會(huì)出現(xiàn)以下的幾個(gè)問(wèn)題,針對(duì)這幾個(gè)問(wèn)題喊递,我自己有進(jìn)行優(yōu)化,因此將優(yōu)化的方案也貼出來(lái)阳似,旨在希望大家不僅能開(kāi)發(fā)功能性的app骚勘,還要開(kāi)發(fā)出性能高的app,我現(xiàn)在是用了700條數(shù)據(jù)進(jìn)行測(cè)試撮奏,每個(gè)item有圖片和文案俏讹。

1.沒(méi)優(yōu)化之前的使用是這個(gè)體驗(yàn),啟動(dòng)是4s:

image

2.問(wèn)題1:當(dāng)進(jìn)界面的時(shí)候畜吊,由于右側(cè)列表數(shù)據(jù)過(guò)于龐大泽疆,一次性加載fragment顯示很慢,將近4s玲献?

1.因?yàn)檫@個(gè)界面的tab上面有角標(biāo)殉疼,這個(gè)時(shí)候通常的做法,是在網(wǎng)絡(luò)數(shù)據(jù)請(qǐng)求完成之后捌年,再去進(jìn)行ViewPager和TabLayout的初始化瓢娜,這個(gè)時(shí)候很明顯會(huì)有一片空白的時(shí)候?

解決辦法:我們?cè)贏ctivity加載的時(shí)候礼预,我們就應(yīng)該viewPager眠砾,fragment初始化好,在網(wǎng)絡(luò)請(qǐng)求拿到數(shù)據(jù)之后托酸,我們只需要拿到初始化的fragment和tabLayout進(jìn)行刷新數(shù)據(jù)就可以了褒颈。如下面就是在網(wǎng)絡(luò)請(qǐng)求完成之后,回調(diào)fragment提供接口中的notifyDataChange方法励堡,通知fragment進(jìn)行刷新谷丸,同時(shí)我們對(duì)tablayout取到每一個(gè)需要賦值的view,進(jìn)行設(shè)值应结。

private void initVP() {
        for (FragmentWithTitleBean fragmentWithTitleBean : mFragments) {
            ((CheckListFragment) (fragmentWithTitleBean.getFragment())).notifyDataChange();
        }
        //通知tablayout進(jìn)行改變
        for (int i = 0, size = mOrderManagerTabs.getTabCount(); i < size; i++) {
            TabLayout.Tab tab = mOrderManagerTabs.getTabAt(i);
            if (tab != null && tab.getCustomView() != null) {
                TextView tvNum = tab.getCustomView().findViewById(R.id.tv_num);
                int intNum = 0;
                if (i == 0)
                    intNum = getCheckInfoBean().getItemAllCount();
                else if (i == 1)
                    intNum = getCheckInfoBean().getItemDoneCount();
                else if (i == 2)
                    intNum = getCheckInfoBean().getItemAllCount() - getCheckInfoBean().getItemDoneCount();
                setTabNum(tvNum, intNum);
            }
        }

    }

2.RecycerlView在加載的時(shí)候淤井,有這樣的機(jī)制,如果是height為wrap_content的話,那么你的recyclerview在加載的時(shí)候币狠,會(huì)一次性將所有數(shù)據(jù)加載進(jìn)來(lái)游两?what fuck,那這樣1000條數(shù)據(jù)同時(shí)設(shè)置漩绵,那不是卡爆了贱案?但是當(dāng)我們給recyclerview設(shè)置指定的高度的話,那么它一開(kāi)始只會(huì)加載部分的顯示的View止吐,這樣不管數(shù)據(jù)多少條宝踪,那也會(huì)好很多,那這樣有思路碍扔,那么我們接下來(lái)就是要給右側(cè)的recyclerview設(shè)定指定的高度瘩燥?

private void initRightRVHeight() {
        mChildRecyclerviewRight.post(new Runnable() {
            @Override
            public void run() {
                ViewGroup.LayoutParams layoutParams = mChildRecyclerviewRight.getLayoutParams();
                layoutParams.height = mParentActivity.getVpHeight();
                mChildRecyclerviewRight.setLayoutParams(layoutParams);
            }
        });
    }

問(wèn)題2:我們?cè)谝贿M(jìn)來(lái),三個(gè)tab下面的fragment都有這么大的數(shù)據(jù)不同,同時(shí)執(zhí)行cpu會(huì)有點(diǎn)吃力吧厉膀,沒(méi)錯(cuò)就是這樣?那這樣的話二拐,就需要用到業(yè)內(nèi)的懶加載機(jī)制服鹅,相信他們都會(huì)解決方案,這里我貼我的實(shí)現(xiàn)吧:

public abstract class LazyFragment extends Fragment {
    boolean isViewPrepared; // 標(biāo)識(shí)fragment視圖已經(jīng)初始化完畢
    boolean hasFetchData; // 標(biāo)識(shí)已經(jīng)觸發(fā)過(guò)懶加載數(shù)據(jù)


    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (isVisibleToUser) {//當(dāng)當(dāng)前為顯示頁(yè)面時(shí)
            lazyFetchDataIfPrepared();
        }
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        isViewPrepared = true;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        lazyFetchDataIfPrepared();
    }

    void lazyFetchDataIfPrepared() {
        // 用戶可見(jiàn)fragment && 沒(méi)有加載過(guò)數(shù)據(jù) && 視圖已經(jīng)準(zhǔn)備完畢
        if (getUserVisibleHint() && !hasFetchData && isViewPrepared) {
            hasFetchData = true; //已加載過(guò)數(shù)據(jù)
            lazyFetchData();
        }
    }

    abstract void lazyFetchData();
}

三.經(jīng)過(guò)上面三步之后百新,你再使用過(guò)的時(shí)候企软,有這樣的體驗(yàn),真是快太多了呀饭望,從原來(lái)的4s到現(xiàn)在的1s開(kāi)仗哨,體驗(yàn)圖如下:

image

四.代碼已經(jīng)上傳,有需要的可以去看下铅辞,github地址藻治,您的點(diǎn)贊或者star是我持續(xù)開(kāi)源的最大動(dòng)力。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末巷挥,一起剝皮案震驚了整個(gè)濱河市桩卵,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌倍宾,老刑警劉巖雏节,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異高职,居然都是意外死亡钩乍,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門怔锌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)寥粹,“玉大人变过,你說(shuō)我怎么就攤上這事±缘樱” “怎么了媚狰?”我有些...
    開(kāi)封第一講書人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)阔拳。 經(jīng)常有香客問(wèn)我崭孤,道長(zhǎng),這世上最難降的妖魔是什么糊肠? 我笑而不...
    開(kāi)封第一講書人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任辨宠,我火速辦了婚禮,結(jié)果婚禮上货裹,老公的妹妹穿的比我還像新娘嗤形。我一直安慰自己,他們只是感情好弧圆,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開(kāi)白布赋兵。 她就那樣靜靜地躺著,像睡著了一般墓阀。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上拓轻,一...
    開(kāi)封第一講書人閱讀 51,287評(píng)論 1 301
  • 那天斯撮,我揣著相機(jī)與錄音,去河邊找鬼扶叉。 笑死勿锅,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的枣氧。 我是一名探鬼主播溢十,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼达吞!你這毒婦竟也來(lái)了张弛?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤酪劫,失蹤者是張志新(化名)和其女友劉穎吞鸭,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體覆糟,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡刻剥,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了滩字。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片造虏。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡御吞,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出漓藕,到底是詐尸還是另有隱情陶珠,我是刑警寧澤,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布撵术,位于F島的核電站背率,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏嫩与。R本人自食惡果不足惜寝姿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望划滋。 院中可真熱鬧饵筑,春花似錦、人聲如沸处坪。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)同窘。三九已至玄帕,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間想邦,已是汗流浹背裤纹。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留丧没,地道東北人鹰椒。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像呕童,于是被迫代替她去往敵國(guó)和親漆际。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354

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

  • #一練每日晨問(wèn)#6月第1周 習(xí)慣 一種不假思索就能夠自然流現(xiàn)的思考和行為方式夺饲。在這種狀態(tài)中的人往往是沒(méi)有覺(jué)察的奸汇。改...
    劍峰_簡(jiǎn)書閱讀 137評(píng)論 0 0
  • 震耳的鞭炮聲慢慢消散 歡騰的鑼鼓聲漸行漸遠(yuǎn) 在外工作的你收拾行囊 春節(jié)的長(zhǎng)假一晃就休完 媽媽身前身后圍著你轉(zhuǎn) 強(qiáng)忍...
    隨緣青青閱讀 278評(píng)論 1 4
  • 我是日記星球89號(hào)星寶寶,我正在參加日記星球21日蛻變之旅往声,這是我的第33篇原創(chuàng)日記 今天是女神節(jié)茫蛹,我心情好到爆,...
    富足喜悅的江華閱讀 202評(píng)論 1 1