2015-06-02 105 views
3

我写了一个小应用程序,显示两个相邻的scrollViews。我需要2个scrollViews的滚动位置进行同步。为此,我扩展了ScrollView,并且我覆盖了ScrollChanged以在滚动发生时得到通知,然后同步2个scrollViews。Scrollviews同步问题

我的两个滚动视图显示一堆蓝色视图。左侧scrollView有红色背景,右侧有绿色背景。

下面是一个滚动左侧滚动视图发生:
scroll on left scrollView
=>同步是正常

而且这里是一个滚动右边滚动视图发生:
scroll on right scrollView
= >同步不好,还有差距

(两个截图都是在滚动视图的一瞥中拍摄的)

如何在两种情况下都有很好的同步?

我的Activity,我的scrollView和我的scrollView容器的代码是here

+2

为什么你使用两个ScrollViews而不是一个? –

+0

我同意@Médéric为什么不使用1? – Budius

+1

因为在某些时候,我需要一个重叠另一个。 – MartinMoizard

回答

1

看起来你在这里遇到了一个系统限制 - 系统会在你的XML中声明它们。

因此,当你扔第一个宣布ScrollView,第二个得到更新,但第一个不会再更新。然而,当你扔第二个,第一个被更新,然后第二个被更新,这个更改被反映到第一个并且它被再次更新。

我不确定上面的描述是否100%准确,但它是沿着这些线。

我创建了一个测试案例来检查我的假设代替main.xml如下:

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:id="@+id/main_layout"> 


    <View android:id="@+id/separator_view" 
     android:layout_width="0dp" 
     android:layout_height="0dp" 
     android:layout_centerHorizontal="true" 
     android:visibility="invisible"/> 


    <com.example.www.syncscrollviewtesting_stackoverflow.ObservableScrollView 
     android:layout_width="0dp" 
     android:layout_height="match_parent" 
     android:layout_alignParentEnd="true" 
     android:layout_toEndOf="@id/separator_view" 
     android:background="@android:color/holo_green_light" 
     android:id="@+id/left_scrollview"> 
     <com.example.www.syncscrollviewtesting_stackoverflow.Container 
      android:layout_width="match_parent" 
      android:layout_height="100000dp" 
      android:minHeight="100000dp" 
      android:id="@+id/left_container"/> 

    </com.example.www.syncscrollviewtesting_stackoverflow.ObservableScrollView> 


    <com.example.www.syncscrollviewtesting_stackoverflow.ObservableScrollView 
     android:layout_width="0dp" 
     android:layout_height="match_parent" 
     android:layout_alignParentStart="true" 
     android:layout_toStartOf="@id/separator_view" 
     android:background="@android:color/holo_red_dark" 
     android:id="@+id/right_scrollview"> 
     <com.example.www.syncscrollviewtesting_stackoverflow.Container 
      android:layout_width="match_parent" 
      android:layout_height="100000dp" 
      android:minHeight="100000dp" 
      android:id="@+id/right_container"/> 
    </com.example.www.syncscrollviewtesting_stackoverflow.ObservableScrollView> 

</RelativeLayout> 

上述XML允许您同时ScrollView S于该separator_view的两侧定位。我发现无论你如何定位它们,一个具有红色背景的ScrollView(声明为第二个)总是会导致“滞后”,而具有绿色背景的ScrollView的投掷效果很好。

我也试图加入到了他们的代码,以防止ScrollView S的不必要的更新:

@Override 
    protected void onScrollChanged(int x, int y, int oldx, int oldy) { 
     super.onScrollChanged(x, y, oldx, oldy); 
     if (!mIsDisabled && scrollViewListener != null) { 
     scrollViewListener.onScrollChanged(this, x, y, oldx, oldy); 
     } 
    } 

    public void setDisabled(boolean isDisabled) { 
     mIsDisabled = isDisabled; 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent ev) { 
     if (mIsDisabled) 
     return false; // Ignore touch event when disabled 
     else 
     return super.onTouchEvent(ev); 
    } 

...这对Activity的:

@Override 
    public void onScrollChanged(ObservableScrollView scrollView, int x, int y, int oldx, int oldy) { 
     if (scrollView == mRightScrollView) { 
     mLeftScrollView.setDisabled(true); 
     mLeftScrollView.setScrollY(y); 
     mLeftScrollView.setDisabled(false); 
     } else { 
     mRightScrollView.setDisabled(true); 
     mRightScrollView.setScrollY(y); 
     mRightScrollView.setDisabled(false); 
     } 

    } 

,但它没“ t帮助...

所以,我想,你最好找到另一种方法,不涉及重绘一大堆Views,或只是接受“落后”。

解决方案: 该解决方案是由OP自己,根据我的情况分析提供:触摸事件可以从右边ScrollView(在XML声明秒)到左侧ScrollView转发。这样,考虑到左边ScrollView的fl do不会导致滞后,所有的触摸事件被视为由第一个声明的ScrollView开始,并且避免了滞后。

+0

子位置确实与具有同步问题的scrollView链接。作为一种解决方法,当在右侧scrollView上发生触摸时,我将其转发到左侧scrollView。这是一个黑客,但这是我发现保持2个scrollViews同步的唯一解决方案。 – MartinMoizard

+0

@MartinMoizard,我甚至没有想到这个简单的解决方案。它的简单巧妙!感谢分享 - 如果您不介意,我会将其添加到答案中。 – Vasiliy

0

对于我以前的答案道歉没有妥善研究你的问题。

正如我所说,我不认为你可以正确同步2 ScrollView,没有任何延迟。但是,您仍然可以使用单个视图。

这会变得有点棘手,因为您还想将拆分拆分成与weight属性相等的部分。可以找到here。对建立我已经想出了下面的代码:

<ScrollView 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 
    <RelativeLayout 
     android:orientation="horizontal" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content"> 
     <View 
      android:id="@+id/spacer" 
      android:layout_width="0dp" 
      android:layout_height="0dp" 
      android:layout_centerHorizontal="true"/> 
     <LinearLayout 
      android:id="@+id/left" 
      android:layout_alignRight="@id/spacer" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      android:orientation="vertical"> 
      ... 
     </LinearLayout> 
     <LinearLayout 
      android:id="@+id/right" 
      android:layout_alignLeft="@id/spacer" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      android:orientation="vertical"> 
      ... 
     </LinearLayout> 
    </RelativeLayout> 
</ScrollView> 

然后,当你想切换leftright重叠视通话这样的:

leftParams.addRule(RelativeLayout.ALIGN_RIGHT, 0); 
rightParams.addRule(RelativeLayout.ALIGN_LEFT, 0); 

leftParams.addRule(RelativeLayout.ALIGN_RIGHT, R.id.spacer); 
rightParams.addRule(RelativeLayout.ALIGN_LEFT, R.id.spacer); 

设置参数后,您需要重新绘制视图:

left.requestLayout(); 
right.requestLayout(); 

一个工作示例可以在this GitHub page上找到。