Scrollview+Viewpager+fragment滑动冲突、高度问题修复

遇到这个组合 ,查看了很多相关的资料 ,每人遇到的情况不一,有很多实现不了 ,要么不满足需求:这里记录一下 用到了 解决了我的问题:Android开发之复杂布局嵌套(ScrollView+TabLayout+ViewPager+RecyclerView)导致冲突的解决办法_黄庆庆的世界-CSDN博客

整理一下我的用到的:方便查看

大致布局:

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.hq.testscrollview.InterceptScrollView
        android:id="@+id/interceptScrollView"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:id="@+id/container_normal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:descendantFocusability="beforeDescendants"
            android:focusable="true"
            android:focusableInTouchMode="true"
            android:orientation="vertical">

            <RelativeLayout
                android:id="@+id/top_info"
                android:layout_width="match_parent"
                android:layout_height="60dp">

                <TextView
                    android:id="@+id/tv"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerInParent="true"
                    android:text="顶部内容模块添加"
                    android:textSize="18sp" />
            </RelativeLayout>

            <android.support.design.widget.TabLayout
                android:id="@+id/tabLayout"
                android:layout_width="match_parent"
                android:layout_height="50dp"
                android:background="@android:color/white"
                app:tabMode="fixed"
                app:tabSelectedTextColor="@android:color/black" />
            <!-- 占位布局,默认是为gone状态,当TabLayout移除时,才更改其状态为可见,达到“占位”效果-->
            <View
                android:id="@+id/view_place"
                android:layout_width="match_parent"
                android:layout_height="50dp"
                android:visibility="gone" />

            <com.hq.testscrollview.AutofitViewPager
                android:id="@+id/viewPager"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />

        </LinearLayout>
    </com.hq.testscrollview.InterceptScrollView>

    <!-- 悬浮在屏幕上方的顶部空布局-->
    <LinearLayout
        android:id="@+id/container_top"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:orientation="vertical">

    </LinearLayout>
</RelativeLayout>
两个自定义控件代码:

public class InterceptScrollView extends ScrollView {

    private int lastInterceptX;
    private int lastInterceptY;

    private ScrollChangedListener onScrollChangedListener;
    
    public InterceptScrollView(Context context) {
        super(context);
    }

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

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

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        boolean intercept = false;
        int x = (int) ev.getX();
        int y = (int) ev.getY();
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                intercept = false;
                break;
            case MotionEvent.ACTION_MOVE:
                int deltaX = x - lastInterceptX;
                int deltaY = y - lastInterceptY;
                //如果是垂直滑动,则拦截
                if (Math.abs(deltaX) - Math.abs(deltaY) < 0) {
                    intercept = true;
                } else {
                    intercept = false;
                }

                break;
            case MotionEvent.ACTION_UP:
                intercept = false;
                break;
        }
        lastInterceptX = x;
        lastInterceptY = y;
        super.onInterceptTouchEvent(ev);//这一句一定不能漏掉,否则无法拦截事件
        return intercept;
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        if(onScrollChangedListener!=null){
            onScrollChangedListener.onScrollChanged(l,t,oldl,oldt);
        }
    }

    public void setScrollChangedListener(ScrollChangedListener listener){
        onScrollChangedListener = listener;
    }

    public interface ScrollChangedListener{
        void onScrollChanged(int scrollX, int scrollY, int oldScrollX, int oldScrollY);
    }
}

使用fillViewport属性行不通,那我们就重写ViewPageronmeasure方法来解决高度显示为0的问题。重写ViewPager,代码如下:

public class AutofitViewPager extends ViewPager {

    public AutofitViewPager(@NonNull Context context) {
        this(context,null);
    }

    public AutofitViewPager(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        addOnPageChangeListener(new OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            }

            @Override
            public void onPageSelected(int position) {
                requestLayout();//保证每次选中当前页时,计算高度,达到高度自适应效果
            }

            @Override
            public void onPageScrollStateChanged(int state) {
            }
        });
    }

    //重写onMeasure,解决高度显示为0,同时高度动态显示为当前子项的高度
    @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();
            if(i==getCurrentItem()){
                height=h;
            }
        }
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(height,
                MeasureSpec.EXACTLY);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

}
这是普通的解决方式。

下面来看看介绍CoordinatorLayout,所以就不花很大的篇幅来讲解,对这个布局感兴趣的可以深入了解下,当然在使用这个布局之前,记得加上support:design的依赖库,下面直接放上布局代码:

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/coordinatorLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:elevation="0dp"
        android:background="@android:color/white">

        <RelativeLayout
            android:id="@+id/title_layout"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            app:layout_scrollFlags="scroll">

            <TextView
                android:id="@+id/tv"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:text="顶部内容模块"
                android:textSize="18sp" />
        </RelativeLayout>

        <android.support.design.widget.TabLayout
            android:id="@+id/tabLayout"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:background="@android:color/white"
            app:tabMode="fixed"
            app:tabSelectedTextColor="@android:color/black" />

    </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>
这个布局可以解决很多发杂的viewpager+fragment处理各种高度、滑动冲突等问题。

猜你喜欢

转载自blog.csdn.net/qq_25462179/article/details/121116720
今日推荐