在Android中按像素滚动ListView

时间:2010-03-03 21:24:06

标签: android listview scroll

我想按照像素数滚动Android中的ListView。例如,我想将列表向下滚动10个像素(以便列表中的第一个项目隐藏其前10个像素行)。

我认为ListView上明显可见的scrollByscrollTo方法可以完成这项工作,但他们没有,而是错误地滚动整个列表(事实上,getScrollY即使我用手指滚动列表,也总是返回零。)

我正在做的是我正在捕捉轨迹球事件,我想根据轨迹球的运动平滑地滚动列表视图。

5 个答案:

答案 0 :(得分:11)

滚动ListView窗口小部件的支持方式是:

mListView.smoothScrollToPosition(position);

http://developer.android.com/reference/android/widget/AbsListView.html#smoothScrollToPosition(int)

但是,由于您特别提到要垂直偏移视图,因此必须调用:

mListView.setSelectionFromTop(position, yOffset);

http://developer.android.com/reference/android/widget/ListView.html#setSelectionFromTop(int,%20int)

请注意,您也可以使用smoothScrollByOffset(yOffset)。但是,它仅在API> = 11

上受支持

http://developer.android.com/reference/android/widget/ListView.html#smoothScrollByOffset(int)

答案 1 :(得分:10)

如果查看api 19中添加的scrollListBy()方法的源代码,您将看到可以使用包范围trackMotionScroll方法。

public class FutureListView {

    private final ListView mView;

    public FutureListView(ListView view) {
        mView = view;
    }

    /**
     * Scrolls the list items within the view by a specified number of pixels.
     *
     * @param y the amount of pixels to scroll by vertically
     */
    public void scrollListBy(int y) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            mView.scrollListBy(y);
        } else {
            // scrollListBy just calls trackMotionScroll
            trackMotionScroll(-y, -y);
        }
    }

    private void trackMotionScroll(int deltaY, int incrementalDeltaY) {
        try {
            Method method = AbsListView.class.getDeclaredMethod("trackMotionScroll", int.class, int.class);
            method.setAccessible(true);
            method.invoke(mView, deltaY, incrementalDeltaY);
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        };
    }
}

答案 2 :(得分:3)

以下是我的ListView子类中的一些代码。它可以很容易地进行调整,因此可以在活动代码中使用。

getListItemsHeight()返回列表的总像素高度,并使用每个项目的垂直像素偏移填充数组。虽然此信息有效,但getListScrollY()会返回当前垂直像素滚动位置,而scrollListToY()会将列表滚动到像素位置。 如果列表的大小或内容发生变化,则必须再次调用getListItemsHeight()

private int m_nItemCount;
private int[] m_nItemOffY;

private int getListItemsHeight() 
{  
    ListAdapter adapter = getAdapter();  
    m_nItemCount = adapter.getCount();
    int height = 0;
    int i;

    m_nItemOffY = new int[m_nItemCount];

    for(i = 0; i< m_nItemCount; ++i){ 
        View view  = adapter.getView(i, null, this);  

        view.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
                    MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));  

        m_nItemOffY[i] = height;
        height += view.getMeasuredHeight();
    }  

    return height;  
}  

private int getListScrollY()
{
    int pos, nScrollY, nItemY;
    View view;

    pos = getFirstVisiblePosition();
    view = getChildAt(0);
    nItemY = view.getTop();
    nScrollY = m_nItemOffY[pos] - nItemY;

    return nScrollY;
}

private void scrollListToY(int nScrollY)
{
    int i, off;

    for(i = 0; i < m_nItemCount; ++i){
        off = m_nItemOffY[i] - nScrollY;
        if(off >= 0){
            setSelectionFromTop(i, off);
            break;
        }
    }
}

答案 3 :(得分:1)

目前,ListViewCompat可能是更好的解决方案。

android.support.v4.widget.ListViewCompat.scrollListBy(@NonNull ListView listView, int y)

答案 4 :(得分:0)

如果你想按像素移动,那么你可以使用这个

public void scrollBy(ListView l, int px){
    l.setSelectionFromTop(l.getFirstVisiblePosition(),l.getChildAt(0).getTop() - px);
}

这适用于具有大量标题的偶数