Android:同步滚动两个不同的视图

时间:2011-01-04 06:05:48

标签: android gridview scroll scrollview

我有一个与同步滚动两个相关的棘手问题 不同意见。 我已经创建了自己的自定义网格视图窗口小部件,它具有“粘性”视图 左边和顶边只有一个方向与网格。想一想 日历,其中您有时间在顶部,日期在左边,以及何时 你水平滚动时间,日期视图应该保持, 当您在日期中垂直滚动时,时间视图应该 留下来。

网格本身是使用嵌套的水平滚动视图实现的 垂直滚动视图。电网运行良好,所以没问题。 由于粘滞视图不在实际网格中,因此我已覆盖 onScrollChanged在网格滚动视图中以编程方式调用 当用户滚动网格时滚动粘贴视图。

按预期工作,除了有一点时间偏移 当两个不同的视图开始滚动并结束滚动时。它 当你考虑滚动可能被执行时,这是有道理的 线性地在UI线程上我想..

所有视图都是滚动视图,我已启用平滑滚动 并使用smoothScrollTo等代替尝试改进这一点,但它是 尽管如此,同样的问题。问题特别明显 更大的屏幕,如三星Galaxy Tab,而它几乎没有 在中小屏幕设备上很明显。

任何帮助表示赞赏!如果有一个简单的解决方案,很棒..如果它意味着 新设计(符合上面的粘性视图用例),那就这样吧。

触发编程的代码。滚动,水平相同

@Override  
protected void onScrollChanged(int x, int y, int oldx, int oldy) {  
   mListener.onScrollY(y);  
   super.onScrollChanged(x, y, oldx, oldy);  
}  
// which leads to,  
// Handle vertical scroll  
public void onScrollY(final int y) {  
   mCurrentY = y;  
   mVerticalScroll.smoothScrollTo(0, y);  
}  

下面的XML布局,如果有任何帮助

实际网格,它是一个包含在垂直滚动视图中的水平滚动视图,网格项垂直添加在嵌套的linearlayout中     >

  < com.....VerticalScrollView  
    android:id="@+id/gridscroll" 
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent" 
    android:layout_below="@id/timescroll"
    android:layout_toRightOf="@id/vertscroll"  
    android:layout_alignTop="@id/vertscroll"  
    android:layout_marginLeft="2dp" android:scrollbars="none"  
    android:fadingEdge="none">   

    < com....HorizScrollView
    android:id="@+id/horizscroll"
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent"
    android:scrollbars="none"  
    android:fadingEdge="none">  

    < LinearLayout android:id="@+id/grid"  
      android:layout_width="fill_parent"  
      android:layout_height="fill_parent"  
      android:orientation="vertical">  

      < /LinearLayout>  

      < /com.....HorizScrollView>  

      < /com.....VerticalScrollView>  

水平粘滞视图

  

 < com.....GridTimeScrollView
    android:id="@+id/timescroller" 
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:scrollbars="none"
    android:fadingEdge="none">

    < LinearLayout android:id="@+id/timelist"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="horizontal" />
    < /com.....GridTimeScrollView>

垂直粘滞视图

  

< com....GridVertListScrollView
android:id="@+id/vertscroller"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scrollbars="none" 
android:fadingEdge="none">

< LinearLayout
android:id="@+id/vertitemlist"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" />
< /com.....GridVertListScrollView>

3 个答案:

答案 0 :(得分:6)

首先,我认为您应该注意这一点:ScrollView Inside ScrollView

简而言之:在scrollviews中使用滚动视图是一件坏事,会打破许多优化。

现在,问你的问题。

我对你所描述的内容有类似的需求。我最终实现了自定义视图及其onDraw方法。这部分是因为我画的东西不是微不足道的,你可能不必这样做。

无论如何,我相信你最好的选择是:

  1. 实现扩展相对布局的自定义视图
  2. 使用将成为可滚动组件的顶部,左侧和“主”视图创建此视图的布局
  3. 在此视图中添加OnGestureListener,并将活动中的触摸事件传递到自定义视图
  4. 当您的手势监听器检测到fling或滚动时,在每个滚动视图中调用scrollBy。执行此操作时,如果希望顶视图仅水平滚动,请将0作为垂直滚动距离。
  5. 为了实现平滑的移动动作,您需要创建scroller(在自定义视图中)。当手势监听器检测到fling事件时,请将卷轴设置为向上。然后,覆盖自定义视图的computeScroll()方法并更新每个子视图中的滚动。 检查此example以了解如何实施它。我道歉,我会尝试在可能的情况下发布一个更好的例子。 检查下面的代码...它更简单:)
  6. 更新示例代码

    @Override
        public void computeScroll() {
            if (scroller.computeScrollOffset()) {
                if (!scrolledLastFrame) {
                    lastX = scroller.getStartX();
                    lastY = scroller.getStartY();
                }
    
                int dx = scroller.getCurrX() - lastX;
                int dy = scroller.getCurrY() - lastY;
    
                lastX = scroller.getCurrX();
                lastY = scroller.getCurrY();
    
                doScroll(dx, dy);
                scrolledLastFrame = true;
            } else {
                scrolledLastFrame = false;
            }
    
        }
    

答案 1 :(得分:3)

不要使用smoothScrollTo,而是使用scrollTo。 smoothScrollTo会将滚动从当前位置设置为您想要的位置,因为您希望它们同步,您希望其他滚动视图立即与其他滚动视图完全相同,scrollTo会这样做。

答案 2 :(得分:2)

看看答案。你为什么不用OnTouch Listener来处理它。触摸事件为MOVE时,您可以拨打电话。

public void onScrollY(final int y) {  
   mCurrentY = y;  
   mVerticalScroll.smoothScrollTo(0, y);  
}  

在您的其他ScrollView上使用getVerticalScroll的值。这很简单。返回true,以便进一步处理TouchEvents。

这就是它的样子

@Override
public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_MOVE:
            lv2.onScrollY(lv.getScrollY());
            break;
        default:
            break;
    }
    return false;
}

简单吧?

不确定它是否正是您想要的。但是你能详细说明你想要实现的目标吗?不是在布局的意义上,而是在实践中......你的用户界面是什么意思?