☰
动画生命周期
2026/10/23 2:55:30 网站建设 项目流程

WPF动画生命周期

动画会暂时覆盖属性的值,但不会自动修改属性的基础值。

① 动画开始前:属性有自己的基础值

<Button x:Name="btn" Width="100" Height="50" Content="按钮"/>

此时:

项目值
Width 的基础值100
界面实际使用的宽度100

这里的“基础值”,可以先理解为:不考虑动画时,这个属性应该使用的值。本例中,就是 XAML 设置的 100。


② 动画运行中:动画值暂时覆盖基础值

启动一个让宽度从 100 变成 300 的动画:

DoubleAnimation animation = new DoubleAnimation { From = 100, To = 300, Duration = TimeSpan.FromSeconds(2) }; btn.BeginAnimation( FrameworkElement.WidthProperty, animation);

假设动画执行到一半:

项目值
Width 的基础值仍然是 100
当前动画值约 200
界面实际使用的宽度约 200

按钮变宽了,但原本设置的 100 并没有被动画改成 200。

你可以把它想成:基础值还在下面,动画临时提供了一个优先使用的值。


③ 动画播放完:默认继续保持终点值

2 秒后,按钮宽度变为 300。

你可能以为:

动画已经结束,那么它应该不再影响按钮了。

但是默认情况下,动画的:

FillBehavior = FillBehavior.HoldEnd;

HoldEnd表示:播放完成后,继续保持动画的最终效果。

因此:

项目值
Width 的基础值100
动画保持的值300
界面实际使用的宽度300

这里要区分两件事:

  • 播放完成:属性不再从 100 逐渐变到 300。
  • 停止影响属性:属性不再使用动画提供的值。

播放完成,不代表动画已经停止影响属性。

这种现象描述为动画结束后仍保持作用。更严格地说,默认情况下此时进入的是填充阶段(Filling),已经不是正在变化的活动阶段(Active)。

④ 为什么动画结束后,重新赋值“没有效果”?

假设动画播放结束后执行:

btn.Width = 150;

按钮可能仍然显示为 300。

不是这句代码没执行,而是现在变成了:

项目值
Width 的基础值已经改成 150
动画保持的值仍然是 300
界面实际使用的宽度300

基础值改了,但动画值仍然优先。

这就是这一节最容易遇到的问题。

⑤ 解决办法一:结束后恢复基础值

设置:

animation.FillBehavior = FillBehavior.Stop;

完整写法:

DoubleAnimation animation = new DoubleAnimation { From = 100, To = 300, Duration = TimeSpan.FromSeconds(2), FillBehavior = FillBehavior.Stop }; btn.BeginAnimation( FrameworkElement.WidthProperty, animation);

假设基础值一直是 100,效果就是:

阶段实际宽度
开始前100
播放中从 100 逐渐变到 300
播放完成后恢复为 100

注意:恢复的是当时的基础值。如果你在动画过程中把基础值改成了 150,那么动画结束后就会显示 150。

另外,FillBehavior.Stop是让动画结束后不再提供属性值,不等同于把动画对象删除或立刻回收内存。

⑥ 解决办法二:主动移除属性上的动画

通过下面的代码,移除宽度属性上的动画影响:

btn.BeginAnimation( FrameworkElement.WidthProperty, null);

这里的null表示不再给这个属性应用动画。

例如:

// 移除动画,恢复使用基础值 btn.BeginAnimation( FrameworkElement.WidthProperty, null); // 正常设置宽度 btn.Width = 150;

这次按钮就会显示为 150。

注意:它移除的是Width 属性上的动画,不是按钮上的所有动画。

⑦ 解决办法三:播放结束后保留最终宽度,同时移除动画

实际开发中,你可能希望:

按钮变宽到 300 后就保持 300,并且以后还能正常修改 Width。

可以在Completed事件中处理:

private void btn_Click(object sender, RoutedEventArgs e) { DoubleAnimation animation = new DoubleAnimation { From = 100, To = 300, Duration = TimeSpan.FromSeconds(2) }; animation.Completed += (s, args) => { // 1. 先记住动画作用下的当前宽度 double currentWidth = btn.Width; // 2. 移除动画 btn.BeginAnimation( FrameworkElement.WidthProperty, null); // 3. 把刚才的宽度设置为基础值 btn.Width = currentWidth; }; btn.BeginAnimation( FrameworkElement.WidthProperty, animation); }

顺序很重要:

  1. 先记录当前宽度 300。
  2. 再移除动画。
  3. 再赋值,让基础值也变为 300。

这样,动画移除后,按钮依然保持 300。以后再执行:

btn.Width = 150;

就可以正常变成 150。

这里的Completed表示动画完成了活动期,并不表示动画已经自动移除。上述例子使用默认的HoldEnd,所以能在事件中读取到保持的最终值。

⑧ 书里另外两种方式,应该怎样理解?

书中还提到“回到原值”的动画,以及:

animation.AutoReverse = true;

AutoReverse的效果是:

从 100 变到 300,再从 300 变回 100。

但要注意:反向播放回到 100,不代表动画已被移除。如果仍使用默认的HoldEnd,它还可能保持反向播放结束时的值。

因此,当你的目的是“动画结束后,让普通赋值恢复正常”,最直接的办法是:

你的需求做法
播放后恢复基础值FillBehavior.Stop
立即取消动画影响BeginAnimation(属性, null)
播放后保留最终值,并恢复正常赋值Completed中记录当前值、移除动画、再赋值

记住这一节的核心关系:基础值一直存在;动画可以覆盖它;动画播放完毕后,是否继续覆盖,由结束行为和移除操作决定。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询