【问题标题】:Android: Synchronized scrolling of two different viewsAndroid:两个不同视图的同步滚动
【发布时间】:2011-01-04 06:05:48
【问题描述】:

我有一个与两个同步滚动有关的棘手问题 不同的看法。 我制作了自己的自定义网格视图小部件,它具有“粘性”视图 left 和 top 表示只在一个方向上用网格。想一个 日历,顶部有时间,左侧有日期,以及时间 你水平滚动时间,日期视图应该保持不变, 当您垂直滚动日期时,时间视图应该 留在原地。

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

这按预期工作,只是有一点时间偏移 到两个不同的视图开始滚动和结束滚动的时间。它 当您认为可能执行了滚动时,这是有道理的 我想在 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 布局,如果有帮助的话

实际的网格,它是一个水平滚动视图包裹在一个垂直滚动视图中,并且网格项垂直添加到嵌套的线性布局中
>

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

【问题讨论】:

    标签: android gridview scroll scrollview


    【解决方案1】:

    首先,我认为你应该意识到这一点:ScrollView Inside ScrollView

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

    现在,谈谈你的问题。

    我和你描述的有类似的需求。我最终实现了一个自定义视图及其onDraw 方法。这部分是因为我画了一些不重要的东西,你可能不必这样做。

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

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

    更新:示例代码

    @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;
            }
    
        }
    

    【讨论】:

    • 感谢您的回答。您所指的帖子似乎讨论了滚动视图与列表视图的组合?我确实意识到滚动视图的嵌套可能不是最佳的,但它似乎是唯一不需要从头开始新的小部件的替代方案。在我考虑回答这个问题之前,我想知道这如何保证比我当前的解决方案更“同步”的滚动?我是否仍然需要一次滚动一个视图(网格、粘性视图),这可能会导致它们的滚动方式略有偏移?
    • 没有。我认为您的“同步”问题是因为当您获得有关滚动的信息时,该信息已经由一个视图处理,然后您命令其他视图像第一个视图一样滚动。这样,一个视图滚动,其他视图将在下一个循环中进行相应的滚动。使用我的方法,所有视图同时滚动。你不会有这个问题。
    【解决方案2】:

    不要使用smoothScrollTo,而是使用scrollTo。 smoothScrollTo 将动画从当前位置滚动到您想要的位置,因为您希望它们同步,您希望另一个滚动视图立即准确地位于另一个滚动视图所在的位置,scrollTo 就是这样做的。

    【讨论】:

      【解决方案3】:

      查看答案。为什么不使用 OnTouch 侦听器来处理它。当触摸事件为 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;
      }
      

      简单吧?

      不确定这是否正是您想要的。但是你能详细说明你想要达到的目标吗?不是在布局的意义上,而是在实践中……你的 UI 有什么意义?

      【讨论】:

      • 感谢您的回答。这可能是一个可行的解决方法,但似乎我现在也必须出于其他原因选择另一种实现。
      猜你喜欢
      • 1970-01-01
      • 2011-12-13
      • 1970-01-01
      • 2016-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-19
      相关资源
      最近更新 更多