【问题标题】:Making a Flex DataGrid scroll smoothly使 Flex DataGrid 平滑滚动
【发布时间】:2010-12-22 12:54:39
【问题描述】:

我注意到 DataGrid 的垂直滚动条的默认行为是一次滚动一行。当行都统一且小(例如,显示单行文本)时,这一切都很好,但是一旦您的行具有可变高度,就会变得非常丑陋。

我很好奇,有没有办法让 DataGrid 滚动“顺畅”?例如,有没有办法让 DataGrid 滚动一定数量的像素、文本行等,而不是一次滚动一行?

到目前为止,我想出的唯一解决方案是将 DataGrid 放在 Canvas 中,并让 Canvas 代替 DataGrid 进行滚动。但是,这种方法的问题在于,一旦 Canvas 滚动得足够远,DataGrid 标题就会滚动到屏幕外。理想情况下,我希望获得 Canvas 的平滑滚动特性,同时保持 DataGrid 标题可见。这可能吗?

【问题讨论】:

    标签: apache-flex actionscript-3 mxml


    【解决方案1】:

    ItemRenderer 在 Flex 3 中的工作方式使得平滑滚动难以实现。基本上,Flex 回收从列表顶部滚动的项目渲染器,作为用于列表底部新数据的显示对象。 Adobe 在 Flex 3 中对大多数列表组件的实现会在这些项目出现在屏幕上时创建并添加它们,而不仅仅是在屏幕之外,因此它们“弹出”并且平滑滚动不可用。我不确定为什么他们不能以类似的方式对当前滚动窗格上方或下方 +/- 一个位置的项目执行此操作,但他们没有,并且默认情况下我们坚持使用粘性滚动。

    确实存在变通方法,尽管您已经注意到(将数据网格放到画布中)否定了项目渲染器的显示对象保存意图并产生了性能成本。这将在 Flex 4 中为大多数基于列表的 Flex 组件修复,但不会立即为 DataGrid 修复。 DataGrid / AdvancedDataGrid 组件是由位于印度的一个独立团队维护的,上次我听说过,所以它往往比 SDK 的其余部分有点落后。

    我建议尝试类似于this implementation of a smooth-scrolling list by Alex Harui 的方法。我不确定它对 DataGrid 或 AdvancedDataGrid 的效果到底如何,但这是我能想到的让列表正确滚动的最直观的技术。

    【讨论】:

    • 非常翔实的答案,谢谢!虽然我理解为什么(重用 itemRenderers 非常方便!),但这目前无法完成,这太糟糕了。可悲的是,Alex 的示例对我不起作用,因为我的 DataGrid 确实具有可变的行高。我想我必须等待 Flex 的未来版本才能获得此功能。
    • 事实上,大多数平台都使用相同的技术来重用单元格,而不是为整个数据网格创建所有单元格。例如。 iPhone sdk 遵循相同的逻辑,内存中只有一定数量的单元格,足以填充当前显示的区域。然而,通过在屏幕上渲染几个额外的单元格并在我们滚动时将它们平滑地带到用户的视图中,平滑滚动效果很好。也希望尽快从 DataGrid 获得这种滚动手指交叉
    【解决方案2】:

    试试这个...它仍然基于上面提到的 Alex 的代码。他应该仍然是消除 snap-to-row 行为的一个很好的开始。原始来源: http://blogs.adobe.com/aharui/2008/03/smooth_scrolling_list.html

    Alex 的一些用于平滑垂直滚动的原始代码,但这不是我在使用 DataGrid 时遇到的问题。我需要的是平滑的水平滚动。我以非正统的方式使用 DataGrid 来分析我们的数据库输出的纯文本报告(在文档上提供视觉反馈的好方法)。下面的代码允许内容离开屏幕,并且用户可以在没有对齐列行为的情况下滚动。

    您可以调整它以使用相同的数学例程进行垂直滚动,然后它将使滚动成为可能并忽略对齐到行的行为。特别是切换 listContent.move 方法的使用来垂直移动内容,并使用您从垂直滚动条计算的舍入像素值的倒数(而不是我使用水平滚动条)。

    这个方法比上面链接中 Alex 的方法简单一些 - 代码少很多,所以尝试适应并看看它是如何工作的。

    override protected function scrollHandler(event:Event):void
            {           
                // Override the default scroll behavior to provide smooth horizontal scrolling and not the usual "snap-to-column" behavior
                var scrEvt:ScrollEvent = event as ScrollEvent;
                if(scrEvt.direction == ScrollEventDirection.HORIZONTAL) {
                    // Get individual components of a scroll bar for measuring and get a horizontal position to use
                    var scrDownArrow:DisplayObject = horizontalScrollBar.getChildAt(3);
                    var sctThumb:DisplayObject = horizontalScrollBar.getChildAt(2);     
                    // I replaced maxHorizontalScrollPosition in Alex's code with "1300" to fix my exact application. In other situations you may finding using some property or different value is more appropriate. Don't rely on my choice.
                    var hPos:Number = Math.round((sctThumb.y - scrDownArrow.height) / (scrDownArrow.y - sctThumb.height - scrDownArrow.height) * 1300);     
    
                    // Inverse the position to scroll the content to the left for large reports
                    listContent.move(hPos * -1, listContent.y);
                }
                // Go ahead and use the default handler for vertical scrolling
                else {
                    super.scrollHandler(event);
                }
            }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-19
      • 1970-01-01
      • 2010-12-26
      • 2012-08-06
      • 2018-12-30
      • 2011-02-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多