我写了一个小应用程序,显示彼此相邻的2个scrollViews。我需要同步2个scrollViews的滚动位置。为此,我扩展了ScrollView并且我覆盖onScrollChanged以在滚动发生时得到通知,然后同步2个scrollViews。
我的两个滚动视图显示了一堆蓝色视图。左侧scrollView有红色背景,右侧有绿色背景。
以下是左侧scrollView上滚动的情况:
=>同步没问题
以下是右侧scrollView上滚动的情况:
=>同步不好,有差距
(这两个截图都是在滚动视图'fling)中拍摄的
如何在两种情况下都有良好的同步?
我的Activity,我的scrollView和我的scrollView容器的代码是here。
答案 0 :(得分: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
放置在separator_view
的任意一侧。我发现无论你如何定位它们,ScrollView
具有红色背景(声明为第二个)的投掷总是导致“滞后”,而具有绿色背景的ScrollView
的投掷工作正常。
我还尝试通过将ScrollView
添加到代码来防止不必要的 @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);
}
}
:
Views
但它也没有帮助......
所以,我想,你最好找到另一种方法,不涉及重绘大量的ScrollView
,或只是接受“滞后”。
<强>解决方案:强>
该解决方案由OP本人提供,基于我对情况的分析:触摸事件可以从右ScrollView
(在XML中声明为第二个)转发到左ScrollView
。这样,假设左侧ScrollView
上的flings不会导致滞后,则所有触摸事件都被视为由第一个声明的{{1}}启动,并且避免滞后。
答案 1 :(得分:0)
我之前回答的道歉没有正确地研究你的问题。
正如我所说,我认为你可以在没有任何延迟的情况下正确同步2 ScrollView
。但是,您仍然可以使用单个视图。
这有点棘手,因为你也想把你的分裂分成具有权重属性的相等部分。
可以找到解决方案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>
然后,如果您要切换left
和right
视图重叠,请拨打以下电话:
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找到一个工作示例。