如何通过动画修改控件尺寸?需实现类iOS 3D Touch动画效果
UWP实现类似iOS 3D Touch的控件尺寸动画(单独修改宽高)
1. 直接通过Storyboard实现基础宽高动画
你可以用DoubleAnimation分别绑定控件的Width和Height属性,实现独立的尺寸变化,配合指针事件触发动画,模拟3D Touch的按压效果。
XAML示例
<Button x:Name="3DTouchBtn" Content="3D Touch Test" Width="200" Height="80" PointerPressed="Btn_PointerPressed" PointerReleased="Btn_PointerReleased"> <Button.Resources> <!-- 按压时的尺寸缩小动画 --> <Storyboard x:Name="PressAnimation"> <DoubleAnimation Storyboard.TargetName="3DTouchBtn" Storyboard.TargetProperty="Width" To="180" Duration="0:0:0.1" EasingFunction="{StaticResource CubicEase}" /> <DoubleAnimation Storyboard.TargetName="3DTouchBtn" Storyboard.TargetProperty="Height" To="70" Duration="0:0:0.1" EasingFunction="{StaticResource CubicEase}" /> </Storyboard> <!-- 释放时的尺寸恢复动画 --> <Storyboard x:Name="ReleaseAnimation"> <DoubleAnimation Storyboard.TargetName="3DTouchBtn" Storyboard.TargetProperty="Width" To="200" Duration="0:0:0.1" EasingFunction="{StaticResource CubicEase}" /> <DoubleAnimation Storyboard.TargetName="3DTouchBtn" Storyboard.TargetProperty="Height" To="80" Duration="0:0:0.1" EasingFunction="{StaticResource CubicEase}" /> </Storyboard> <CubicEase x:Key="CubicEase" EasingMode="EaseInOut" /> </Button.Resources> </Button>
后台代码
private void Btn_PointerPressed(object sender, PointerRoutedEventArgs e) { PressAnimation.Begin(); } private void Btn_PointerReleased(object sender, PointerRoutedEventArgs e) { ReleaseAnimation.Begin(); }
2. 自定义Behavior实现可绑定的复用动画
如果要把动画快速绑定到任意控件,避免重复写事件和Storyboard,可以自定义Behavior封装逻辑,直接在XAML中附加到控件上。
步骤1:创建自定义Behavior类
using Microsoft.Xaml.Interactivity; using Windows.UI.Xaml; using Windows.UI.Xaml.Media.Animation; public class 3DTouchSizeBehavior : Behavior<FrameworkElement> { // 定义依赖属性,用于设置按压后的目标宽高 public static readonly DependencyProperty PressedWidthProperty = DependencyProperty.Register(nameof(PressedWidth), typeof(double), typeof(3DTouchSizeBehavior), new PropertyMetadata(double.NaN)); public static readonly DependencyProperty PressedHeightProperty = DependencyProperty.Register(nameof(PressedHeight), typeof(double), typeof(3DTouchSizeBehavior), new PropertyMetadata(double.NaN)); public double PressedWidth { get => (double)GetValue(PressedWidthProperty); set => SetValue(PressedWidthProperty, value); } public double PressedHeight { get => (double)GetValue(PressedHeightProperty); set => SetValue(PressedHeightProperty, value); } private Storyboard _pressStoryboard; private Storyboard _releaseStoryboard; private double _originalWidth; private double _originalHeight; protected override void OnAttached() { base.OnAttached(); // 记录控件原始尺寸 _originalWidth = AssociatedObject.Width; _originalHeight = AssociatedObject.Height; // 创建按压、释放动画 _pressStoryboard = BuildSizeAnimation(PressedWidth, PressedHeight); _releaseStoryboard = BuildSizeAnimation(_originalWidth, _originalHeight); // 绑定指针事件,处理取消场景防止动画不复位 AssociatedObject.PointerPressed += OnPointerPressed; AssociatedObject.PointerReleased += OnPointerReleased; AssociatedObject.PointerCanceled += OnPointerReleased; } protected override void OnDetaching() { base.OnDetaching(); // 解绑事件避免内存泄漏 AssociatedObject.PointerPressed -= OnPointerPressed; AssociatedObject.PointerReleased -= OnPointerReleased; AssociatedObject.PointerCanceled -= OnPointerReleased; } private Storyboard BuildSizeAnimation(double targetWidth, double targetHeight) { var storyboard = new Storyboard(); var easing = new CubicEase { EasingMode = EasingMode.EaseInOut }; if (!double.IsNaN(targetWidth)) { var widthAnim = new DoubleAnimation { To = targetWidth, Duration = TimeSpan.FromMilliseconds(100), EasingFunction = easing }; Storyboard.SetTarget(widthAnim, AssociatedObject); Storyboard.SetTargetProperty(widthAnim, "Width"); storyboard.Children.Add(widthAnim); } if (!double.IsNaN(targetHeight)) { var heightAnim = new DoubleAnimation { To = targetHeight, Duration = TimeSpan.FromMilliseconds(100), EasingFunction = easing }; Storyboard.SetTarget(heightAnim, AssociatedObject); Storyboard.SetTargetProperty(heightAnim, "Height"); storyboard.Children.Add(heightAnim); } return storyboard; } private void OnPointerPressed(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e) { _pressStoryboard.Begin(); } private void OnPointerReleased(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e) { _releaseStoryboard.Begin(); } }
步骤2:在XAML中使用Behavior
先引入命名空间(假设你的Behavior位于YourApp.Behaviors下):
xmlns:behaviors="using:YourApp.Behaviors" xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
然后直接附加到任意控件:
<Button Content="复用3D Touch动画" Width="200" Height="80"> <interactivity:Interaction.Behaviors> <behaviors:3DTouchSizeBehavior PressedWidth="180" PressedHeight="70" /> </interactivity:Interaction.Behaviors> </Button>
关键注意点
- 控件必须设置固定的
Width和Height,Auto状态下无法用DoubleAnimation修改尺寸; - 调整
Duration和EasingFunction可以优化动画手感,比如CubicEase能让动画更自然; - 必须处理
PointerCanceled事件,防止用户按压后移出控件区域导致动画无法复位。
内容的提问来源于stack exchange,提问作者wxinbang
相关产品推荐
相关产品推荐

