【问题标题】:How to synchronize two scrollview in Android?如何在Android中同步两个滚动视图?
【发布时间】:2016-07-29 18:48:31
【问题描述】:

我有两个水平的scrollview,并希望它们始终保持在相同的位置/距离。如果用户滚动一个,则需要以编程方式滚动另一个。挑战在于,将发生无限循环。一个人会举起另一个人,另一个人会先举起。如何设置状态,指示用户启动的滚动仍在进行中?所以其他scrollview不应该执行程序化滚动。

其中一个是HorizontalScrollView,另一个是RecyclerView

尝试了以下解决方案,但没有任何成功:

horizontalScrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
        @Override
        public void onScrollChanged() {

            if (programmaticScrollEnable) {
                programmaticScrollEnable = false;
                // do programmatic scrolling here
                programmaticScrollEnable = true;
            }
        }
    });        

试图在onScrollStateChanged 方法中改变状态:

@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
    super.onScrollStateChanged(recyclerView, newState);

    /*if (newState == RecyclerView.SCROLL_STATE_IDLE) {
        MainActivity.programmaticScrollEnable = true;
    }*/
}

【问题讨论】:

    标签: android scroll scrollview android-scrollview horizontal-scrolling


    【解决方案1】:

    试试这个...

    horizontalScrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
    
        @Override
        public void onScrollChanged() {
    
       recyclerView.scrollTo(horizontalScrollView.scrollTo(horizontalScrollView.getScrollX(), 0);
    
        }
    });
    

    【讨论】:

    【解决方案2】:

    挑战在于,会发生无限循环。

    您可以通过在OnTouchListener 中注册最后一次触摸的ScrolledView 来避免无限循环。这触动了ScrollView 不得以编程方式滚动;但其他应该是。

    这可以通过为每个ScrollView 设置一个标签来跟踪,并在滚动事件期间比较该标签。

    如果您是 API 级别 23 (Android M),您可以注册View.OnScrollChangeListener。对于低于此的 API,您可以注册ViewTreeObserver.OnScrollChangedListener。但后者占用大量资源;所以你需要处理它。

    对于 API 级别 23+

    // Tracking last touched SV
    private var touchedSVTag = -1
    
    // list of ScrollViews
    val svs = arrayListOf(scrollview1, scrollview2)
    
    val scrollListener =
        View.OnScrollChangeListener { view, scrollX, _, _, _ ->
    
            val currentSVTag = view!!.tag as Int
    
            if (currentSVTag == touchedSVTag) {
                for (svTag in 0 until svs.size) 
                    if (svTag != currentSVTag) 
                        svs[svTag].scrollTo(scrollX, 0)
            }
        }
    
    val itemTouchListener = View.OnTouchListener { sv, _ ->
        val svTag = sv.tag as Int
    
        if (touchedSVTag != -1 && touchedSVTag != svTag) {
            // stop scrollView in the middle of the scroll
            svs[touchedSVTag].fling(0)
        }
    
        touchedSVTag = svTag
        false
    }
    
    for (i in 0 until svs.size) {
        val sv = svs[i]
        sv.tag = i
        sv.setOnScrollChangeListener(scrollListener)
        sv.setOnTouchListener(itemTouchListener)
    }
    

    对于低于 23 的 API 级别:

    // Tracking last touched SV
    private var touchedSVTag = -1
    
    // list of ScrollViews
    val svs = arrayListOf(scrollview1, scrollview2)
    
    val scrollListener = {
        val scrolledSV = svs[touchedSVTag]
        for (svTag in 0 until svs.size) 
            if (svTag != touchedSVTag)
                svs[svTag].scrollTo(scrolledSV.scrollX, 0)
    }
    
    val itemTouchListener = View.OnTouchListener { sv, _ ->
        val svTag = sv.tag as Int
    
        if (touchedSVTag != -1 && touchedSVTag != svTag) {
            // stop scrollView in the middle of the scroll
            svs[touchedSVTag].fling(0)
        }
    
        touchedSVTag = svTag
        false
    }
    
    for (i in 0 until svs.size) {
        val sv = svs[i]
        sv.tag = i
        sv.viewTreeObserver.addOnScrollChangedListener(scrollListener)
        sv.setOnTouchListener(itemTouchListener)
    }
    

    【讨论】:

      猜你喜欢
      • 2011-12-13
      • 1970-01-01
      • 1970-01-01
      • 2016-01-18
      • 2017-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多