38

我的应用程序中有一个android.support.v4.view.ViewPager,我想区分以编程方式启动的平滑滚动和用户启动的触摸滚动。

我看过了ViewPager.OnPageChangeListener,我相信答案可能就在那里,但我只是不确定如何。

4

3 回答 3

96

好的,所以事实证明我对答案的看法是正确的ViewPager.onPageChangeListener。特别是它在于使用onPageScrollStateChanged(int state). ViewPager本质上,a 中的页面可以处于三种状态:

  1. Dragging:表示用户当前正在拖动寻呼机。
  2. 空闲:表示寻呼机处于空闲、稳定状态。
  3. 安定:表示寻呼机正在安定到最终位置。

所以拖动状态只发生在当前页面被用户物理拖动时。因此,当用户滑动页面时,状态按以下顺序发生:拖动 -> 稳定 -> 空闲。现在,该onPageSelected(int position)方法在“Settling”和“Idle”状态之间被调用。因此,为了确定页面更改是否是由用户滚动引起的,只需要检查之前的状态是“拖动”并且当前状态是“稳定”。然后,您可以保留一个boolean变量来跟踪页面更改是否是用户发起的,并在您的onPageSelected(int position)方法中检查它。

这是我的onPageScrollStateChanged方法

public void onPageScrollStateChanged(int state) 
{
    if (previousState == ViewPager.SCROLL_STATE_DRAGGING
            && state == ViewPager.SCROLL_STATE_SETTLING)
        userScrollChange = true;

    else if (previousState == ViewPager.SCROLL_STATE_SETTLING
            && state == ViewPager.SCROLL_STATE_IDLE)
        userScrollChange = false;

    previousState = state;
}

ifandelse if语句不需要那么明确,但我这样做是为了清楚起见。

于 2013-07-23T20:53:21.233 回答
7

我将自己的答案标记为正确并在下面的评论中。

首先我分析一下完整的监听器是如何表现的:

USER
onPageScrollStateChanged:        1             SCROLL_STATE_DRAGGING
onPageScrollStateChanged:        2             SCROLL_STATE_SETTLING
onPageSelected:              SELECTION     
onPageScrollStateChanged:        0             SCROLL_STATE_IDLE

PROGRAMATIC
onPageScrollStateChanged:        2             SCROLL_STATE_SETTLING
onPageSelected:              SELECTION
onPageScrollStateChanged:        0             SCROLL_STATE_IDLE  

发现:

  • 正如您在这两种情况下看到的,当onPageScrollStateChanged移动到时事件结束SCROLL_STATE_IDLE这意味着空闲是循环的结束

  • 用户事件是SCROLL_STATE_DRAGGING,然后SCROLL_STATE_SETTLING 是 2,而states不是只有 1state用于程序化事件 SCROLL_STATE_SETTLING

  • onPageSelected发生在周期结束之前,但在我们能够确定更改是由用户触发还是以编程方式触发之后,所以之前发生的任何事情都会在那时告诉我们它是否是用户

解决方案:

所以我使用List<Integer>每次循环结束时重置的,并且能够知道用户是否在onPageSelected方法中触发了事件,我检查了List. 如果大小为 2,则表示用户滚动寻呼机。

abstract class PagerListenerActivity extends AppCompatActivity implements ViewPager.OnPageChangeListener {

    private static final int USER_SCROLL = 2;
    private List<Integer> validator = new ArrayList<>();

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    }

    @Override
    public void onPageSelected(int position) {
        if (validator.size() == USER_SCROLL) {
            userScroll(position);
        }
    }

    @Override
    public void onPageScrollStateChanged(int state) {
        validator.add(state);
        if (ViewPager.SCROLL_STATE_IDLE == state) {
            validator.clear();
        }

    }

    protected abstract void userScroll(int position);
}

现在,这个类可以方便地被另一个需要它的人继承。

于 2017-12-08T19:25:15.863 回答
4

你是对的使用ViewPager.OnPageChangeListener

@Override
public void onPageSelected(int arg0) {
    // programmatically-initiated                           
}

@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {

}

@Override
public void onPageScrollStateChanged(int arg0) {
    // user-initiated touch scroll      
}

或者,您可以使用布尔标志来区分programmatically-initiated smooth scroll and a user-initiated touch scroll. 例如,如果您使用setCurrentItem(int item)以编程方式更改页面,请尝试:

boolean progChange = false;

....
....
....

progChange = true;
setCurrentItem(somePageId);     // Set progChange = true every time

....
....
....

在你的内部ViewPager.OnPageChangeListener

@Override
public void onPageSelected(int arg0) {

}

@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
    if (progChange) {
        // programmatically-initiated
    } else {
        // user-initiated touch scroll
    }

    // Set progChange to false;
    progChange = false;                 
}

@Override
public void onPageScrollStateChanged(int arg0) {

}
于 2013-07-23T20:53:34.923 回答