It seems like you hit a system limitation here - the system draws the views in order they are declared in your XML.
Therefore, when you fling the first declared ScrollView
, the second one gets updated but the first one is not updated again. When you fling the second one, however, the first one gets updated, then the second one gets updated, the change is reflected to the first one and it gets updated again.
I'm not sure that the above description is 100% accurate, but it is something along these lines.
I created a test case to check my hypothesis substituting the following for 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>
The above XML allows you to position both ScrollView
s on either sides of the separator_view
. I found out that no matter how you position them, a fling of the ScrollView
having red background (declared second) always causes the "lag", while a fling of the ScrollView
having green background works fine.
I also tried to prevent unnecessary updates of the ScrollView
s by adding this to their code:
@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);
}
... and this to Activity
's:
@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);
}
}
but it didn't help either...
So, I guess, you better find another approach which does not involve redrawing a whole lot of Views
, or just accept the "lag".
Solution:
This solution was provided by the OP himself, based on my analysis of the situation: touch events can be forwarded from the right ScrollView
(declared second in XML) to the left ScrollView
. This way, given that flings on the left ScrollView
do not cause lags, all touch events are treated as being initiated by the first declared ScrollView
and the lag is avoided.