简体   繁体   English

Android:onScrollStateChanged SCROLL_STATE_IDLE 有时不会触发

[英]Android: onScrollStateChanged SCROLL_STATE_IDLE sometimes doesn't fire

I'm running into a bit of a problem.我遇到了一点问题。 What I'm doing: I've got a ListView which has got some images in it.我在做什么:我有一个 ListView,里面有一些图像。 To make the scrolling smoother I've disabled the images to show up when scrolling.为了使滚动更流畅,我禁用了滚动时显示的图像。 Now there seems to be a bug in Android which sometimes causes the scroll state to not change back from SCROLL_STATE_FLING back to SCROLL_STATE_IDLE, which causes my images to not show up again.现在,Android 中似乎存在一个错误,有时会导致滚动状态无法从 SCROLL_STATE_FLING 变回 SCROLL_STATE_IDLE,从而导致我的图像不再显示。

My first thought was to set an onTouchListener and check when I get ACTION_UP, but that doesn't help because the SCROLL_STATE_FLING state is obviously being set after that.我的第一个想法是设置一个 onTouchListener 并检查何时获得 ACTION_UP,但这无济于事,因为 SCROLL_STATE_FLING 状态显然是在此之后设置的。 So now I've thought I could start a timer when the SCROLL_STATE_FLING state is being set and check after some time if the state is still in fling mode and then invalidate my view.所以现在我想我可以在设置 SCROLL_STATE_FLING 状态时启动一个计时器,并在一段时间后检查状态是否仍处于翻转模式,然后使我的视图无效。 But I don't think that's a very good solution.但我认为这不是一个很好的解决方案。

Does anyone have a better idea on how I could do that?有没有人对我如何做到这一点有更好的想法? I've seen this reply but I need a solution for API level < 9 (plus it also sometimes happen when it's not overscrolling)我已经看到了这个回复,但我需要一个 API 级别 < 9 的解决方案(而且它有时也会在它没有过度滚动时发生)

Here's my code for that:这是我的代码:

    mList.setOnScrollListener(new OnScrollListener() {

        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
            mListAdapter.setIsScrolling(scrollState != SCROLL_STATE_IDLE);
            Log.i(this, "scrollStateChanged" + scrollState);
            if (scrollState == SCROLL_STATE_IDLE) {
                mList.invalidateViews();
            }
        }

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        }
    });

Thanks, Maria谢谢,玛丽亚

I had the same problem, so my solution was to just detect if the scrollview position has reached the last page and in that case always load the images regardless of the scroll state (since the problem seems to always occur when the user flings to the end of the listview).我遇到了同样的问题,所以我的解决方案是只检测滚动视图位置是否已到达最后一页,在这种情况下,无论滚动状态如何,始终加载图像(因为问题似乎总是在用户跳到最后时发生的列表视图)。 So modifying your code you would have:因此,修改您的代码,您将拥有:

mList.setOnScrollListener(new OnScrollListener() {

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        mListAdapter.setIsScrolling(scrollState != SCROLL_STATE_IDLE);
        Log.i(this, "scrollStateChanged" + scrollState);

        int first = view.getFirstVisiblePosition();
        int count = view.getChildCount();

        if (scrollState == SCROLL_STATE_IDLE || (first + count > mListAdapter.getCount()) ) {
            mList.invalidateViews();
        }
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
    }
});

I ran into the same issue with a RecyclerView .我遇到了与RecyclerView相同的问题。

Jason Burke's answer is correct, but I'll provide an alternate way of checking if you are at the beginning/end of the RecyclerView / ListView . Jason Burke 的回答是正确的,但我将提供另一种方法来检查您是否处于RecyclerView / ListView的开头/结尾。

I do it in onScrolled instead of onScrollStateChanged since I don't trust that I get a state changed event in the case when you scroll/fling to the edge of the RecyclerView .我在onScrolled而不是onScrollStateChanged执行此操作,因为我不相信在滚动/飞到RecyclerView边缘时会收到状态更改事件。

recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {

    override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
        super.onScrollStateChanged(recyclerView, newState)

        if (newState == RecyclerView.SCROLL_STATE_IDLE) {
            updateUi()
        }
    }

    override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
        super.onScrolled(recyclerView, dx, dy)

        /* If the user scrolls to the edges of the recyclerview, we can't trust that we get the SCROLL_STATE_IDLE state.
         * Therefore we have to update the view here in onScrolled for these cases
         */
        if (!recyclerView.canScrollVertically(1) || !recyclerView.canScrollVertically(-1)) {
            updateUi()
        }
    }
}

In my case it was actually a horizontal RecyclerView, so I had to do this instead:在我的例子中,它实际上是一个水平的 RecyclerView,所以我不得不这样做:

if (!recyclerView.canScrollHorizontally(1) || !recyclerView.canScrollHorizontally(-1)) {
    updateUi()
}

I have had this same problem and posted a workaround on the bug list :我遇到了同样的问题,并在错误列表上发布了一个解决方法:

For anybody still running into this problem (as I was last week) a workaround that works for me is the following: If android SDKInt == 7 set a onTouchListener on the (Abs)ListView对于仍然遇到这个问题的任何人(就像我上周一样),对我有用的解决方法如下:如果 android SDKInt == 7 在(Abs)ListView上设置一个onTouchListener

In that onTouchListener when the OnTouch event action is MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL在那个onTouchListenerOnTouch事件动作是OnTouch MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL you force a onScrollStateChanged with first a SCROLL_STATE_FLING and then a SCROLL_STATE_IDLE MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL onScrollStateChanged你强制一个onScrollStateChanged与第一个SCROLL_STATE_FLING然后一个SCROLL_STATE_IDLE

Code example: In the onCreate :代码示例:在onCreate

 if(androidSDKInt <= 7){ listViewDateSelector.setOnTouchListener(new FingerTracker(onScrollListener)); }

Then add a private class with:然后添加一个私有类:

 private class FingerTracker implements View.OnTouchListener { private OnScrollListener myOnScrollListener; public FingerTracker(OnScrollListener onScrollListener){ myOnScrollListener = onScrollListener; } public boolean onTouch(View view, MotionEvent event) { final int action = event.getAction(); boolean mFingerUp = action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL; if (mFingerUp) { myOnScrollListener.onScrollStateChanged((AbsListView) view, OnScrollListener.SCROLL_STATE_FLING); myOnScrollListener.onScrollStateChanged((AbsListView) view, OnScrollListener.SCROLL_STATE_IDLE); } return false; } }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 当Scroll_State_Idle时onScrollStateChanged不会平滑滚动 - onScrollStateChanged wont scroll smooth when Scroll_State_Idle 回收器添加侦听器onScrollState将回调滚动状态“ SCROLL_STATE_IDLE”更改为不可忽略的延迟时间 - Recycler add listener onScrollStateChanged that callback scroll state “SCROLL_STATE_IDLE” for a delay time which can't be ignored SCROLL_STATE_IDLE无法解析符号,为什么? - SCROLL_STATE_IDLE can not resolve symbol why? android:AbsListView.OnScrollListener在SCROLL_STATE_TOUCH_SCROLL(版本2.1)之后不调用SCROLL_STATE_IDLE - android: AbsListView.OnScrollListener SCROLL_STATE_IDLE is not called after SCROLL_STATE_TOUCH_SCROLL (Version 2.1) SCROLL_STATE_IDLE 上的 NumberPicker.getValue(),可能不是最后更新的值 - NumberPicker.getValue() on SCROLL_STATE_IDLE, might not be the last updated value Android-长时间未触发警报有时 - Android - Alarm doesn`t fire sometimes after long period 警报无法正常触发,有时甚至根本无法触发 - Alarm doesn't fire presicely and sometimes not at all Android setOnEditorActionListener() 不会触发 - Android setOnEditorActionListener() doesn't fire 如何检测Android Scroll视图是否处于空闲状态? - How to detect whether Android Scroll view is in idle state? Flutter中Android的RecyclerView.SCROLL_STATE_IDLE相当于什么 - What is the equivalent of Android's RecyclerView.SCROLL_STATE_IDLE in Flutter
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM