Android中ScrollView的onScrollChanged被多次触发

8
我希望跟踪Scrollview上的ScrollY(不,我不能使用网格或列表)。
我正在使用ViewTreeObserver和onScrollChanges监听器。但是,它会多次触发。更糟糕的是:当它被调用3或4次时,滚动视图的scrollY为0,只有1次正确。然而,并不是每4次调用都是正确的,正确值被触发的时刻是随机的,我需要能够监听滚动位置0。
以下是我用来观察我的Scrollview的代码:
mScrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {

        @Override
        public void onScrollChanged() {
           Log.d("StupidScrollView", "Scroll positionY: " + mScrollView.getScrollY());
        }
    });

样本输出:

 D/StupidScrollView﹕ Scroll positionY: 0
 D/StupidScrollView﹕ Scroll positionY: 0
 D/StupidScrollView﹕ Scroll positionY: 0
 D/StupidScrollView﹕ Scroll positionY: 77

我必须提到,我正在使用ViewPager,我的片段包含一个需要观察的ScrollView。这听起来有点像与此相关的问题。


我面临着完全相同的情况,在我的自定义视图中,我有一个 ViewTreeObserver,并且我需要检查 getY() 的值,就像你的情况一样,每隔2到3个值是正确的。你能在这里指导我吗?谢谢。 - ShahrozKhan91
2个回答

8

我理解您的问题,我自己也曾经在滚动视图方面遇到过很多麻烦。这是我的解决方案,可以获取滚动视图中的滚动值(我为您添加了System.out)。

首先创建一个自定义类,继承ScrollView,并创建一个监听器,该监听器具有onScrollChanged方法,如下所示:

public class ProductDetailScrollView extends ScrollView {

    public interface OnScrollChangedListener {
        void onScrollChanged(ScrollView who, int l, int t, int oldl, int oldt);
    }

    private OnScrollChangedListener mOnScrollChangedListener;

    public void setOnScrollChangedListener(OnScrollChangedListener listener) {
        mOnScrollChangedListener = listener;
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        if (mOnScrollChangedListener != null) {
            mOnScrollChangedListener.onScrollChanged(this, l, t, oldl, oldt);
        }
    }

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

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

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

然后我在活动中创建了一个变量mOnScrollChangedListener,并将其设置为mScrollView的监听器:

private ProductDetailScrollView.OnScrollChangedListener mOnScrollChangedListener = new ProductDetailScrollView.OnScrollChangedListener() {
    public void onScrollChanged(ScrollView who, int l, int t, int oldl, int oldt) {

        System.out.println("Scrolled: " + t);

        //Parallax Effect on scroll
        if (t > 0) {
            final float newY = (t / 4.0f) * -1.0f;
            mProductImageContainer.setY(newY);
        } else {
            mProductImageContainer.setY(0.0f);
        }
    }
};

在我的情况下,“t”值代表垂直滚动的变化量,“l”是水平滚动,“oldl”和“oldt”是t和l的旧值,因此如果您需要知道它向上或向下滚动,可以使用if(oldt>t)等…

您可以像这样在scrollview中设置侦听器:

mScrollView.setOnScrollChangedListener(mOnScrollChangedListener);

@Angelo我遇到了完全相同的情况,在我的自定义视图中, 我有一个ViewTreeObserver,我需要检查getY()值,就像你的情况一样,每隔2或3个值是正确的。你能指导我吗? 谢谢。 - ShahrozKhan91
面对相同的问题。@ShahrozKhan91,你找到解决方案了吗? - maysi
@maysi,其实我只是想出了一种智能区分错误值和正确值的方法。 - ShahrozKhan91
@ShahrozKhan91,你能在这里发布你的解决方案吗?(我选择了listview来实现我的目的,因为我没有找到其他解决方案) - maysi
这对我来说是正确的解决方案。通过 ViewTree 添加 onScrollChangedListener 会给我混合了一堆看似不相关的值的正确滚动值。而子类化 ScrollView 并重写 onScrollChanged 方法将导致只触发出正确的滚动值! - Luke Bartolomeo
显示剩余3条评论

0
我曾经有过同样的问题。我将我的ScrollView替换为android.support.v4.widget.NestedScrollView
然后实现了NestedScrollView.OnScrollChangeListener
将监听器附加到我的NestedScrollView上。
现在我能够检测滚动变化了。 :)

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