ScrollView+TabLayout+ViewPager嵌套解決方案

首先看一下效果圖肴焊,圖片來自于簡書APP


簡書App示例

做移動開發(fā)的小伙伴們肯定會遇到這樣的設計要求吧就乓,做為一個初級程序員要完成這個效果還是會遇到不少坑烹吵,所以在這里記錄一下惧眠,有什么問題也可以在下面的評論區(qū)留言打颤。

注意事項

  • 本身項目中TabLayout只有三個模塊暴拄,所以只有三個Fragment,這個是跟上面的圖不太一樣的地方,這里提供的圖片只是一個大概的模型瘸洛。
  • 簡書App的標題欄是有滑到頂部固定的效果揍移,這個因為不是本篇文章的重點,所以不再詳細說明反肋。

解決思路

  1. 當我們用ScrollView嵌套ViewPager的時候那伐,如果每個ViewPager的頁面高度不同會導致下面有一部分的空白,所以要在ViewPager切換頁面的時候重置它的高度石蔗,因此要重寫ViewPager罕邀。
  2. ViewPager的子布局是四個Fragment,如果Fragment里面是ListView的話,就要求我們獲取到這個ListView的高度养距。

實現(xiàn)步驟

第一步 重寫ListView
public class MyListView extends ListView {

    public MyListView(Context context) {
        super(context);
    }

    public MyListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyListView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int expandSpec = View.MeasureSpec.makeMeasureSpec(
                Integer.MAX_VALUE >> 2, View.MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, expandSpec);
    }
}

注意這里LsitView分頁加載的功能是通過給ScrollView設置滾動到底部的監(jiān)聽器實現(xiàn)的诉探,下面的內(nèi)容會提到。

第二步 重寫ViewPager
public class PersonalViewPager extends ViewPager {

    private int position;
    
    private HashMap<Integer, Integer> maps = new LinkedHashMap<Integer, Integer>();

    public PersonalViewPager(Context context) {
        super(context);
    }

    public PersonalViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int height = 0;
        for (int i = 0; i < this.getChildCount(); i++) {
            View child = getChildAt(i);
            child.measure(widthMeasureSpec,
                    MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
            int h = child.getMeasuredHeight();
            maps.put(i, h);
        }
        if (getChildCount() > 0) {
            height = getChildAt(position).getMeasuredHeight();
        }
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(height,
                MeasureSpec.EXACTLY);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    /**
     * 在切換tab的時候棍厌,重置viewPager的高度
     */
    public void resetHeight(int position) {
        this.position = position;
        if (maps.size() > position) {
            LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) getLayoutParams();
            if (layoutParams == null) {
                layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, maps.get(position));
            } else {
                layoutParams.height = maps.get(position);
            }
            setLayoutParams(layoutParams);
        }
    }
}
第三步 重寫ScrollView
public class PersonalScrollView extends ScrollView {

    public PersonalScrollView(Context context) {
        super(context);
    }

    public PersonalScrollView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public PersonalScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);

        View view = (View) getChildAt(getChildCount() - 1);

        int d = view.getBottom();

        d -= (getHeight() + getScrollY());

        if ((d == 0) && (onScrollBottomListener != null)) {
            onScrollBottomListener.onScrollBottom();
        }
    }

    public OnScrollBottomListener onScrollBottomListener = null;

    public interface OnScrollBottomListener {
        void onScrollBottom();
    }

    public void setOnScrollBottomListener(OnScrollBottomListener onScrollBottomListener) {
        this.onScrollBottomListener = onScrollBottomListener;
    }
}
第四步 Activity實現(xiàn)
  • 實現(xiàn)TabLayout和ViewPager的聯(lián)動
    這個可以百度一下相關的文章肾胯,后面也可能專門寫一篇文章來詳細介紹
  • ViewPager的滾動監(jiān)聽
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                if (position == 0) {
                    mViewPager.resetHeight(0);
                } else if (position == 1) {
                    mViewPager.resetHeight(1);
                } else if (position == 2) {
                    mViewPager.resetHeight(2);
                }
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });
  • ScrollView的滾動監(jiān)聽
mScrollView.setOnScrollBottomListener(new PersonalScrollView.OnScrollBottomListener() {
            @Override
            public void onScrollBottom() {
                if (mTabLayout.getSelectedTabPosition() == 0) {
                    ((PersonalCourseFragment) fragmentList.get(0)).loadData();
                } else if (mTabLayout.getSelectedTabPosition() == 1) {
                    ((PersonalNewsFragment) fragmentList.get(1)).loadData();
                } else if (mTabLayout.getSelectedTabPosition() == 2) {
                    ((PersonalIssueAnswerFragment) fragmentList.get(2)).loadData();
                }
            }
        });

這里的loadData()方法是在Fragment里面自定義加載數(shù)據(jù)的方法。

也有簡書的朋友推薦CoordinatorLayout+TabLayout+ViewPager實現(xiàn)耘纱,也是一種可行的辦法敬肚,不過這個要再研究一下,有結果的話就補充在文章的末尾束析。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末艳馒,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子员寇,更是在濱河造成了極大的恐慌弄慰,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蝶锋,死亡現(xiàn)場離奇詭異陆爽,居然都是意外死亡,警方通過查閱死者的電腦和手機扳缕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進店門墓陈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來恶守,“玉大人,你說我怎么就攤上這事贡必。” “怎么了庸毫?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵仔拟,是天一觀的道長。 經(jīng)常有香客問我飒赃,道長利花,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任载佳,我火速辦了婚禮炒事,結果婚禮上,老公的妹妹穿的比我還像新娘蔫慧。我一直安慰自己挠乳,他們只是感情好,可當我...
    茶點故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布姑躲。 她就那樣靜靜地躺著睡扬,像睡著了一般。 火紅的嫁衣襯著肌膚如雪黍析。 梳的紋絲不亂的頭發(fā)上卖怜,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天,我揣著相機與錄音阐枣,去河邊找鬼马靠。 笑死,一個胖子當著我的面吹牛蔼两,可吹牛的內(nèi)容都是我干的甩鳄。 我是一名探鬼主播,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼宪哩,長吁一口氣:“原來是場噩夢啊……” “哼娩贷!你這毒婦竟也來了?” 一聲冷哼從身側響起锁孟,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤彬祖,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后品抽,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體储笑,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年圆恤,在試婚紗的時候發(fā)現(xiàn)自己被綠了突倍。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖羽历,靈堂內(nèi)的尸體忽然破棺而出焊虏,到底是詐尸還是另有隱情,我是刑警寧澤秕磷,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布诵闭,位于F島的核電站,受9級特大地震影響澎嚣,放射性物質發(fā)生泄漏疏尿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一易桃、第九天 我趴在偏房一處隱蔽的房頂上張望褥琐。 院中可真熱鬧,春花似錦晤郑、人聲如沸敌呈。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽驱富。三九已至,卻和暖如春匹舞,著一層夾襖步出監(jiān)牢的瞬間褐鸥,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工赐稽, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留叫榕,地道東北人。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓姊舵,卻偏偏與公主長得像晰绎,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子括丁,可洞房花燭夜當晚...
    茶點故事閱讀 44,871評論 2 354

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,117評論 25 707
  • 日遠天高望青門荞下,九關紫氣煞沖云。 朝乘紅旗充勤政史飞,暗貯金屋當和珅尖昏。 饕餮嘴,貔貅身构资,賞罰只按窮達...
    梨渦小篆本尊閱讀 561評論 1 7
  • 題記 南朝宋·劉敬叔《異苑》卷三: “罽賓國王買得一鸞,欲其鳴,不可致,飾金繁,饗珍饈,對之愈戚,三年不鳴抽诉。夫人曰...
    偶遇小娘子閱讀 721評論 0 1
  • 原地跑步35分鐘,微微出汗吐绵。
    向日葵0601閱讀 185評論 0 0
  • 文 | 李馨 01 雅米是我朋友圈里的一位朋友迹淌,現(xiàn)實中我們并不相識河绽,通過一次線上活動互加好友,而后再無聯(lián)系唉窃,于我耙饰,...
    李馨閱讀 1,398評論 35 16