以编程方式animation(平滑)ScrollViewer

有没有办法在Windows Phone 8.1 Runtime中平滑地设置ScrollViewer的垂直偏移?

我已经尝试使用ScrollViewer.ChangeView()方法,无论是否将disableAnimation参数设置为true或false,垂直偏移的更改都不会生成animation。

例如: myScrollViewer.ChangeView(null, myScrollViewer.VerticalOffset + p, null, false); 偏移量被改变而没有animation。

我也尝试使用垂直偏移调解器:

 /// <summary> /// Mediator that forwards Offset property changes on to a ScrollViewer /// instance to enable the animation of Horizontal/VerticalOffset. /// </summary> public sealed class ScrollViewerOffsetMediator : FrameworkElement { /// <summary> /// ScrollViewer instance to forward Offset changes on to. /// </summary> public ScrollViewer ScrollViewer { get { return (ScrollViewer)GetValue(ScrollViewerProperty); } set { SetValue(ScrollViewerProperty, value); } } public static readonly DependencyProperty ScrollViewerProperty = DependencyProperty.Register("ScrollViewer", typeof(ScrollViewer), typeof(ScrollViewerOffsetMediator), new PropertyMetadata(null, OnScrollViewerChanged)); private static void OnScrollViewerChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) { var mediator = (ScrollViewerOffsetMediator)o; var scrollViewer = (ScrollViewer)(e.NewValue); if (null != scrollViewer) { scrollViewer.ScrollToVerticalOffset(mediator.VerticalOffset); } } /// <summary> /// VerticalOffset property to forward to the ScrollViewer. /// </summary> public double VerticalOffset { get { return (double)GetValue(VerticalOffsetProperty); } set { SetValue(VerticalOffsetProperty, value); } } public static readonly DependencyProperty VerticalOffsetProperty = DependencyProperty.Register("VerticalOffset", typeof(double), typeof(ScrollViewerOffsetMediator), new PropertyMetadata(0.0, OnVerticalOffsetChanged)); public static void OnVerticalOffsetChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) { var mediator = (ScrollViewerOffsetMediator)o; if (null != mediator.ScrollViewer) { mediator.ScrollViewer.ScrollToVerticalOffset((double)(e.NewValue)); } } /// <summary> /// Multiplier for ScrollableHeight property to forward to the ScrollViewer. /// </summary> /// <remarks> /// 0.0 means "scrolled to top"; 1.0 means "scrolled to bottom". /// </remarks> public double ScrollableHeightMultiplier { get { return (double)GetValue(ScrollableHeightMultiplierProperty); } set { SetValue(ScrollableHeightMultiplierProperty, value); } } public static readonly DependencyProperty ScrollableHeightMultiplierProperty = DependencyProperty.Register("ScrollableHeightMultiplier", typeof(double), typeof(ScrollViewerOffsetMediator), new PropertyMetadata(0.0, OnScrollableHeightMultiplierChanged)); public static void OnScrollableHeightMultiplierChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) { var mediator = (ScrollViewerOffsetMediator)o; var scrollViewer = mediator.ScrollViewer; if (null != scrollViewer) { scrollViewer.ScrollToVerticalOffset((double)(e.NewValue) * scrollViewer.ScrollableHeight); } } } 

我可以用DoubleAnimationanimationVerticalOffset属性:

 Storyboard sb = new Storyboard(); DoubleAnimation da = new DoubleAnimation(); da.EnableDependentAnimation = true; da.From = Mediator.ScrollViewer.VerticalOffset; da.To = da.From + p; da.Duration = new Duration(TimeSpan.FromMilliseconds(300)); da.EasingFunction = new ExponentialEase() { EasingMode = EasingMode.EaseOut }; Storyboard.SetTarget(da, Mediator); Storyboard.SetTargetProperty(da, "(Mediator.VerticalOffset)"); sb.Children.Add(da); sb.Begin(); 

Mediator在XAML中声明。 但是这个animation在我的设备上并不stream畅(Lumia 930)。

无论数据虚拟化是否ChangeView ,您都应该使用ChangeView来滚动animation。

没有看到你的代码ChangeView不工作的地方,要猜测到底是怎么回事有些困难,但是有几件事情你可以尝试。

第一种方法是在调用ChangeView之前添加一个Task.Delay(1) ,只是为了给操作系统一些时间来完成其他并发的UI任务。

 await Task.Delay(1); scrollViewer.ChangeView(null, scrollViewer.ScrollableHeight, null, false); 

第二种方法有点复杂。 我注意到,当ListView有许多复杂的项目时,从第一个项目到最后一个(从ChangeView方法)的滚动animation根本不是很stream畅。

这是因为ListView首先需要通过数据虚拟化来实现/呈现许多项目,然后执行animation滚动。 恕我直言,不是很有效率。

我想到了这一点 – 首先,使用非animationListView.ScrollIntoView滚动到最后一个项目才能实现它。 然后,调用ChangeView将偏移量上移到ListViewActualHeight * 2的大小,禁用animation(根据应用程序的滚动体验,可以将其更改为任何大小)。 最后,再次调用ChangeView以回滚到最后,这次是animation。 这样做会带来更好的滚动体验,因为滚动距离只是ListViewActualHeight

请记住,当您要滚动的项目已经在用户界面上实现,你不想做任何事情。 您只需计算此项目与ScrollViewer顶部之间的距离,然后调用ChangeView滚动到该项目。

我已经把上面的逻辑包含在这个答案的更新2部分中(感谢这个问题,我意识到当虚拟化开启时我的初始答案不起作用:p)。 让我知道你怎么去。

我想这个问题已经在这里回答了:

在ScrollViewer上进行animation(平滑)滚动

还有WinRT XAML Toolki,它提供了“通过animation滚动ScrollViewer到指定偏移量的方法”:

http://winrtxamltoolkit.codeplex.com/

ScrollToVerticalOffset在较新版本的Windows 10(不再使用ScrollViewOffSetMediator扩展控件)中不推荐使用/废弃,而新的ChangeView方法实际上不能提供stream畅的或可控制的animation,因此需要新的解决scheme。 请在这里看到我的答案,它允许一个顺利地animation和缩放ScrollViewer及其内容到任何所需的位置,无论应用程序的最终用户有最初定位的滚动条的位置:

如何滚动到UWP中的元素