ScrollView嵌套ViewPager+RecyclerView 动态获取ViewPager的高度问题

本文分享了一种实现滑动悬浮效果的方法,适用于电商场景。通过使用CoordinatorLayout、AppBarLayout、ViewPager和RecyclerView,解决了滑动卡顿和高度计算问题,无需自定义behavior。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最新因为有一个项目需求是滑动悬浮效果,很多电商都可能用到的场景,话不多说,直接上图:

其实这个很容易做:最近老加班,脑子有点转不过来了。

布局比较复杂,刚开始想的是用自定义ScrollView嵌套TabLayout+ ViewPager + RecyclerView做,ViewPager是用自包裹做的,但是做出来后发现滑多了以后再切换ViewPager发现很卡顿,我认为是RecyclerView里面的元素没有被复用导致的。因为ViewPager是自包裹的嘛,而且还发现一个问题就是切换后面的tab的时候ViewPager的高度算的不对,下面是计算ViewPager的高度的方法:

 @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int height = 0;
        for (int i = 0; i < 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);
    }

但是发现ChildCount数量最多到8,这个跟你的fragment数量有一定关系,但不是fragment的数量,后来一查,是说ChildCount指的是ViewPager的缓存数量,并不等于ViewPager的itemCount,网上的demo的tab刚好都小于8,超过8后切换到后面的tab项的时候ViewPager的高度都算的不对。

于是想着使用外部拦截法,把ViewPager的高度固定,通过滑动到临界值的方式去交换滑动事件。想法是好的,但是把滑动事件交给了外部的ScrollView去控制,这里又挖坑了,遇到了一个棘手的问题,慢滑到临界值的时候,事件交换不过来,导致有时候会滑不动, 必须快速的滑过去,很影响用户体验啊0.0...

于是又弃坑了,换了个思路:内部拦截的方式,于是又在埋坑的路上继续前行了... 后来发现RecyclerView的item显示有问题,外面根本滑不动,滑动事件没有传递到ScrollView,应该是被ViewPager消费了,后来尝试修改ViewPager的拦截,发现没什么用,有哪位大神做出来的可以指点一二。

后来想了想觉得不用ScrollView了,为什么一定要用ScrollView呢,脑子糊涂了~,用CoordinateLayout + AppBarLayout + ViewPager + RecyclerView其实就可以了。而且这个联动还是挺简单的,不需要自定义behavior。

下面附上布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/COLOR_WHITE"
    android:orientation="vertical">

    <android.support.design.widget.CoordinatorLayout
        android:id="@+id/coordinator"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.design.widget.AppBarLayout
            android:id="@+id/appbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/COLOR_WHITE">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="-76dp"
                android:orientation="vertical"
                app:layout_scrollFlags="scroll|enterAlwaysCollapsed">

                <RelativeLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="vertical">

                    <com.youth.banner.Banner
                        android:id="@+id/banner"
                        android:layout_width="match_parent"
                        android:layout_height="@dimen/dip240"
                        app:image_scale_type="fit_xy">

                    </com.youth.banner.Banner>

                    <ImageView
                        android:layout_width="match_parent"
                        android:layout_height="@dimen/dip36"
                        android:layout_alignParentBottom="true"
                        android:contentDescription="@null"
                        android:scaleType="fitXY"
                        android:src="@drawable/audition_banner_cover_img" />

                </RelativeLayout>

                <RelativeLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="-30dp">

                    <LinearLayout
                        android:id="@+id/ll_super_withdraw_card"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_below="@+id/iv_super_withdraw_card"
                        android:layout_marginLeft="@dimen/dip16"
                        android:layout_marginRight="@dimen/dip16"
                        android:layout_marginTop="-17dp"
                        android:background="@drawable/bg_gradient_r27"
                        android:gravity="center"
                        android:paddingBottom="@dimen/dip12"
                        android:paddingTop="@dimen/dip12">

                        <LinearLayout
                            android:id="@+id/ll_dwc"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:layout_gravity="center_vertical">

                            <TextView
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:text="本日剩余额度:"
                                android:textColor="@color/COLOR_WHITE"
                                android:textSize="@dimen/font12" />

                            <TextView
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:text="@string/rmb"
                                android:textColor="@color/COLOR_YELLOW"
                                android:textSize="@dimen/font12" />

                            <TextView
                                android:id="@+id/tv_dwc_amount"
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:text="0"
                                android:textColor="@color/COLOR_YELLOW"
                                android:textSize="@dimen/font18" />

                            <TextView
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:layout_marginLeft="@dimen/dip15"
                                android:text="无门槛提现"
                                android:textColor="@color/COLOR_WHITE"
                                android:textSize="@dimen/font12" />

                        </LinearLayout>

                        <ImageView
                            android:id="@+id/iv_help"
                            android:layout_width="@dimen/dip22"
                            android:layout_height="@dimen/dip22"
                            android:layout_marginLeft="@dimen/dip8"
                            android:contentDescription="@null"
                            android:src="@drawable/audition_diamond_help_img" />

                    </LinearLayout>

                    <ImageView
                        android:id="@+id/iv_super_withdraw_card"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_centerHorizontal="true"
                        android:contentDescription="@null"
                        android:src="@drawable/accumulate_super_withdraw_card_bg_img" />

                </RelativeLayout>
                <!--拼多多、淘宝专栏-->
                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/dip16">

                    <RelativeLayout
                        android:id="@+id/rl_tb"
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:layout_marginEnd="@dimen/dip4"
                        android:layout_marginRight="@dimen/dip4"
                        android:background="@drawable/bg_soild_r8_ff8a3d">

                        <ImageView
                            android:id="@+id/iv_tb"
                            android:layout_width="@dimen/dip56"
                            android:layout_height="@dimen/dip56"
                            android:layout_marginBottom="@dimen/dip17"
                            android:layout_marginLeft="@dimen/dip10"
                            android:layout_marginStart="@dimen/dip10"
                            android:layout_marginTop="@dimen/dip17"
                            android:contentDescription="@null"
                            android:src="@drawable/audition_home_tb_img" />

                        <LinearLayout
                            android:layout_width="match_parent"
                            android:layout_height="match_parent"
                            android:layout_alignParentRight="true"
                            android:layout_centerVertical="true"
                            android:layout_toRightOf="@+id/iv_tb"
                            android:gravity="center"
                            android:orientation="vertical">

                            <TextView
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:text="淘宝专区"
                                android:textColor="@color/COLOR_WHITE"
                                android:textSize="@dimen/font15"/>

                            <TextView
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:text="海量优惠券"
                                android:textColor="@color/COLOR_WHITE"
                                android:textSize="@dimen/font12"/>

                            <TextView
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:layout_marginTop="@dimen/dip4"
                                android:background="@drawable/bg_solid_r10_000000"
                                android:paddingBottom="@dimen/dip2"
                                android:paddingLeft="@dimen/dip10"
                                android:paddingRight="@dimen/dip10"
                                android:paddingTop="@dimen/dip2"
                                android:text=" 逛淘宝 "
                                android:textColor="@color/COLOR_FF5E5E"
                                android:textSize="@dimen/font11"/>

                        </LinearLayout>
                    </RelativeLayout>

                    <RelativeLayout
                        android:id="@+id/rl_pdd"
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_marginLeft="@dimen/dip4"
                        android:layout_marginStart="@dimen/dip4"
                        android:layout_weight="1"
                        android:background="@drawable/bg_soild_r8_ff5e5e">

                        <ImageView
                            android:id="@+id/iv_pdd"
                            android:layout_width="@dimen/dip56"
                            android:layout_height="@dimen/dip56"
                            android:layout_marginBottom="@dimen/dip17"
                            android:layout_marginLeft="@dimen/dip10"
                            android:layout_marginStart="@dimen/dip10"
                            android:layout_marginTop="@dimen/dip17"
                            android:contentDescription="@null"
                            android:src="@drawable/audition_home_pdd_img" />

                        <LinearLayout
                            android:layout_width="match_parent"
                            android:layout_height="match_parent"
                            android:layout_alignParentRight="true"
                            android:layout_centerVertical="true"
                            android:layout_toRightOf="@+id/iv_pdd"
                            android:gravity="center"
                            android:orientation="vertical">

                            <TextView
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:text="拼多多专区"
                                android:textColor="@color/COLOR_WHITE"
                                android:textSize="@dimen/font15"/>

                            <TextView
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:text="9.9全网最低"
                                android:textColor="@color/COLOR_WHITE"
                                android:textSize="@dimen/font12"/>

                            <TextView
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:layout_marginTop="@dimen/dip4"
                                android:background="@drawable/bg_solid_r10_000000"
                                android:paddingBottom="@dimen/dip2"
                                android:paddingLeft="@dimen/dip10"
                                android:paddingRight="@dimen/dip10"
                                android:paddingTop="@dimen/dip2"
                                android:text="逛拼多多"
                                android:textColor="@color/COLOR_FF5E5E"
                                android:textSize="@dimen/font11"/>

                        </LinearLayout>

                    </RelativeLayout>

                </LinearLayout>

            </LinearLayout>

            <FrameLayout
                android:layout_width="match_parent"
                android:layout_height="75dp" />

            <!--tab-->
            <com.billionstech.grassbook.widget.tablayout.TabLayout
                android:id="@+id/tab_find"
                android:layout_width="match_parent"
                android:layout_height="@dimen/dip40"
                android:background="@color/COLOR_WHITE"
                android:textStyle="bold"
                app:tabBackground="@color/COLOR_WHITE"
                app:tabGravity="fill"
                app:tabIndicatorColor="@color/COLOR_FFCC00"
                app:tabIndicatorHeight="3dp"
                app:tabLineOffset="@dimen/dip12"
                app:tabMinWidth="30dp"
                app:tabMode="scrollable"
                app:tabTextAppearance="@style/TabLayoutTextStyle" />

        </android.support.design.widget.AppBarLayout>

        <android.support.v4.view.ViewPager
            android:id="@+id/viewpager"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior" />

    </android.support.design.widget.CoordinatorLayout>

    <!--顶部-->
    <LinearLayout
        android:id="@+id/ll_top"
        android:layout_width="match_parent"
        android:layout_height="@dimen/dip75"
        android:gravity="center_vertical"
        android:paddingTop="@dimen/dip15"
        android:visibility="visible">

        <!--搜索-->
        <RelativeLayout
            android:id="@+id/rl_search"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginBottom="@dimen/dip10"
            android:layout_marginLeft="@dimen/dip15"
            android:layout_marginStart="@dimen/dip15"
            android:layout_marginTop="@dimen/dip10"
            android:layout_weight="1"
            android:background="@drawable/bg_solid_stroke_r20_000000_eeeeee"
            android:paddingBottom="@dimen/dip9"
            android:paddingEnd="@dimen/dip12"
            android:paddingLeft="@dimen/dip12"
            android:paddingRight="@dimen/dip12"
            android:paddingStart="@dimen/dip12"
            android:paddingTop="@dimen/dip9">

            <ImageView
                android:id="@+id/iv_search"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:contentDescription="@null"
                android:scaleType="fitXY"
                android:src="@drawable/auditions_search_img" />

            <TextView
                android:id="@+id/et_search"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentEnd="true"
                android:layout_alignParentRight="true"
                android:layout_centerVertical="true"
                android:layout_marginLeft="@dimen/dip14"
                android:layout_marginStart="@dimen/dip14"
                android:layout_toEndOf="@+id/iv_search"
                android:layout_toRightOf="@+id/iv_search"
                android:background="@null"
                android:text="你想买啥"
                android:textColor="@color/COLOR_999999" />

        </RelativeLayout>

        <!--通知-->
        <RelativeLayout
            android:id="@+id/rl_notify"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:gravity="center"
            android:paddingEnd="@dimen/dip23"
            android:paddingLeft="@dimen/dip26"
            android:paddingRight="@dimen/dip23"
            android:paddingStart="@dimen/dip26">

            <ImageView
                android:id="@+id/iv_notify"
                android:layout_width="@dimen/dip22"
                android:layout_height="@dimen/dip22"
                android:layout_below="@+id/iv_un_read"
                android:layout_marginTop="-4dp"
                android:contentDescription="@null"
                android:src="@drawable/auditions_notify_img" />

            <ImageView
                android:id="@+id/iv_un_read"
                android:layout_width="8dp"
                android:layout_height="8dp"
                android:layout_marginLeft="-7dp"
                android:layout_toRightOf="@+id/iv_notify"
                android:src="@drawable/mine_un_read_img"
                android:visibility="invisible" />

        </RelativeLayout>

    </LinearLayout>

</RelativeLayout>

不明白CoordinateLayout用法的,可以看看这篇博文:https://blog.youkuaiyun.com/kilotwo/article/details/79197498

如果需要做更复杂的联动,可以考虑自定义behavior。

所以,前面一顿操作猛如虎,没什么卵用,不过踩了一些坑也,涨见识了,哈哈~

Ps:万一产品提一个很变态的需求,你又没什么想法的时候,可以研究一下竞品是怎么做的。打开竞品的app的当前页,

运行 adb shell dumpsys activity top,你就能看到他们写的布局了,可以做参考,给自己提供一下思路。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值