ViewPager中的ViewPager

xpe*_*int 38 android swipe swipe-gesture android-viewpager android-nested-fragment

我想创建一个ViewPager(有三个项目),其中每个视图是另一个ViewPager(有两个项目).用户然后滑动这样的项目:

ViewPager1[0] ViewPager2[0]
ViewPager1[0] ViewPager2[1]
ViewPager1[1] ViewPager2[0]
ViewPager1[1] ViewPager2[1]
ViewPager1[2] ViewPager2[0]
ViewPager1[2] ViewPager2[1]
Run Code Online (Sandbox Code Playgroud)

怎么可能呢?

str*_*aya 57

覆盖父ViewPager中的canScroll:

@Override
protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
   if(v != this && v instanceof ViewPager) {
      return true;
   }
   return super.canScroll(v, checkV, dx, x, y);
}
Run Code Online (Sandbox Code Playgroud)

  • 这有效,但我想这样做.如果子视图搜索器位于末尾,则滚动父视图. (8认同)

And*_*oob 28

试试这个:

public class CustomViewPager extends ViewPager {
    private int childId;

    public CustomViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
     @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        if (childId > 0) {          
            ViewPager pager = (ViewPager)findViewById(childId);

            if (pager != null) {           
                pager.requestDisallowInterceptTouchEvent(true);
            }

        }

        return super.onInterceptTouchEvent(event);
    }

    public void setChildId(int id) {
        this.childId = id;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 掌握onInterceptTouchEvent是所有嵌套可滚动视图的秘密. (8认同)

gtR*_*nkN 12

我搜索了很长时间在另一个ViewPager工作中创建一个ViewPager,并在这里找到了"Android Noob"的解决方案.非常感谢你!

我也想分享我的解决方案.一旦到达内部ViewPager中的最后一个(最右边)元素,我添加了将滑动管理切换到周围ViewPager的可能性.为了防止毛刺,我还保存了最后一个元素的第一个滑动方向:即如果你向左滑动,最小向右滑动不会重置滚动状态.

public class GalleryViewPager extends ViewPager {

    /** the last x position */
    private float   lastX;

    /** if the first swipe was from left to right (->), dont listen to swipes from the right */
    private boolean slidingLeft;

    /** if the first swipe was from right to left (<-), dont listen to swipes from the left */
    private boolean slidingRight;

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

    public GalleryViewPager(final Context context) {
        super(context);
    }

    @Override
    public boolean onTouchEvent(final MotionEvent ev) {
        final int action = ev.getAction();
        switch (action) {
            case MotionEvent.ACTION_DOWN:

                // Disallow parent ViewPager to intercept touch events.
                this.getParent().requestDisallowInterceptTouchEvent(true);

                // save the current x position
                this.lastX = ev.getX();

                break;

            case MotionEvent.ACTION_UP:
                // Allow parent ViewPager to intercept touch events.
                this.getParent().requestDisallowInterceptTouchEvent(false);

                // save the current x position
                this.lastX = ev.getX();

                // reset swipe actions
                this.slidingLeft = false;
                this.slidingRight = false;

                break;

            case MotionEvent.ACTION_MOVE:
                /*
                 * if this is the first item, scrolling from left to
                 * right should navigate in the surrounding ViewPager
                 */
                if (this.getCurrentItem() == 0) {
                    // swiping from left to right (->)?
                    if (this.lastX <= ev.getX() && !this.slidingRight) {
                        // make the parent touch interception active -> parent pager can swipe
                        this.getParent().requestDisallowInterceptTouchEvent(false);
                    } else {
                        /*
                         * if the first swipe was from right to left, dont listen to swipes
                         * from left to right. this fixes glitches where the user first swipes
                         * right, then left and the scrolling state gets reset
                         */
                        this.slidingRight = true;

                        // save the current x position
                        this.lastX = ev.getX();
                        this.getParent().requestDisallowInterceptTouchEvent(true);
                    }
                } else
                /*
                 * if this is the last item, scrolling from right to
                 * left should navigate in the surrounding ViewPager
                 */
                if (this.getCurrentItem() == this.getAdapter().getCount() - 1) {
                    // swiping from right to left (<-)?
                    if (this.lastX >= ev.getX() && !this.slidingLeft) {
                        // make the parent touch interception active -> parent pager can swipe
                        this.getParent().requestDisallowInterceptTouchEvent(false);
                    } else {
                        /*
                         * if the first swipe was from left to right, dont listen to swipes
                         * from right to left. this fixes glitches where the user first swipes
                         * left, then right and the scrolling state gets reset
                         */
                        this.slidingLeft = true;

                        // save the current x position
                        this.lastX = ev.getX();
                        this.getParent().requestDisallowInterceptTouchEvent(true);
                    }
                }

                break;
        }

        super.onTouchEvent(ev);
        return true;
    }

}
Run Code Online (Sandbox Code Playgroud)

希望这有助于未来的人!


小智 11

如果子视图搜索器位于末尾,则滚动父视图

protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
    if(v != this && v instanceof ViewPager) {
        int currentItem = ((ViewPager) v).getCurrentItem();
        int countItem = ((ViewPager) v).getAdapter().getCount();
        if((currentItem==(countItem-1) && dx<0) || (currentItem==0 && dx>0)){
            return false;
        }
        return true;
    }
    return super.canScroll(v, checkV, dx, x, y);
}
Run Code Online (Sandbox Code Playgroud)


Wes*_*y92 9

对于 a ViewPager2,当前的解决方案是使用NestedScrollableHost: https: //github.com/android/views-widgets-samples/blob/master/ViewPager2/app/src/main/java/androidx/viewpager2/integration/testapp/NestedScrollableHost .kt

您可以在此处查看错误报告和进度: https: //issuetracker.google.com/issues/123006042


Eri*_*iaz 5

首先以这种方式创建一个自定义ViewPager类:

public class CustomViewPager extends ViewPager {

    public CustomViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    @Override
    protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
        if(v instanceof ViewPager) {
            return true;
        }
        return super.canScroll(v, checkV, dx, x, y);
    }
}
Run Code Online (Sandbox Code Playgroud)

canScroll方法的返回值(布尔值)将告诉您ViewPager更改页面的水平手势是否需要在片段的右边界或左边界(true),或者它是否适用于完整片段屏幕(false)。例如,如果您希望仅第一个片段使用右边框移至下一个片段,因为第一个片段具有另一个水平滚动事件,这将是重写方法canScroll的代码:

@Override
protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
    if(v instanceof ViewPager) {
        int currentItem = ((ViewPager) v).getCurrentItem();
        if((currentItem==0)){
            return true;
        }
        return false;
    }
    return super.canScroll(v, checkV, dx, x, y);
}
Run Code Online (Sandbox Code Playgroud)

最后一步是在主类中使用CustomViewPager类:

ViewPager myPager= (CustomViewPager)myContext.findViewById(R.id.myCustomViewPager);
Run Code Online (Sandbox Code Playgroud)

和xml:

<my.cool.package.name.CustomViewPager
        android:id="@+id/myCustomViewPager"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />
Run Code Online (Sandbox Code Playgroud)