4

我正在开发一个使用许多页面进行滑动的应用程序,但是在某些页面上,我希望能够防止滚动到下一页,直到他们选择了某些内容。

目前我已经扩展了 ViewPager:

/* (non-Javadoc)
 * @see android.support.v4.view.ViewPager#onInterceptTouchEvent(android.view.MotionEvent)
 */
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    if (this.canGoLeft || this.canGoRight) {
        return super.onInterceptTouchEvent(event);
    }

    return false;
}

/* (non-Javadoc)
 * @see android.support.v4.view.ViewPager#onTouchEvent(android.view.MotionEvent)
 */
@Override
public boolean onTouchEvent(MotionEvent ev) {
    boolean lockScroll = false;
    switch (ev.getAction()) {
    case MotionEvent.ACTION_DOWN:
        lastX = ev.getX();
        lockScroll = false;
        return super.onTouchEvent(ev);
    case MotionEvent.ACTION_MOVE:
        if (canGoLeft && lastX < ev.getX()) {
            lockScroll = false;
        } else if (canGoRight && lastX > ev.getX()) {
            lockScroll = false;
        } else {
            lockScroll = true;
        }


        lastX = ev.getX();

        break;
    }

    lastX = ev.getX();

    if (lockScroll) {
        //make callback to prevent movement
        if (mOnPreventCallback != null) {
            mOnPreventCallback.onPreventMovement();
        }
        return false;
    } else {
        return super.onTouchEvent(ev);
    }
}

注意:我已经尝试实现防止滑动到上一页,但是您仍然可以滑动到上一页,但是您需要从最左侧滑动并向右滑动一点。它是喜怒无常的,但它并不能完全阻止滑动。

我想在这里做三件事:

  1. 防止滚动到下一个屏幕,直到他们选择了一个项目或其他东西
  2. 防止滚动到上一个屏幕(部分实现)
  3. 向用户提供反馈以显示滚动已禁用,就像 Android 以渐变方式显示顶部和底部屏幕的方式一样。
4

5 回答 5

4

当我遇到类似的问题时,我用一个手势检测器制作了自己的监听器,让它根本不响应滑动,您可以轻松地将其调整为仅在某些情况下不响应向右滑动。这应该回答您的数字 1 和 2。

这是听众:

public class OnSwipeTouchListener implements OnTouchListener {

@SuppressWarnings("deprecation")
private final GestureDetector gestureDetector = new GestureDetector(new GestureListener());

public boolean onTouch(final View v, final MotionEvent event) {
    return gestureDetector.onTouchEvent(event);
}

private final class GestureListener extends SimpleOnGestureListener {

    private static final int SWIPE_THRESHOLD = 100;
    private static final int SWIPE_VELOCITY_THRESHOLD = 100;

    @Override
    public boolean onDown(MotionEvent e) {
        return true;
    }
    @Override
    public boolean onSingleTapConfirmed(MotionEvent e) {
        onTouch(e);
        return true;
    }


    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        boolean result = false;
        try {
            float diffY = e2.getY() - e1.getY();
            float diffX = e2.getX() - e1.getX();
            if (Math.abs(diffX) > Math.abs(diffY)) {
                if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                    if (diffX > 0) {
                        onSwipeRight();
                    } else {
                        onSwipeLeft();
                    }
                }
            } else {
               // onTouch(e);
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }
        return result;
    }
}
public void onTouch(MotionEvent e) {
}
public void onSwipeRight() {
//call this only if your condition was set
}

public void onSwipeLeft() {
//nothing, this means,swipes to left will be ignored
}

public void onSwipeTop() {
}

public void onSwipeBottom() {
}
}

这是一个使用示例:

viewPager.setOnTouchListener(new OnSwipeTouchListener() {
public void onSwipeRight() {
  if(your conditionIsMet){
// move your pager view to the right
     }
   }

});

可能有一个更简单、更优雅的解决方案,但这对我来说效果很好。

于 2012-11-07T13:21:23.580 回答
2

我一直在谷歌搜索解决这个问题的好方法......我尝试覆盖ontouchevent等......

我认为这对我来说是最好的解决方案(而且不那么老套)..只是实现一个最大或最小跟踪器并将其设置为当前页面

        maxPageToScroll = viewPager.getCurrentItem();
        minPageToScroll = viewPager.getCurrentItem();

然后添加到“onPageSelected”方法:

public void onPageSelected(int position) {

        if (position < minPageToScroll) {
            viewPager.setCurrentItem(maxPageToScroll);
        }
        else if (position > maxPageToScroll) {
            viewPager.setCurrentItem(maxPageToScroll);
            // you can alert here that user needs to do certain actions before proceeding
        }
        else { 
            // enter normal commands here
        }

因此,当满足条件时,您只需将 maxpage 增加 1..

        maxPageToScroll = viewPager.getCurrentItem() + 1;

请注意,这不会阻止用户表单滚动......它只是阻止查看寻呼机更改页面。

于 2013-02-22T08:04:00.700 回答
1

我认为不需要扩展 ViewPager。您需要做的是即时修改提供给 PagerAdapter 的页面列表。这意味着,您检查某个页面是否标记为“已完成”,然后才将下一页添加到列表中。这就是 ViewPager 的工作原理。

看看Roman Nurik 的向导-寻呼机实现。在 MainActivity 中有一个名为 recalculateCutOffPage 的方法,它可以按照我说的做。

于 2013-09-07T07:28:08.087 回答
1

您可以使用自定义视图寻呼机

public class CustomViewPager extends ViewPager
{   
float mStartDragX;
OnSwipeOutListener mListener;
Context context;
public static boolean enabled;

public CustomViewPager(Context context, AttributeSet attrs)
{
    super(context, attrs);
    this.context = context;
    enabled = true;
}


@Override
public boolean onTouchEvent(MotionEvent event)
{

    if (enabled) //view pager scrolling enable if true
    {
        return super.onTouchEvent(event);
    }
    return false;
}


@Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{

    if (enabled)enter code here
    {
        return super.onInterceptTouchEvent(ev);
    }
    else  // view pager disable scrolling 
    {
        float x = ev.getX();
        switch (ev.getAction())
        {
            case MotionEvent.ACTION_DOWN:
                mStartDragX = x;

                break;
            case MotionEvent.ACTION_MOVE:
                if (mStartDragX < x - 100)//100 value velocity
                {
                    //Left scroll 
                    //return super.onInterceptTouchEvent(ev); 
                }
                else
                    if (mStartDragX > x + 100)
                    {
                        //Right scroll 
                        //return super.onInterceptTouchEvent(ev);
                    }
                break;
        }
    }

    return false;

}


public void setOnSwipeOutListener(OnSwipeOutListener listener)
{
    mListener = listener;
}

public interface OnSwipeOutListener
{

    public void onSwipeOutAtStart();


    public void onSwipeOutAtEnd();
}

}

于 2014-04-21T10:07:44.610 回答
-1

我为具有用户无法通过的最大页面的向导实现了 viewpager。

最后,解决方案在适配器中。我更改了 PagerAdapter 的计数,这样可以阻止用户传递最大页面:

@Override
public int getCount() {
    return mProgress; //max page + 1
}

当用户进入下一页时:

private void setWizardProgress(int progress) {
    if(progress > mProgress) {
        mProgress = progress;
        mWizardPagerAdapter.notifyDataSetChanged();
    }
}

这样,当用户处于最大页面时,他无法向右滚动,直到进度更新。

于 2014-02-06T12:49:25.327 回答