学到一个新词:Show me the money
这几天查资料,看到 CodeProject 上面的一篇 Post 《Advanced Custom TreeView Layout in WPF》,感谢作者,将 TreeView 重定义了布局,效果如上图所示,区别在于,没有展开和收拢的动画。正巧当下在浏览一些 Behavior 的内容,突发奇想写了一个 SizeChangedAnimationBehavior,可用来附加到大多数 FrameworkElement 上,实现如上的对 SizeChanged 应用动画的效果。
考虑使用一个通用的 SizeChangedAnimationBehavior 来实现对 FrameworkElement 的功能附加,好处是功能可热插拔,可通用等。
private void AssociatedObjectOnSizeChanged(object sender, SizeChangedEventArgs sizeChangedEventArgs)
{
// NewSize 属性,如果存在 double.NaN,则处于一次动画中,跳过此次 OnSizeChanged 处理
if (double.NaN.Equals(GetNewSize(AssociatedObject).Width) || double.NaN.Equals(GetNewSize(AssociatedObject).Height)) return;
Size oldSize = GetOldSize(AssociatedObject);
// 产生动画,注意,这里需要使用 ActualWidth/ActualHeight,并需要使用 FillBehavior.HoldEnd。这里的 Duration 可以扩展为一个附加属性,提高灵活性
DoubleAnimation wAnimation = new DoubleAnimation(oldSize.Width, AssociatedObject.ActualWidth, new Duration(TimeSpan.FromMilliseconds(150)), FillBehavior.HoldEnd);
DoubleAnimation hAnimation = new DoubleAnimation(oldSize.Height, AssociatedObject.ActualHeight, new Duration(TimeSpan.FromMilliseconds(150)), FillBehavior.HoldEnd);
// 动画结束时,需要解除属性的动画锁定,即调用 AssociatedObject.BeginAnimation(FrameworkElement.WidthProperty, null);
// 然后设置 NewSize 对应动画属性为 0(非 NaN),保证下次动画顺利执行
wAnimation.Completed += (o, args) =>
{
AssociatedObject.BeginAnimation(FrameworkElement.WidthProperty, null);
double height = GetNewSize(AssociatedObject).Height;
SetNewSize(AssociatedObject, new Size(0, height));
};
hAnimation.Completed += (o, args) =>
{
AssociatedObject.BeginAnimation(FrameworkElement.HeightProperty, null);
double width = GetNewSize(AssociatedObject).Width;
SetNewSize(AssociatedObject, new Size(width, 0));
};
// 设置 OldSize 为 ActualSize,为下次动画做准备
SetOldSize(AssociatedObject, new Size(AssociatedObject.ActualWidth, AssociatedObject.ActualHeight));
// 设置 NewSize 为 NaN,表明当前无 NewSize,处于动画执行中,执行结束后,NewSize 将恢复为 0
SetNewSize(AssociatedObject, new Size(double.NaN, double.NaN));
// 执行动画
AssociatedObject.BeginAnimation(FrameworkElement.WidthProperty, wAnimation);
AssociatedObject.BeginAnimation(FrameworkElement.HeightProperty, hAnimation);
}
代码比较简单,注意注释说明。
其中,OldSize/NewSize 是两个附加属性。
调用如下:
1)如下图,Button 的 Resize 操作,可实现动画效果;
2)如下图,Textbox 等实现 Height 的动画效果。此效果灵感(测试UI)来源于 《WPF TextBox with Animated Overflow》,感谢作者。
关于 Behavior,这里不细说,大佬们的博客太多。本文主要学习于周银辉大佬的 《从WPF的AttachProperty到Sliverlight3中的Behavior》,感谢作者,很棒的文章。
< 原文链接:https://blog.csdn.net/Liwuqingxin/article/details/81138164 转载请保留原文链接,小猿谢过~ >