android:smoothScrollToPosition() 不能正常工作

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11431832/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 07:23:50  来源:igfitidea点击:

android: smoothScrollToPosition() not working correctly

androidlistviewselectionandroid-arrayadaptersmooth-scrolling

提问by user1515520

I'm trying to smoothly scroll to last element of a list after adding an element to the arrayadapter associated with the listview. The problem is that it just scrolls to a random position

在将元素添加到与列表视图关联的数组适配器后,我试图平滑滚动到列表的最后一个元素。问题是它只是滚动到一个随机位置

arrayadapter.add(item);
//DOES NOT WORK CORRECTLY:
listview.smoothScrollToPosition(arrayadapter.getCount()-1);

//WORKS JUST FINE:
listview.setSelection(arrayadapter.getCount()-1);

回答by Martin Marconcini

You probably want to tell the ListView to post the scroll when the UI thread can handle it (which is why yours it not scrolling properly). SmoothScroll needs to do a lot of work, as opposed to just go to a position ignoring velocity/time/etc. (required for an "animation").

您可能想告诉 ListView 在 UI 线程可以处理它时发布滚动(这就是为什么它不能正确滚动)。SmoothScroll 需要做很多工作,而不是仅仅去一个忽略速度/时间/等的位置。(“动画”所需)。

Therefore you should do something like:

因此,您应该执行以下操作:

    getListView().post(new Runnable() {
        @Override
        public void run() {
            getListView().smoothScrollToPosition(pos);
        }
    });

回答by Lars Blumberg

(Copied from my answer: smoothScrollToPositionFromTop() is not always working like it should)

(复制自我的回答:smoothScrollToPositionFromTop() 并不总是像它应该的那样工作

This is a known bug.See https://code.google.com/p/android/issues/detail?id=36062

这是一个已知的错误。https://code.google.com/p/android/issues/detail?id=36062

However, I implemented this workaround that deals with all edge cases that might occur:

但是,我实施了此解决方法来处理可能发生的所有边缘情况:

First call smothScrollToPositionFromTop(position)and then, when scrolling has finished, call setSelection(position). The latter call corrects the incomplete scrolling by jumping directly to the desired position. Doing so the user still has the impression that it is being animation-scrolled to this position.

首先调用smothScrollToPositionFromTop(position),然后在滚动完成后调用setSelection(position)。后一个调用通过直接跳转到所需位置来纠正不完整的滚动。这样做,用户仍然会觉得它正在被动画滚动到这个位置。

I implemented this workaround within two helper methods:

我在两个辅助方法中实现了这个解决方法:

smoothScrollToPosition()

平滑滚动到位置()

public static void smoothScrollToPosition(final AbsListView view, final int position) {
    View child = getChildAtPosition(view, position);
    // There's no need to scroll if child is already at top or view is already scrolled to its end
    if ((child != null) && ((child.getTop() == 0) || ((child.getTop() > 0) && !view.canScrollVertically(1)))) {
        return;
    }

    view.setOnScrollListener(new AbsListView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(final AbsListView view, final int scrollState) {
            if (scrollState == SCROLL_STATE_IDLE) {
                view.setOnScrollListener(null);

                // Fix for scrolling bug
                new Handler().post(new Runnable() {
                    @Override
                    public void run() {
                        view.setSelection(position);
                    }
                });
            }
        }

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

    // Perform scrolling to position
    new Handler().post(new Runnable() {
        @Override
        public void run() {
            view.smoothScrollToPositionFromTop(position, 0);
        }
    });
}

getChildAtPosition()

getChildAtPosition()

public static View getChildAtPosition(final AdapterView view, final int position) {
    final int index = position - view.getFirstVisiblePosition();
    if ((index >= 0) && (index < view.getChildCount()))?{
        return view.getChildAt(index);
    } else {
        return null;
    }
}

回答by TaoZang

You should use setSelection() method.

您应该使用 setSelection() 方法。

回答by Siddhesh Shirodkar

Use LayoutManager to smooth scroll

使用 LayoutManager 平滑滚动

layoutManager.smoothScrollToPosition(recyclerView, new RecyclerView.State(), position);

回答by Daniel Roberts

The set selection method mentioned by Lars works, but the animation was too jumpy for our purposes as it skips whatever was left. Another solution is to recall the method repeatedly until the first visible position is your index. This is best done quickly and with a limit as it will fight the user scrolling the view otherwise.

Lars 提到的设置选择方法有效,但动画对于我们的目的来说太跳跃了,因为它跳过了剩下的任何内容。另一种解决方案是重复调用该方法,直到第一个可见位置是您的索引。这最好快速完成并且有限制,否则它会与用户滚动视图作斗争。

private  void DeterminedScrollTo(Android.Widget.ListView listView, int index, int attempts = 0) {
    if (listView.FirstVisiblePosition != index && attempts < 10) {
        attempts++;
        listView.SmoothScrollToPositionFromTop (index, 1, 100);
        listView.PostDelayed (() => {
            DeterminedScrollTo (listView, index, attempts);
        }, 100);
    }
}

Solution is in C# via. Xamarin but should translate easily to Java.

解决方案是在 C# 中通过。Xamarin 但应该很容易转换为 Java。

回答by VSB

final Handler handler = new Handler();
//100ms wait to scroll to item after applying changes
handler.postDelayed(new Runnable() {
@Override
public void run() {
   listView.smoothScrollToPosition(selectedPosition);
}}, 100);

回答by Code Poet

Do you call arrayadapter.notifyDataSetChanged()after you called arrayadapter.add()? Also to be sure, smoothScrollToPositionand setSelectionare methods available in ListViewnot arrayadapteras you have mentioned above.

arrayadapter.notifyDataSetChanged()打完电话后还打arrayadapter.add()吗?还可以肯定,smoothScrollToPositionsetSelection在可用的方法ListView并不arrayadapter如你所提到的。

In any case see if this helps: smoothScrollToPosition after notifyDataSetChanged not working in android

在任何情况下,看看这是否有帮助: smoothScrollToPosition after notifyDataSetChanged not working in android