如何在Android中当scrollView滚动到底部时触发事件?

15

我正在寻找一个能在scrollView上使用的事件,当用户滚动到底部时触发。

例如,我的项目列表应自动扩展更多项目。

有什么想法如何实现这个功能吗?

非常感谢任何提示。


不需要扩展ScrollView的简单解决方案:https://dev59.com/22kv5IYBdhLWcg3w1kOq#41139693 - Andrew Koster
5个回答

10
请阅读这篇文章:Android:了解ScrollView何时到达底部 源代码:
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) 
{
    // Grab the last child placed in the ScrollView, we need it to determinate the bottom position.
    View view = (View) getChildAt(getChildCount()-1);

    // Calculate the scrolldiff
    int diff = (view.getBottom()-(getHeight()+getScrollY()));

    // if diff is zero, then the bottom has been reached
    if( diff == 0 )
    {
        // notify that we have reached the bottom
        Log.d(ScrollTest.LOG_TAG, "MyScrollView: Bottom has been reached" );
    }

    super.onScrollChanged(l, t, oldl, oldt);
}

如果您想的话,可以添加自定义小部件。
例如:
package se.marteinn.ui;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ScrollView;


/**
 * Triggers a event when scrolling reaches bottom.
 *
 * Created by martinsandstrom on 2010-05-12.
 * Updated by martinsandstrom on 2014-07-22.
 *
 * Usage:
 *
 *  scrollView.setOnBottomReachedListener(
 *      new InteractiveScrollView.OnBottomReachedListener() {
 *          @Override
 *          public void onBottomReached() {
 *              // do something
 *          }
 *      }
 *  );
 * 
 *
 * Include in layout:
 *  
 *  <se.marteinn.ui.InteractiveScrollView
 *      android:layout_width="match_parent"
 *      android:layout_height="match_parent" />
 *  
 */
public class InteractiveScrollView extends ScrollView {
    OnBottomReachedListener mListener;

    public InteractiveScrollView(Context context, AttributeSet attrs,
            int defStyle) {
        super(context, attrs, defStyle);
    }

    public InteractiveScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public InteractiveScrollView(Context context) {
        super(context);
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        View view = (View) getChildAt(getChildCount()-1);
        int diff = (view.getBottom()-(getHeight()+getScrollY()));

        if (diff == 0 && mListener != null) {
            mListener.onBottomReached();
        }

        super.onScrollChanged(l, t, oldl, oldt);
    }


    // Getters & Setters

    public OnBottomReachedListener getOnBottomReachedListener() {
        return mListener;
    }

    public void setOnBottomReachedListener(
            OnBottomReachedListener onBottomReachedListener) {
        mListener = onBottomReachedListener;
    }


    /**
     * Event listener.
     */
    public interface OnBottomReachedListener{
        public void onBottomReached();
    }

}

你也可以重写 onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) 方法,并检查 clampedY 是否为 true。 - Julian
我有些困惑。当你写下这段代码时:int diff = (view.getBottom()-(recyclerView.getHeight()+recyclerView.getScrollY())); 为什么我们需要添加recyclerView.getScrollY()呢?getBottom()计算总是相对于父级的。我们为什么需要添加偏移量呢?你能解释一下吗? - Manish Kumar Sharma

2

我曾经也遇到过同样的问题,我通过使用ListView(如果需要会自动添加ScrollView)并设置OnScrollListener解决了它。

以下是代码示例:

        tableListView.setOnScrollListener(new OnScrollListener() {

        public void onScrollStateChanged(AbsListView view, int scrollState) {

        }

        public void onScroll(AbsListView view, int firstVisibleItem,
                int visibleItemCount, int totalItemCount) {
            if (visibleItemCount == totalItemCount)
            // too little items (ScrollView not needed)
            {
                java.lang.System.out.println("too little items to use a ScrollView!");
            }
            else {
                if ((firstVisibleItem + visibleItemCount) == totalItemCount) {
                    // put your stuff here
                    java.lang.System.out.println("end of the line reached!");
                }
            }

        }
    });

1

如果你使用的是 Android API 21(Android M)以下版本,不要尝试使用 SetOnScrollChangeListener,可以尝试使用以下方法:

yourScrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
            @Override
            public void onScrollChanged() {
                int rootHeight = yourScrollView.getHeight();
                int childHeight = yourScrollView.getChildAt(0).getHeight();
                int scrollY = yourScrollView.getScrollY();
                if(childHeight - rootHeight == scrollY)
                Log.d("Hei","You Have Reach The End!");
            }
        });

0

虽然这个答案有点晚了,但如果有人碰巧遇到了这个问题,我们可以使用setOnScrollChangeListener来解决。

  childScrollView.setOnScrollChangeListener(object : NestedScrollView.OnScrollChangeListener {
            override fun onScrollChange(v: NestedScrollView?, scrollX: Int, scrollY: Int, oldScrollX: Int, oldScrollY: Int) {
                when {//maxScrollPixelPoint  is defined local/global variable
                    scrollY > maxScrollPixelPoint -> {
                        maxScrollPixelPoint = scrollY
                    }
                    scrollY == maxScrollPixelPoint -> {
                        //reached bottom 
                    }
                }
            }

        })

-2
这里有一个更简单的解决方案,无需子类化滚动视图。 假设您有一个 RecyclerView recyclerView 变量,
recyclerView.computeVerticalScrollRange() 可以给出完整的滚动范围,或者换句话说,内容高度。
(recyclerView.computeVerticalScrollOffset() 会给出滚动时距顶部的偏移量。此值将一直持续到内容高度-滚动视图高度。
因此,
    if( (recyclerView.computeVerticalScrollOffset() == 
(recyclerView.computeVerticalScrollRange() - recyclerView.getHeight()) ) {
    // You have hit rock bottom.
    }

直接操作滚动视图的子视图似乎很不专业。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接