Android:检测ScrollView何时停止滚动


84

ScrollView在Android中使用,其中的可见部分与ScrollView中的单元格之一大小相同Scrollview。每个“单元”的高度相同。所以我想做的是ScrollView在滚动后将其卡入到位。

目前,我正在检测用户何时触摸了,ScrollView以及他们何时开始滚动并从那里进行操作,但这是相当多的错误。当用户轻弹它并滚动然后减速时,它也需要工作。

在iPhone上,有一个类似的功能,didDecelerateScrollView滚动完成后,我可以执行任何我想要的代码。Android有这样的事情吗?还是我可以查看一些代码来找出一种更好的方法?

我查看了Android文档,找不到类似的东西。

Answers:


101

我最近不得不实现您描述的功能。我所做的是让Runnable通过将首次触发onTouchEvent时getScrollY()返回的值与变量newCheck定义的时间后返回的值进行比较,来检查ScrollView是否已停止滚动。

请参见下面的代码(有效的解决方案):

public class MyScrollView extends ScrollView{

private Runnable scrollerTask;
private int initialPosition;

private int newCheck = 100;
private static final String TAG = "MyScrollView";

public interface OnScrollStoppedListener{
    void onScrollStopped();
}

private OnScrollStoppedListener onScrollStoppedListener;

public MyScrollView(Context context, AttributeSet attrs) {
    super(context, attrs);

    scrollerTask = new Runnable() {

        public void run() {

            int newPosition = getScrollY();
            if(initialPosition - newPosition == 0){//has stopped

                if(onScrollStoppedListener!=null){

                    onScrollStoppedListener.onScrollStopped();
                }
            }else{
                initialPosition = getScrollY();
                MyScrollView.this.postDelayed(scrollerTask, newCheck);
            }
        }
    };
}

public void setOnScrollStoppedListener(MyScrollView.OnScrollStoppedListener listener){
    onScrollStoppedListener = listener;
}

public void startScrollerTask(){

    initialPosition = getScrollY();
    MyScrollView.this.postDelayed(scrollerTask, newCheck);
}

}

然后我有:

scroll.setOnTouchListener(new OnTouchListener() {

        public boolean onTouch(View v, MotionEvent event) {

            if (event.getAction() == MotionEvent.ACTION_UP) {

                scroll.startScrollerTask();
            }

            return false;
        }
});
scroll.setOnScrollStoppedListener(new OnScrollStoppedListener() {

        public void onScrollStopped() {

            Log.i(TAG, "stopped");

        }
});

顺便说一句,我在我的应用程序中使用了其他回复中的一些想法。希望这可以帮助。有任何问题请随时询问我(们)。干杯。


11
谢谢,一直在寻找类似这样的东西。改用在Horizo​​ntalScrollView中(显然)也可以。只能将getScrollY()替换为getScrollX()
Schnodahipfe 2012年

1
在这里都试过了。这是唯一可行的方法。
Mike6679

23

这是对IMHO的另一种修复,它丢失了ScrollView中的OnEndScroll事件错误。

其灵感来自卑鄙的回答。只需将此类放入您的项目中(更改程序包以匹配您自己的类),然后使用以下xml

package com.thecrag.components.ui;

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

public class ResponsiveScrollView extends ScrollView {

    public interface OnEndScrollListener {
        public void onEndScroll();
    }

    private boolean mIsFling;
    private OnEndScrollListener mOnEndScrollListener;

    public ResponsiveScrollView(Context context) {
        this(context, null, 0);
    }

    public ResponsiveScrollView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

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

    @Override
    public void fling(int velocityY) {
        super.fling(velocityY);
        mIsFling = true;
    }

    @Override
    protected void onScrollChanged(int x, int y, int oldX, int oldY) {
        super.onScrollChanged(x, y, oldX, oldY);
        if (mIsFling) {
            if (Math.abs(y - oldY) < 2 || y >= getMeasuredHeight() || y == 0) {
                if (mOnEndScrollListener != null) {
                    mOnEndScrollListener.onEndScroll();
                }
                mIsFling = false;
            }
        }
    }

    public OnEndScrollListener getOnEndScrollListener() {
        return mOnEndScrollListener;
    }

    public void setOnEndScrollListener(OnEndScrollListener mOnEndScrollListener) {
        this.mOnEndScrollListener = mOnEndScrollListener;
    }

}

再次更改软件包名称以匹配您的项目

<com.thecrag.components.ui.ResponsiveScrollView
        android:id="@+id/welcome_scroller"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/welcome_scroll_command_help_container"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:layout_below="@+id/welcome_header_text_thecrag"
        android:layout_margin="6dp">
    ....
</com.thecrag.components.ui.ResponsiveScrollView>

2
+1不错,简单的答案。我改变差值20.5f反映原有ScrollViewMAX_SCROLL_FACTOR价值。
Phil

2
这个实现很好,但是在开始时未填充滚动视图时失败。这是一种解决方法(对于水平滚动视图,因此将所有x替换为y以获得垂直的滚动视图):@Override protected void onScrollChanged(int x,int y,int oldX,int oldY){super.onScrollChanged(x,y ,oldX,oldY);如果(Math.abs(x-oldX)<SCROLL_FINISHED_THRESHOLD && x!= lastStopX || x> = getMeasuredWidth()|| x == 0){lastStopX = x; 如果(mOnEndScrollListener!= null){mOnEndScrollListener.onScrollEnded(); }
Snicolas 2013年

这并不总是有效。与在模拟器中一样,并不总是调用public void fling(int velocityY)。滚动结束阈值有时大于20像素。
安德鲁·冯

9

我将(Horizo​​ntal)ScrollView子类化,并做了如下操作:

@Override
protected void onScrollChanged(int x, int y, int oldX, int oldY) {
    if (Math.abs(x - oldX) > SlowDownThreshold) {  
        currentlyScrolling = true;
    } else {
        currentlyScrolling = false;
        if (!currentlyTouching) {
            //scrolling stopped...handle here
        }
    }
    super.onScrollChanged(x, y, oldX, oldY);
}

我将SlowDownThreshold的值设为1,因为它似乎总是最后一个onScrollChanged事件的差值。

为了使它在缓慢拖动时正确运行,我必须这样做:

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            currentlyTouching = true;
    }
    return super.onInterceptTouchEvent(event);
}

@Override
public boolean onTouch(View view, MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
            currentlyTouching = false;
            if (!currentlyScrolling) {
                //I handle the release from a drag here
                return true;
            }
    }
    return false;
}

好答案。唯一的一项。在onInterceptTouchEvent()中,您还可以处理MotionEvent.ACTION_UP和MotionEvent.ACTION_CANCEL,否则,如果您在单击上打开另一个活动,则currentTouching将保持为真。
Cynichniy Bandera

另一个解决方法:在onScrollChanged()中,即使减速尚未到1,您也必须检查滚动结束。像这样:boolean end =(oldx> x)?(x <= 0):(x> = getMaxScrollAmount()); 如果(Math.abs(x-oldx)> 1 &&!end){滚动开始;} else {scroll end}
Cynichniy Bandera

这不适用于某些设备,例如GS3。在我的GS3上,在滚动中间,y与旧y之间的差异可以为1。不过,它可以在我的Nexus 4上完美运行。我不知道为什么。
布赖恩

也不适用于Samsung Galaxy Note 2和Asus Memo Pad 7。我还在这些设备上的滚动中间看到了1的增量。
奥利弗·豪斯勒

7

我的方法是通过每次调用onScrollChanged()时更改的时间戳来确定滚动状态。确定滚动开始和结束的时间非常容易。您也可以更改阈值(我用100ms)来固定灵敏度。

public class CustomScrollView extends ScrollView {
    private long lastScrollUpdate = -1;

    private class ScrollStateHandler implements Runnable {

        @Override
        public void run() {
            long currentTime = System.currentTimeMillis();
            if ((currentTime - lastScrollUpdate) > 100) {
                lastScrollUpdate = -1;
                onScrollEnd();
            } else {
                postDelayed(this, 100);
            }
        }
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        if (lastScrollUpdate == -1) {
            onScrollStart();
            postDelayed(new ScrollStateHandler(), 100);
        }

        lastScrollUpdate = System.currentTimeMillis();
    }

    private void onScrollStart() {
        // do something
    }

    private void onScrollEnd() {
        // do something
    }

}

很好的解决方案。按预期工作。
奥利弗·豪斯勒

感谢您的代码。如何从您的代码中检测滚动启动侦听器方法。请看看我的问题stackoverflow.com/questions/27864700/...
MAMurali

6

在我看来,这是又一个简单而干净的解决方案,它自然受到上述答案的启发。基本上,在短暂延迟(此处为50ms)之后,用户结束手势后,检查getScrollY()是否仍在更改。

public class ScrollViewWithOnStopListener extends ScrollView {

    OnScrollStopListener listener;

    public interface OnScrollStopListener {
        void onScrollStopped(int y);
    }

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

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

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_UP:
                checkIfScrollStopped();
        }

        return super.onTouchEvent(ev);
    }

    int initialY = 0;

    private void checkIfScrollStopped() {
        initialY = getScrollY();
        this.postDelayed(new Runnable() {
            @Override
            public void run() {
                int updatedY = getScrollY();
                if (updatedY == initialY) {
                    //we've stopped
                    if (listener != null) {
                        listener.onScrollStopped(getScrollY());
                    }
                } else {
                    initialY = updatedY;
                    checkIfScrollStopped();
                }
            }
        }, 50);
    }

    public void setOnScrollStoppedListener(OnScrollStopListener yListener) {
        listener = yListener;
    }
}

5

对于这个问题,我的方法是使用计时器检查以下两个“事件”。

1)onScrollChanged()不再被调用

2)用户的手指从滚动视图中抬起

public class CustomScrollView extends HorizontalScrollView {

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

Timer ntimer = new Timer();
MotionEvent event;

@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) 
{
    checkAgain();
    super.onScrollChanged(l, t, oldl, oldt);
}

public void checkAgain(){
    try{
        ntimer.cancel();
        ntimer.purge();
    }
    catch(Exception e){}
    ntimer = new Timer();
    ntimer.schedule(new TimerTask() {

        @Override
        public void run() {

            if(event.getAction() == MotionEvent.ACTION_UP){
                // ScrollView Stopped Scrolling and Finger is not on the ScrollView
            }
            else{
                // ScrollView Stopped Scrolling But Finger is still on the ScrollView
                checkAgain();
            }
        }
    },100);

}

@Override
public boolean onTouchEvent(MotionEvent event) {
    this.event = event; 
    return super.onTouchEvent(event);
    }
}

3

我的解决方案是Lin Yu Cheng出色解决方案的变体,并且还可以检测滚动开始和停止的时间。

步骤1.定义Horizo​​ntalScrollView和OnScrollChangedListener:

CustomHorizontalScrollView scrollView = (CustomHorizontalScrollView) findViewById(R.id.horizontalScrollView);

horizontalScrollListener = new CustomHorizontalScrollView.OnScrollChangedListener() {
    @Override
    public void onScrollStart() {
        // Scrolling has started. Insert your code here...
    }

    @Override
    public void onScrollEnd() {
         // Scrolling has stopped. Insert your code here...
    }
};

scrollView.setOnScrollChangedListener(horizontalScrollListener);

步骤2.添加CustomHorizo​​ntalScrollView类:

public class CustomHorizontalScrollView extends HorizontalScrollView {
    public interface OnScrollChangedListener {
        // Developer must implement these methods.
        void onScrollStart();
        void onScrollEnd();
    }

    private long lastScrollUpdate = -1;
    private int scrollTaskInterval = 100;
    private Runnable mScrollingRunnable;
    public OnScrollChangedListener mOnScrollListener;

    public CustomHorizontalScrollView(Context context) {
        this(context, null, 0);
        init(context);
    }

    public CustomHorizontalScrollView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
        init(context);
    }

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

    private void init(Context context) {
        // Check for scrolling every scrollTaskInterval milliseconds
        mScrollingRunnable = new Runnable() {
            public void run() {
                if ((System.currentTimeMillis() - lastScrollUpdate) > scrollTaskInterval) {
                    // Scrolling has stopped.
                    lastScrollUpdate = -1;
                    //CustomHorizontalScrollView.this.onScrollEnd();
                    mOnScrollListener.onScrollEnd();
                } else {
                    // Still scrolling - Check again in scrollTaskInterval milliseconds...
                    postDelayed(this, scrollTaskInterval);
                }
            }
        };
    }

    public void setOnScrollChangedListener(OnScrollChangedListener onScrollChangedListener) {
        this.mOnScrollListener = onScrollChangedListener;
    }

    public void setScrollTaskInterval(int scrollTaskInterval) {
        this.scrollTaskInterval = scrollTaskInterval;
    }

    //void onScrollStart() {
    //    System.out.println("Scroll started...");
    //}

    //void onScrollEnd() {
    //    System.out.println("Scroll ended...");
    //}

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        if (mOnScrollListener != null) {
            if (lastScrollUpdate == -1) {
                //CustomHorizontalScrollView.this.onScrollStart();
                mOnScrollListener.onScrollStart();
                postDelayed(mScrollingRunnable, scrollTaskInterval);
            }

            lastScrollUpdate = System.currentTimeMillis();
        }
    }
}

2

尝试在StackOverflow上查看此问题-它与您的问题并不完全相同,但是可以让您了解如何管理的滚动事件ScrollView

基本上,您需要CustomScrollView通过扩展ScrollView和覆盖来创建自己的onScrollChanged(int x, int y, int oldx, int oldy)。然后,您需要在布局文件中引用它,而不是ScrollView像这样的标准文件中引用com.mypackage.CustomScrollView


这个onScrollChanged()实际上是我目前使用的。不过谢谢
user1053691 2011年

2

对于您所描述的简单情况,您可能可以在自定义滚动视图中使用替代的fling方法。每当用户从屏幕上举起手指时,都会调用Fling方法以执行“减速”。

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

  1. ScrollView的子类。

    public class MyScrollView extends ScrollView { 
    
        private Scroller scroller;  
        private Runnable scrollerTask; 
    
        //...
    
        public MyScrollView(Context context, AttributeSet attrs) {
            super(context, attrs);
    
            scroller = new Scroller(getContext()); //or OverScroller for 3.0+
            scrollerTask = new Runnable() {
                @Override
                public void run() {
                    scroller.computeScrollOffset();
                    scrollTo(0, scroller.getCurrY());
    
                    if (!scroller.isFinished()) {
                        MyScrollView.this.post(this);
                    } else {
                        //deceleration ends here, do your code
                    }
                }
            };
            //...
        }
    }
    
  2. 子类fling方法,请勿调用超类实现。

    @Override  
    public void fling(int velocityY) {  
        scroller.fling(getScrollX(), getScrollY(), 0, velocityY, 0, 0, 0, container.getHeight());
        post(scrollerTask);  
    
        //add any extra functions you need from android source code:
        //show scroll bars
        //change focus
        //etc.
    }
    
  3. 如果用户在举起手指之前停止滚动(velocityY == 0),则不会触发滑动。如果您也想拦截此类事件,请重写onTouchEvent。

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        boolean eventConsumed = super.onTouchEvent(ev);
        if (eventConsumed && ev.getAction() == MotionEvent.ACTION_UP) {
            if (scroller.isFinished()) {
                //do your code
            }
        }
        return eventConsumed;
    }
    

注意尽管这可行,但是覆盖清除方法可能不是一个好主意。它是公共的,但它几乎不能为子类设计。现在,它执行3件事-它启动私有mScroller的清除,处理可能的焦点更改并显示滚动条。这可能会在未来的android版本中更改。例如,私有mScroller实例在2.3和3.0之间将其类从Scroller更改为OvershootScroller。您必须牢记所有这些小的差异。无论如何,要做好应对未来不可预见的后果的准备。


第二步(2.)中的container.getHeight()是什么?
Mitul Varmora '16

1
container是scrollView内部的视图。由于scrollView只能包含1个孩子,因此可以将容器替换为getChildAt(0)。
Alexey

2

这里有一些很好的答案,但是我的代码无需扩展ScrollView类就可以检测滚动何时停止。每个视图实例都可以调用getViewTreeObserver()。当持有ViewTreeObserver的此实例时,可以使用函数addOnScrollChangedListener()添加一个OnScrollChangedListener。

声明以下内容:

private ScrollView scrollListener;
private volatile long milesec;

private Handler scrollStopDetector;
private Thread scrollcalled = new Thread() {

    @Override
    public void run() { 
        if (System.currentTimeMillis() - milesec > 200) {
            //scroll stopped - put your code here
        }
    }
}; 

并在您的onCreate(或其他位置)中添加:

    scrollListener = (ScrollView) findViewById(R.id.scroll);

    scrollListener.getViewTreeObserver().addOnScrollChangedListener(new OnScrollChangedListener() {

        @Override
        public void onScrollChanged() {
            milesec = System.currentTimeMillis();
            scrollStopDetector.postDelayed(scrollcalled, 200);
        }
    });

您可能希望在两次检查之间花费更长或更长时间,但是在滚动时,此列表器的调用速度非常快,因此它会非常快地工作。


在这种情况下,我还没有尝试过,但是根据我的经验,我猜测onScrollChanged中postDelayed的重复和相互调用会导致内存泄漏。
奥利弗·豪斯勒

2

这是我的解决方案,其中包括滚动跟踪和滚动结束:

public class ObservableHorizontalScrollView extends HorizontalScrollView {
    public interface OnScrollListener {
        public void onScrollChanged(ObservableHorizontalScrollView scrollView, int x, int y, int oldX, int oldY);
        public void onEndScroll(ObservableHorizontalScrollView scrollView);
    }

    private boolean mIsScrolling;
    private boolean mIsTouching;
    private Runnable mScrollingRunnable;
    private OnScrollListener mOnScrollListener;

    public ObservableHorizontalScrollView(Context context) {
        this(context, null, 0);
    }

    public ObservableHorizontalScrollView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

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

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        int action = ev.getAction();

        if (action == MotionEvent.ACTION_MOVE) {
            mIsTouching = true;
            mIsScrolling = true;
        } else if (action == MotionEvent.ACTION_UP) {
            if (mIsTouching && !mIsScrolling) {
                if (mOnScrollListener != null) {
                    mOnScrollListener.onEndScroll(this);
                }
            }

            mIsTouching = false;
        }

        return super.onTouchEvent(ev);
    }

    @Override
    protected void onScrollChanged(int x, int y, int oldX, int oldY) {
        super.onScrollChanged(x, y, oldX, oldY);

        if (Math.abs(oldX - x) > 0) {
            if (mScrollingRunnable != null) {
                removeCallbacks(mScrollingRunnable);
            }

            mScrollingRunnable = new Runnable() {
                public void run() {
                    if (mIsScrolling && !mIsTouching) {
                        if (mOnScrollListener != null) {
                            mOnScrollListener.onEndScroll(ObservableHorizontalScrollView.this);
                        }
                    }

                    mIsScrolling = false;
                    mScrollingRunnable = null;
                }
            };

            postDelayed(mScrollingRunnable, 200);
        }

        if (mOnScrollListener != null) {
            mOnScrollListener.onScrollChanged(this, x, y, oldX, oldY);
        }
    }

    public OnScrollListener getOnScrollListener() {
        return mOnScrollListener;
    }

    public void setOnScrollListener(OnScrollListener mOnEndScrollListener) {
        this.mOnScrollListener = mOnEndScrollListener;
    }

}

2

我认为这已经过去了。AFAIK,您无法轻松检测到。我的建议是您看一下ScrollView.java(这就是我们在Android land中的工作方式:)),并弄清楚如何扩展该类以提供所需的功能。这是我首先要尝试的:

 @Override
 protected void onScrollChanged(int l, int t, int oldl, int oldt) {
     if (mScroller.isFinished()) {
         // do something, for example call a listener
     }
 }

很好,我没有注意到isFinished方法!
Jordi Coscolla

3
谢谢。如何访问此isFinished()方法?我看了看ScrollView.java文件,mScroller是私有的,我看不出有什么方法可以访问它。
user1053691 2011年

嗯,的确如此。我看起来不够近。这就是为什么我说我会首先尝试的原因:)。您可以做其他事情,例如对onScrollChanged,的跟踪调用scrollTo或任何其他与滚动相关的方法。另外,您也可以复制整个ScrollView代码,然后将该字段设置为protected。不过,我不建议这样做。
菲利克斯(Felix)

1
通过反射访问mScroller。也不起作用,每次滚动视图到达您的手指位置时都会触发isFinished(),这几乎是连续的。当两个用户都松开手指并且滚动条停止滚动时,将触发滚动停止事件。
amik

20
这个答案看起来确实很有希望,但是由于它已经死胡同了,也许应该删除它?
spaaarky21

2

这是一个旧线程,但是我想添加一个较短的解决方案:

 buttonsScrollView.setOnScrollChangeListener { v, scrollX, scrollY, oldScrollX, oldScrollY ->

            handler.removeCallbacksAndMessages(null)

            handler.postDelayed({
                  //YOUR CODE TO BE EXECUTED HERE
                },1000)
        }

自然会有1000毫秒的延迟。如果需要,请进行调整。


1

我对ZeroG的答案做了一些改进。主要是取消多余的任务调用,并将整个事情实现为私有的OnTouchListener,因此所有滚动检测代码都将放在一个位置。

将以下代码粘贴到您自己的ScrollView实现中:

private class ScrollFinishHandler implements OnTouchListener
{
        private static final int SCROLL_TASK_INTERVAL = 100;

        private Runnable    mScrollerTask;
        private int         mInitialPosition = 0;

        public ScrollFinishHandler()
        {
            mScrollerTask = new Runnable() {

                public void run() {

                    int newPosition = getScrollY();
                    if(mInitialPosition - newPosition == 0)
                    {//has stopped

                       onScrollStopped(); // Implement this on your main ScrollView class
                    }else{
                        mInitialPosition = getScrollY();
                        ExpandingLinearLayout.this.postDelayed(mScrollerTask, SCROLL_TASK_INTERVAL);
                    }
                }
            };
        }

        @Override
        public boolean onTouch(View v, MotionEvent event) 
        {
            if (event.getAction() == MotionEvent.ACTION_UP) 
            {

                startScrollerTask();
            }
            else
            {
                stopScrollerTask();
            }

            return false;
        }

}

然后在您的ScrollView实现中:

setOnTouchListener( new ScrollFinishHandler() );

-1
        this.getListView().setOnScrollListener(new OnScrollListener(){
        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {}

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem,
            int visibleItemCount, int totalItemCount) {
                     if( firstVisibleItem + visibleItemCount >= totalItemCount ) 
                              // Last item is shown...

            }

希望摘要帮助:)


不幸的是,我使用的是ScrollView,而不是ListView。不过谢谢
user1053691 2011年

1
你好?ScrollView不是ListView。
凯文·帕克
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.