在ViewPager中同步片段滚动

Enr*_*man 2 android scrollview android-fragments android-viewpager

我试图复制像雅虎这样的东西!天气应用程序,但我很失落如何在ViewPager中同步所有相同高度的滚动视图.

我在Fragments中使用ScrollListener来设置背景的不透明度并更新其他片段

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

    @Override
    public void onScrollChanged() {
        if(scrollView.getScrollY() > 0 && scrollView.getScrollY() < 1200) {
            overlay.getBackground().setAlpha((scrollView.getScrollY()/4));

            if(isVisible()) {
                Activity parent = getActivity();
                if(parent != null && parent instanceof MainActivity) {
                    ((MainActivity)parent).updateHeight(scrollView.getScrollY());
                }
            }
        }
    }
};
Run Code Online (Sandbox Code Playgroud)

在MainActivity中我正在做这样的事情:

public void updateHeight(int scroll) {
    for(int i = 0; i<mPager.getChildCount(); i++) {
        View v = mPager.getChildAt(i);
        ScrollView scrollView = (ScrollView) v.findViewById(R.id.frag_scrollview);
        scrollView.setScrollY(scroll);
    }
}
Run Code Online (Sandbox Code Playgroud)

这"几乎"有效,但不是真的.

我试图修改代码以避免更新当前可见页面,但没有成功:

if(i != mPager.getCurrentItem()) {
    View v = mPager.getChildAt(i);
    ScrollView scrollView = (ScrollView) v.findViewById(R.id.frag_scrollview);
    scrollView.setScrollY(scroll);
}
Run Code Online (Sandbox Code Playgroud)

PS:我也非常不确定正确的模式,以便在ScrollView上获得更新.OnScrollChangedListener似乎可以工作,但它被称为很多次,所以我不确定它是否是正确的方法.

提前致谢.

Enr*_*man 6

更新:

我刚刚在gradle/maven上发布了这个解决方案(SynchronizedScrollView)!
它还有一些修复和差异,从最后发布,所以检查代码!

随意使用它并贡献!谢谢.:)


好的,我已经改变了应用程序的所有结构并修复了这部分,它比预期的要容易.

刚刚在几分钟内测试过,所以也许这有问题,但似乎工作得很好.我基本上创建了一个类来保持同步所有ScrollView的责任,ScrollViews只是在滚动时通知这个Synchronizer.

public class Synchronizer {

    private static Synchronizer instance;

    private List<Synchronizable> synchronizableList;

    private Synchronizer() {}

    public static Synchronizer getInstance() {
        if (instance == null)
            instance = new Synchronizer();
        return instance;
    }

    public void registerSynchronizable(Synchronizable synchronizable) {
        if(synchronizableList == null)
            synchronizableList = new ArrayList<>();

        synchronizableList.add(synchronizable);
    }

    public void update(Synchronizable sender, int update) {
        if(update < 0) update = 0;

        for(Synchronizable s : synchronizableList) {
            if(s != sender)
                s.onUpdate(update);
        }
    }

    public interface Synchronizable {
        public void onUpdate(int update);
    }
}
Run Code Online (Sandbox Code Playgroud)

并且ScrollView将实现该Synchronizable接口,并且它们将在创建时"注册"

public class MyScrollView extends ScrollView implements Synchronizer.Synchronizable {

    public MyScrollView(Context context) {
        super(context);
        init();
    }

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

    public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }   

    private void init() {
        // init your ScrollView with style and stuff and then register it

        Synchronizer.getInstance().registerSynchronizable(this);
    }

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

        // listen for "your" scrolls and notify the Synchronizer
        Synchronizer.getInstance().update(this, getScrollY());
    }

    @Override
    public void onUpdate(int update) {
        // listen for the scrolls of your "siblings" from the Synchronizer
        setScrollY(update);
    }
}
Run Code Online (Sandbox Code Playgroud)

希望这会有所帮助!