无法将 ViewPager 放入 ScrollVIew/NestedScrollView

Unable to Put ViewPager inside a ScrollVIew/NestedScrollView

我有一个 ViewPager,它位于父线性布局中,在 ViewPager 下方有一些按钮。 ViewPager 一直运行良好,直到最近我将父级从 LinearLayout 更改为 ScrollView。现在 ViewPager 消失了。请不要将其标记为垃圾邮件或重复。

此外,Playstore 上目前有大量应用程序正在使用它。查看此应用 - link

我尝试了什么:

  1. setFillViewport (true) - 这对我不起作用。
  2. 将 layout_height 设置为 0dp
  3. 使用 CustomScrollView

所有这些都对我没有帮助。我是 运行 Android M.

上的应用

这是我的 layout.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView
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:fillViewport="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black"
tools:context=".activities.HomeActivity">

<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:onClick="pagerClick"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="top"
android:layout_weight="1"
android:overScrollMode="never"/>

<RelativeLayout
android:layout_weight="0.8"
android:layout_marginTop="30dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
.....two buttons
</RelativeLayout>

</LinearLayout>

</android.support.v4.widget.NestedScrollView>

问题:

我怎样才能做到这一点?另外,有官方的方法吗?

最好使用 recyclerView 并在适配器中添加 Viewpager 作为其 child。您需要拦截 recyclerview 的触摸以将滚动交给 ViewPager。

public class TouchInterceptRecyclerView extends RecyclerView {

    private boolean interceptTouch = true;
    private static final int MIN_DISTANCE = 200;
    private float downX = 0, downY = 0, moveX = 0, moveY = 0, upX = 0, upY;

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

    public TouchInterceptRecyclerView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }


    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if (getRvTop() == 0) {
            onTouchEvent(ev);
        }
        return interceptTouch;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downX = event.getX();
                downY = event.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                moveX = event.getX();
                moveY = event.getY();
                break;
            case MotionEvent.ACTION_UP:
                upX = event.getX();
                upY = event.getY();
                break;
        }
        float deltaX = upX - downX;

        if (getViewTop() == 0 && moveY > downY && Math.abs(moveY - downY) > MIN_DISTANCE) {  // moving down
            interceptTouch = true;
        }else if (Math.abs(deltaX) > MIN_DISTANCE) {
            if (upX > downX) {    // Left to Right swipe action
                interceptTouch = false;
            }else {    // Right to left swipe action
                interceptTouch = false;
            }
        } else {  // screen tap
            interceptTouch = false;
        }
        return super.onTouchEvent(event);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        return super.dispatchTouchEvent(ev);
    }

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

    @Override
    public void onScrolled(int dx, int dy) {
        if (getViewTop() <= 0) {
            interceptTouch = false;            // dispatch the touch to child when reached top
        } else {
            interceptTouch = true;           // do not dispatch the touch event
        }
        super.onScrolled(dx, dy);
    }

    public int getViewTop() {
        int top = 0;
        View v = this.getChildAt(1);
        if (v == null) {
            v = this.getChildAt(0);
        }
        if (v != null && v instanceof LinearLayout) {
            top = v.getTop();
        }
        return top;
    }

    public int getRvTop() {
        int top = -1;
        View v = this.getChildAt(1);
        if (v == null) {
            v = this.getChildAt(0);
        }
        if (v != null && v instanceof LinearLayout) {

            ViewPager vp = (ViewPager) v.findViewById(R.id.single_pager);
            if (vp != null) {
                int currentPos = vp.getCurrentItem();
                RecyclerView rv = (RecyclerView) vp.findViewWithTag("recyclerview" + currentPos);
                if (rv != null) {
                    View v1 = rv.getChildAt(0);
                    if (v1 != null && v1 instanceof CardView) {
                        top = v1.getTop() - ResourceUtils.getDimensionPixelOffset(R.dimen.padding_20);   // deducting 20 as we have give top margin as 20 to the top layout
                    }
                }
            }
        }
        return top;
    }
}

在 RecyclerView 的适配器中,您可以像这样添加 ViewPager :

@Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        RecyclerView.ViewHolder viewHolder = null;
        View view;
        switch (viewType) {
            case TYPE_VIEW_PAGER:
                view = LayoutInflater.from(context).inflate(R.layout.pager, parent, false);
                viewHolder = new ViewPagerAdapter(context, view);
                break;
        }
        return viewHolder;
    }

我通过固定 ViewPager 的高度解决了这个问题,例如:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView
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:fillViewport="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black"
tools:context=".activities.HomeActivity">

<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:onClick="pagerClick"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_gravity="top"/>

...

</LinearLayout>

</android.support.v4.widget.NestedScrollView>