一、先看看效果

凯旋门074网址 1

 

 

凯旋门074网址,二、原理

  就算功能非常粗略,然则网络的一对素材涉及的代码量特别可观,而且作用也不是很好看好,滚动的时候没有八个顺滑感。作者那边提供的源码一共120多行,就能够兑现上海教室的效能。

澳门凯旋门注册网址,  本质上大家假使接管ScrollViewer的轮转逻辑,并且把那么些逻辑替换到带有惯性的就可以,那么如何去接管呢?这里的重大是先屏蔽ScrollViewer的鼠标滚轮事件:

1 protected override void OnMouseWheel(MouseWheelEventArgs e)
2 {
3      e.Handled = true;
4 }

  这样一来,ScrollViewer就不会响应滚轮事件了,大家就在此处做小说。首先大家给那些ScrollViewer增添二日性质 IsEnableInertia ,用来调整是不是利用惯性,因为萝卜青菜各有所爱,不要想着强制全部人使用惯性,所以滚轮响应措施成为:

1 protected override void OnMouseWheel(MouseWheelEventArgs e)
2 {
3     if (!IsEnableInertia)
4     {
5         base.OnMouseWheel(e);
6         return;
7     }
8     e.Handled = true;
9 }    

ScrollViewer就不会响应滚轮事件了。  调整ScrollViewer的垂直滚动可以采纳 ScrollViewer.ScrollToVerticalOffset ,横向也同样。为何不能够用 VerticalOffset ?因为 VerticalOffset 在登记的时候就认证了是只读的:

1 private static readonly DependencyPropertyKey VerticalOffsetPropertyKey = DependencyProperty.RegisterReadOnly(nameof (VerticalOffset), typeof (double), typeof (ScrollViewer), (PropertyMetadata) new FrameworkPropertyMetadata((object) 0.0));
2 
3 public static readonly DependencyProperty VerticalOffsetProperty = ScrollViewer.VerticalOffsetPropertyKey.DependencyProperty;

ScrollViewer就不会响应滚轮事件了。  好了,接下去正是怎么在滚轮响应措施中完结惯性运动了,也等于一种减速运动。想到那儿,纯熟动画的博友非常的慢就掌握要用WPF的动画来落到实处了,暗许的卡通片都是贰回线性的,要有惯性成效就得用缓动函数,WPF的缓动函数有过多,而 CubicEase 特别适合用来做惯性,它的叙说图如下:

凯旋门074网址 2

ScrollViewer就不会响应滚轮事件了。ScrollViewer就不会响应滚轮事件了。  图中,横轴表示时间,纵轴表示运动距离。很明朗,中间的 EaseOut 情势正是咱们想要的。到了这里思路就清楚了,我们得以定义叁脾品质 CurrentVerticalOffset ,我们会在它上边完成动画,在它的值回调函数中调用 ScrollViewer.ScrollToVerticalOffset 来更新ScrollViewer的轮转地方。当然大家还须求二个私家字段 _ScrollViewer就不会响应滚轮事件了。totalVerticalOffset ,那么些是用来存放在ScrollViewer滚动目的地方的,滚轮向下滚动贰个单位我们就给它减去二回 e.Delta ,这里的e是滚轮响应措施传进来的参数,每一次给它赋值之后,就足以在 CurrentVerticalOffset 上实施动画了: BeginAnimation(CurrentVerticalOffsetProperty,
animation) ,须要特别注意的是,当一个借助属性用了动画改造后,再对其赋值则不会立见成效,原因是在三个动画片达到活动期的终极后,时间线暗许会保持其速度,直到其父级的活动期和保持期结束甘休。即使想在动画甘休后还足以手动改变依赖属性的值,则需求把 FillBehavior 设置为Stop。不过尔尔又会现出一个难题,一旦动画结束,这几个凭借属性又会回复开首值,所以还要给这几个动画订阅多个 Completed 事件,在事变响应措施中为 CurrentVerticalOffset 给定指标值,也正是 _totalVerticalOffset 。

  最终还恐怕有贰个争持难点,当手动拖动滑块或然当用上下文菜单改动滚动条地方时是无法用动画的,因为这时未有触发 OnMouseWheel ,没提到,那便是我们想要的,可是若是重复触发 OnMouseWheel 就有题目了,因为手动触发滚动的时候大家尚无给 CurrentVerticalOffset 和 _totalVerticalOffset 赋值( CurrentVerticalOffset 和 _totalVerticalOffset 只在 OnMouseWheel 中赋值),所以在用动画实施滚动操作前要先推断一下是或不是须求先更新一下它们俩,怎么样剖断?大家得以用叁个私有字段 _isRunning 来爱戴状态,每当动画开端就给它赋值true,停止则赋值false。那样一来,当 _isRunning = false 时,表达在调用 OnMouseWheel 前,动画已经甘休,用户大概早已手动改造了滚动条地点(也也许未有,但这并不影响),所以将在给前边俩弟兄更新一下值了。

  因为周围的惯性滚动以垂直方向居多,所以笔者从未写水平方向的逻辑,但也很轻便扩张,有意思味的博友能够下载源代码本人钻探。

 

三、源码

  本文所研究的控件源码已经在github开源:

 

相关文章