区分ViewPager中的用户滚动和程序化页面更改

时间:2013-07-23 20:02:56

标签: android android-viewpager

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

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

3 个答案:

答案 0 :(得分:84)

好的,事实证明我对ViewPager.onPageChangeListener中的答案是正确的。特别是它使用onPageScrollStateChanged(int state)。基本上,ViewPager中的页面可以包含三种状态:

  1. 拖动:表示用户当前正在拖动寻呼机。
  2. 空闲:表示寻呼机处于空闲,已稳定状态。
  3. 结算:表示寻呼机正在结算到最终位置。
  4. 因此,拖动状态仅在用户物理拖动当前页面时发生。因此,当用户刷过页面时,状态按以下顺序发生:拖动 - >定居 - >闲。现在,{"定居"之间调用onPageSelected(int position)方法。和#34;闲置"状态。因此,为了确定页面改变是否是由用户滚动引起的,只需要检查先前的状态是否是"拖动"并且目前的状态是"定居"。然后,您可以保留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;
    }
    

    ifelse if语句无需如此明确,但为了清晰起见,我这样做了。

答案 1 :(得分: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) {

}

答案 2 :(得分:2)

我的答案标记是正确的,并且在下面的评论中。

首先,我分析完整的监听器的行为:

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与{1}}不同,适用于程序化活动 state

  • SCROLL_STATE_SETTLING在周期结束之前发生,但在我们能够确定更改是由用户触发还是以编程方式触发后,所以之前发生的任何事情都会在这一点上告诉我们如果是用户

解决方案:

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

onPageSelected

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