Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/231.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android scrollview onScrollChanged_Android_Android Scrollview_Onscrollchanged - Fatal编程技术网

Android scrollview onScrollChanged

Android scrollview onScrollChanged,android,android-scrollview,onscrollchanged,Android,Android Scrollview,Onscrollchanged,我在滚动视图中的文本视图中有固定内容。当用户滚动到某个位置时,我想启动一个活动或触发一个Toast <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/scroller"> <LinearLayout xmln

我在滚动视图中的文本视图中有固定内容。当用户滚动到某个位置时,我想启动一个活动或触发一个
Toast

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="fill_parent" android:layout_height="fill_parent"
 android:id="@+id/scroller">
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical" android:layout_width="fill_parent"
  android:layout_height="fill_parent">
  <TextView android:layout_width="fill_parent" android:id="@+id/story"
   android:layout_height="wrap_content" android:text="@string/lorem"
   android:gravity="fill" />
 </LinearLayout>
</ScrollView>

我的问题是实现受保护的方法
onScrollChanged
以查找滚动视图的位置

我已经找到了答案,有没有比在我发布的链接中声明一个界面、覆盖滚动视图等更简单的解决方案


ScrollView不提供滚动事件的侦听器,甚至不提供检查用户滚动到底有多远的方法,因此您必须按照链接的建议进行操作。

实际上有一种方法可以知道用户滚动到底有多远。ScrollView中的getScrollY()方法告诉您。

有一种比子类化
ScrollView
简单得多的方法。
ScrollView
ViewTreeObserver
对象可用于侦听滚动

由于
ViewTreeObserver
对象可能在
ScrollView
的生命周期内发生变化,因此我们需要在
ScrollView
上注册一个
OnTouchListener
,以便在滚动时获得它的
ViewTreeObserver

final ViewTreeObserver.OnScrollChangedListener onScrollChangedListener = new
                           ViewTreeObserver.OnScrollChangedListener() {

    @Override
    public void onScrollChanged() {
        //do stuff here 
    }
};

final ScrollView scrollView = (ScrollView) findViewById(R.id.scroller);
scrollView.setOnTouchListener(new View.OnTouchListener() {
    private ViewTreeObserver observer;

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (observer == null) {
            observer = scrollView.getViewTreeObserver();
            observer.addOnScrollChangedListener(onScrollChangedListener);
        }
        else if (!observer.isAlive()) {
            observer.removeOnScrollChangedListener(onScrollChangedListener);
            observer = scrollView.getViewTreeObserver();
            observer.addOnScrollChangedListener(onScrollChangedListener);
        }

        return false;
    }
});

这个问题很老了,但万一有人(像我一样)路过:

从API 23开始,Android的
视图有一个
OnScrollChangeListener

支持库中的还支持在API级别之前设置滚动侦听器。据我所知,
NestedScrollView
可以毫无问题地替代普通的
ScrollView

我扩展了ScrollView。也许会有帮助

class MyScroll extends ScrollView {
    boolean onTop=true;
    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        //Log.d(TAG, "scroll changed: " + this.getTop() + " "+t);
        if(t <= 0){
            onTop = true;
            //Log.d(TAG, "scroll top: " + t);
            super.onScrollChanged(l, t, oldl, oldt);
            return;
            // reaches the top end
        }
        onTop = false;

        View view = (View) getChildAt(getChildCount()-1);
        int diff = (view.getBottom()-(getHeight()+getScrollY()+view.getTop()));// Calculate the scrolldiff
        if( diff <= 0 ){
            // if diff is zero, then the bottom has been reached
        }
        super.onScrollChanged(l, t, oldl, oldt);
    }
}
MyScroll类扩展了ScrollView{ 布尔onTop=真; @凌驾 CrollChanged上的受保护无效(int l、int t、int oldl、int oldt){ //Log.d(标记“scroll changed:”+this.getTop()+“”+t);
如果(t只需使用
NestedScroll
NestedScroll.setOnScrollChangeListener()

就可以了,这有助于在Android中监听任意视图的滚动事件。在内部,该组件在使用旧Android API的设备上添加ViewTreeObserver滚动事件监听器(类似于Shubhadeep Chaudhuri的回答中提出的建议)并在具有新Android API(API级别23+)的设备上查看滚动事件侦听器。

从API 23 Android M开始,您可以使用OnScrollChangeListener

 scrollView.setOnScrollChangeListener(new View.OnScrollChangeListener() {
        @Override
        public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
            //work with parameters
        }
    });

NestedScrollView与android.widget.ScrollView类似,但它支持在新版本和旧版本的android上同时充当嵌套滚动父级和子级

第一个-使用NestedScrollView绑定代替ScrollView

第二个-设置滚动侦听器,如下所示,通过示例检测headerView的Y轴移动

    nestedScrollView.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() {

        @Override
        public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
            Log.d(TAG, "onScrollChangeForY - scrollY: " + scrollY + " oldScrollY: " + oldScrollY);

            int MOVE = -1, SCROLL_UP = 0, SCROLL_DOWN = 1;
            float initialPositionY = headerView.getY();

            MOVE = scrollY > oldScrollY ? SCROLL_UP : SCROLL_DOWN;

            if (MOVE == SCROLL_UP) {

                int incrementY = scrollY - oldScrollY;

                headerView.setY(initialPositionY - incrementY);

            } else {

                int incrementY = oldScrollY - scrollY;

                headerView.setY(initialPositionY + incrementY);
            }
        }
    });

您可以使用此触发器显示Toast或开始活动

 scrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
        @Override
        public void onScrollChanged() {
             // do something when Scroll  
        }
    });

您可以使用此代码检测是否向上或向下滚动

scrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
            int lastScroll=0;
            @Override
            public void onScrollChanged() {
                int scrollY = scrollView.getScrollY(); // For ScrollView herzontial use getScrollX()

                if (scrollY > lastScroll ) {
                    Log.e("scroll","down scroll"+scrollY);
                } else if (scrollY < lastScroll ) {
                    Log.e("scroll","up scroll"+scrollY);
                }
                lastScroll=scrollY;
            }
        });
scrollView.getViewTreeObserver().addOnScrollChangedListener(新的ViewTreeObserver.OnScrollChangedListener(){
int lastcoll=0;
@凌驾
public void onScrollChanged(){
int scrollY=scrollView.getScrollY();//对于scrollView区域,请使用getScrollX()
如果(滚动>上次滚动){
Log.e(“滚动”、“向下滚动”+滚动);
}else if(滚动<上次滚动){
Log.e(“滚动”、“向上滚动”+滚动);
}
lastScroll=滚动;
}
});

没有,根据这一点:我在公司的一个项目中使用了这个解决方案。我在这里发布一些东西之前测试了所有东西。也许你也应该这样做?对不起,误读了这个问题。它适用于
滚动视图
,但不适用于
列表视图
网格视图
。有一个可以覆盖的CrollChanged方法。比如ise getScrollX,getScrollY可以使用。这个答案现在似乎无效。从API 23(M)开始,有一个名为“OnScrollChangeListener”的监听器scrollView.setOnScrollChangeListener(new View.OnScrollChangeListener(){@Override public void onScrollChange(视图v,int scrollX,int scrollY,int oldScrollX,int oldScrollY){//使用参数}})@S.D.NChanakaFernando还应该注意的是,当涉及到滚动时,它仍然没有提供一个特定的内置解决方案。例如,如果你想检测滚动的结束,你必须手动使用
onScrollChangeListener
,这是非常烦人的。下面是一些任何人在这个问题上绊倒的建议问题:你可以使用它,这并不一定比子类化
ScrollView
容易。实际上,它包含更多的代码。如果你子类化,你可以覆盖
onScrollChanged
方法。我尝试了这个方法,它似乎为相同的scroll Y值触发了20次或更多的事件。这似乎并不理想。嗯……这是一个巨大的问题使用此代码!此问题会导致错误,如@RandomEngy comment中的错误。因此我不知道为什么它的投票率如此之高。它会在SCROLL上的每个触摸事件中添加此侦听器。因此,基本上,如果您单击滚动20次,将导致20次调用侦听器。侦听器应该只添加一次。例如:
scrollView.getViewTreeObserver().addOnScrollChangedListener(新的ViewTreeObserver.OnScrollChangedListener(){@Override public void onScrollChanged(){//do stuff}}});
。不在触控方式内,甚至更糟的是,它可能会添加至少40个监听器(每次点击至少会触控和触控)在这个例子中,我使用了
OnTouchListener
,因为上面说“返回的ViewTreeObserver观察器不保证在该视图的生命周期内保持有效”。我编辑了答案,因此如果
ViewTreeObserver
不再活动,那么对它的回调