Android:两个不同视图的同步滚动 [英] Android: Synchronized scrolling of two different views

查看:21
本文介绍了Android:两个不同视图的同步滚动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a tricky problem related to synchronized scrolling of two different views. I've made my own custom grid view widget, which has "sticky" views to the left and top that only in one direction with the grid. Think of a calendar where you have times at the top, dates at the left, and when you scroll horizontally through time, the date view should stay put, and when you scroll vertically through the dates, the time view should stay put.

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

The grid itself is implemented using a nested horizontal scrollview in a vertical scrollview. The grid is working great, so no problem there. Since the sticky views are not in the actual grid, I have overriden onScrollChanged in the grid scrollviews and programatically call scrollTo on the sticky views when the user scrolls the grid.

这按预期工作,除了有轻微的时间偏移,因为当两个不同的视图开始滚动和结束滚动时.它当您认为可能会执行滚动时是有道理的我想在 UI 线程上线性地..

That works as expected, except that there is a slight time offset as to when the two different views start scrolling and ends scrolling. It makes sense when you consider that the scrolling likely is executed linearly on the UI thread I suppose..

所有视图都是滚动视图,并且我启用了平滑滚动并使用了 smoothScrollTo 等,而不是尝试改进这一点,但它是同样的问题.这个问题在更大的屏幕,例如三星 Galaxy Tab,而它几乎在中小屏幕设备上很明显.

All the views are scroll views, and I have enabled smooth scrolling and used smoothScrollTo, etc, instead to try to improve this, but it's the same problem nonetheless. The problem is especially noticeable on larger screens, such as the Samsung Galaxy Tab, whereas it's hardly noticeable on small-medium screen devices.

感谢任何帮助!如果有一个简单的修复,很好..如果这意味着新设计(满足上面的粘性视图用例),那就这样吧.

Any help is appreciated! If there is an easy fix, great..if it means new design (that meets the sticky view usecase above), then so be it.

触发程序的代码.滚动,水平相同

Code to trigger prog. scroll, same for horizontal

@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 布局,如果有帮助的话

XML layouts below, if that's of any help

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

The actual grid, which is a horizontal scroll view wrapped in a vertical scroll view and the grid items are added vertically in the nested 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>

推荐答案

首先,我想你应该意识到这一点:ScrollView 内部 ScrollView

First of all, I think you should be aware of this: ScrollView Inside ScrollView

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

现在,开始你的问题.

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

I've had a similar need to what you described. I ended up implementing a custom view and its onDraw method. This was in part because I was drawing something not trivial and you may not have to do it.

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

Anyway, I believe that your best option is:

  1. 实现扩展相对布局的自定义视图
  2. 使用将作为可滚动组件的顶部、左侧和主"视图创建此视图的布局
  3. 向该视图添加一个 OnGestureListener 并传递触摸活动中的事件进入自定义视图
  4. 当您的手势侦听器检测到滑动或滚动时,在每个滚动视图中调用 scrollBy.执行此操作时,如果您希望顶视图仅水平滚动,请将 0 作为垂直滚动距离传递.
  5. 为了实现平滑的投掷动作,您需要创建一个滚动条(在您的自定义视图中).当手势侦听器检测到投掷事件时,设置滚动条.然后,覆盖自定义视图的 computeScroll() 方法并更新每个子视图中的滚动.查看此示例 了解如何实施.抱歉,我会尽可能发布更好的示例. 检查下面的代码...它更简单:)
  1. Implement a custom view that extends relative layout
  2. create the layout of this view with the top, left and "main" views that will be the scrollable components
  3. add a OnGestureListener to this view and pass touch events in your activity into the custom view
  4. when your gesture listener detects a fling or a scroll, invoke scrollBy in each of the scrolling views. When you do this, if you want the top view to scroll horizontally only, pass 0 as the vertical scroll distance.
  5. In order to implement smooth fling movements, you need to create a scroller (in your custom view). When the gesture listener detects a fling event, set the scroller up. Then, override your custom view's computeScroll() method and update the scroll in each of child views. Check this example to know how to implement it. I apologize, I will try to post a better example when possible. Check my code below... it's simpler :)

更新:示例代码

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

    }

这篇关于Android:两个不同视图的同步滚动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆