2015-06-02 103 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上找到。