如何检测滚动嵌套scrollview android在底部的位置?

Posted

技术标签:

【中文标题】如何检测滚动嵌套scrollview android在底部的位置?【英文标题】:how to detect the position of the scroll nestedscrollview android at the bottom? 【发布时间】:2016-07-08 17:09:58 【问题描述】:

我只想检测底部的滚动嵌套scrollview android的位置,以及调用函数。 我的代码是:

scroll.getViewTreeObserver()
      .addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() 
           @Override
           public void onScrollChanged() 
               int totalHeight = scroll.getChildAt(0).getHeight();
               int scrollY = scroll.getScrollY();
               Log.v("position", "totalHeight=" + totalHeight + "scrollY=" + scrollY);
               if (scrollY==totalHeight) 
                   getPlaylistFromServer("more");
               
           
      );

但总高度与 MAX ScrollY 不同。如何解决?

【问题讨论】:

使用ViewCompat.canScrollVertically(View v, int direction) 由于 ViewCompat.canScrollVertically(View v, int direction) 已弃用,请使用 View.canScrollVertically(int direction) 【参考方案1】:

NestedScrollView 参数中设置setOnScrollChangeListener 以获取

NestedScrollView v(带滚动的父级) int scrollY int oldScrollY

要检测偏移量是否在底部,需要获取内容高度v.getChildAt(0).getMeasuredHeight()的值,并比较当前滚动超过父级的高度,如果有相同的值,则表示有到了终点。

你可以通过v.getMeasuredHeight()获取父视图的高度

NestedScrollView scroller = (NestedScrollView) findViewById(R.id.myScroll);

if (scroller != null) 

    scroller.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() 
        @Override
        public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) 

            if (scrollY > oldScrollY) 
                Log.i(TAG, "Scroll DOWN");
            
            if (scrollY < oldScrollY) 
                Log.i(TAG, "Scroll UP");
            

            if (scrollY == 0) 
                Log.i(TAG, "TOP SCROLL");
            

           if (scrollY == ( v.getMeasuredHeight() - v.getChildAt(0).getMeasuredHeight() )) 
               Log.i(TAG, "BOTTOM SCROLL");
           
       
    );

【讨论】:

如何检查用户何时停止滚动,就像它变得空闲一样? 有人能解释为什么这条线有效吗? if (scrollY == (v.getChildAt(0).getMeasuredHeight() - v.getMeasuredHeight()))NestedScrollView 的测量高度怎么会小于内容的高度,即使NestedScrollView 是父级? 这种方法的最小 API 是 23,你知道另一种选择吗? @JoãoCarlos 不,这不是来自 23 API。 setOnScrollChangeListener(View.OnScrollChangeListener) 需要 API 23,但 setOnScrollChangeListener(NestedScrollView.OnScrollChangeListener) 不需要 你是我那个时代的英雄,兄弟!你的回答对我帮助很大。谢谢!【参考方案2】:

我知道已经晚了,但是..试试这个方法。

scroll.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() 
    @Override
    public void onScrollChanged() 
            View view = (View) scroll.getChildAt(scroll.getChildCount() - 1);

            int diff = (view.getBottom() - (scroll.getHeight() + scroll
                    .getScrollY()));

            if (diff == 0) 
                getPlaylistFromServer("more");
                      
    
);

快乐编码..

【讨论】:

谢谢。它拯救了我的一天。 如果您在嵌套滚动视图中有回收站视图。请参考这里。【参考方案3】:

Webserve 回答正确,但需要在 onScrollChange(覆盖方法)中进行一些更改,如下所示:

if (scrollY === v.getChildAt(0).getMeasuredHeight() - v.getMeasuredHeight()) 
   // end of the scroll view

科特林:

if (scrollY == v.getChildAt(0).measuredHeight - v.measuredHeight) 
    // end of the scroll view

【讨论】:

【参考方案4】:
  @Override
public void onScrollChange(NestedScrollView nestedScrollView, int scrollX, int scrollY, int oldScrollX, int oldScrollY) 
    if (nestedScrollView.getChildAt(nestedScrollView.getChildCount() - 1) != null) 
        if ((scrollY >= (nestedScrollView.getChildAt(nestedScrollView.getChildCount() - 1).getMeasuredHeight() - nestedScrollView.getMeasuredHeight())) &&
                scrollY > oldScrollY) 
            LogsUtils.INSTANCE.makeLogD(">onScrollChange>", ">>BOTTOm");
        

    

它对我有用,Source

【讨论】:

这个帮助了我【参考方案5】:

这对我有用:

nestedScroll.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() 
        @Override
        public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) 

            if (v.getChildAt(0).getBottom()<=(nestedScroll.getHeight()+scrollY)) 
                System.out.println("End of NestedScrollView");
            

        
    );

基本上,我们在一个nestedScrollView 中添加了许多视图,但将它们以单一视图的形式包装在一起。因此,childCount 将始终为 1,其索引为 0。因此,使用 v.getChildAt(0).getBottom() 确定其底部。现在,nestedScroll.getHeight() 以像素为单位返回高度,scrollY 将返回当前垂直原点。因此,每次到达 NestedScrollView 的底部时,上述条件都会为真。

if (v.getChildAt(0).getBottom()==(nestedScroll.getHeight()+nestedScroll.getScrollY()))

这只会在一段时间内起作用......因此,不要以这种方式使用它。

【讨论】:

【参考方案6】:

对于 api

例子

public class About extends AppCompatActivity implements 
ViewTreeObserver.OnScrollChangedListener

private float viewScrolled = 0;

   nestedScrollView.getViewTreeObserver().addOnScrollChangedListener(this);



@Override
public void onScrollChanged() 

    if (viewScrolled < nestedScrollView.getScrollY())
        viewScrolled = nestedScrollView.getScrollY();
        Log.d(TAG, "scrolling up");
    
    if (viewScrolled > nestedScrollView.getScrollY())
        viewScrolled = nestedScrollView.getScrollY();
        Log.d(TAG, "scrolling down");
    

【讨论】:

【参考方案7】:

Webserve 回答正确,但条件应该是这样的

 if (scrollY == (v?.getChildAt(0)?.measuredHeight ?: 0) - (v?.measuredHeight ?: 0)) 
    //at bottom
    

【讨论】:

【参考方案8】:

这对我有用!

            my_scroll_view.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() 
            @Override
            public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) 



                    if (scrollY == v.getChildAt(0).getMeasuredHeight() - v.getMeasuredHeight()) 
                        Log.d(TAG, "onScrollChange: SRCOLLED ==> scrollY: ======================================> THIS IS THE VERY END ");
                    

                

            
        );

【讨论】:

以上是关于如何检测滚动嵌套scrollview android在底部的位置?的主要内容,如果未能解决你的问题,请参考以下文章

如何检测scrollView的滚动方向?

如何在ScrollView中嵌套ListView

多层ScrollView嵌套UITableView、UICollectionView联动

react-native ScrollView 嵌套 FlatList滚动

解决ScrollView中嵌套ListView滚动效果冲突问题

嵌套的scrollview + recyclerview,奇怪的自动滚动行为[重复]