Scrollviews同步问题

时间:2015-06-02 12:14:39

标签: android scrollview

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

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

以下是左侧scrollView上滚动的情况:
scroll on left scrollView
=>同步没问题

以下是右侧scrollView上滚动的情况:
scroll on right scrollView
=>同步不好,有差距

(这两个截图都是在滚动视图'fling)中拍摄的

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

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

2 个答案:

答案 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>

然后,如果您要切换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找到一个工作示例。