目录

在 Maui 中自绘组件4:点击动效

在这篇文章中,将为 MagicButton 绘制点击动画效果,实现从点击位置开始,绘制一个不断扩大的半透明圆形。

先决条件

绘制点击动画

MagicButtonDrawable 中定义 TouchPointAnimationPercent 属性。TouchPoint 为点击焦点的位置坐标,AnimationPercent 为动画进度比例。

public PointF TouchPoint { get; set; }
public double AnimationPercent { get; set; }

定义 DrawRippleEffect 方法,绘制点击动画。

public void DrawRippleEffect(ICanvas canvas, RectF dirtyRect) {
    if (!dirtyRect.Contains(TouchPoint)) {
        return;
    }

    canvas.SaveState();

    var clippingPath = new PathF();
    clippingPath.AppendRoundedRectangle(
        dirtyRect.X,
        dirtyRect.Y,
        dirtyRect.Width,
        dirtyRect.Height,
        dirtyRect.Height / 2,
        dirtyRect.Height / 2,
        dirtyRect.Height / 2,
        dirtyRect.Height / 2
        );
    canvas.ClipPath(clippingPath);

    canvas.FillColor = Colors.White.WithAlpha(0.75f);
    canvas.Alpha = 0.25f;
    var minimumRippleEffectSize = 0.0f;
    var rippleEffectSize = minimumRippleEffectSize.Lerp(dirtyRect.Width, AnimationPercent);
    canvas.FillCircle(TouchPoint.X, TouchPoint.Y, rippleEffectSize);

    canvas.RestoreState();
}

通过 ClipPath 设置一个与当前 dirtyRect 位置大小相同的路径,绘制动画效果时将在此路径上绘制,否则动画效果将溢出 MagicButton 元素。然后根据 AnimationPercent 计算出要绘制的圆形动画效果的大小,并进行绘制。

触发绘制动画

MagicButton 中定义类型为 IAnimationManager 的字段,并在构造函数中进行实例化。

private readonly IAnimationManager _animationManager;

public MagicButton() {

    // ......

#if __ANDROID__
    _animationManager = new AnimationManager(new PlatformTicker(new Microsoft.Maui.Platform.EnergySaverListenerManager()));
#else
    _animationManager = new AnimationManager(new PlatformTicker());
#endif
}

定义 AnimateRippleEffect 来调用 MagicButtonDrawable 绘制动画。

public void AnimateRippleEffect() {
    if (Drawable is not MagicButtonDrawable drawable) {
        return;
    }

    var start = 0f;
    var end = 1f;

    _animationManager.Add(new Microsoft.Maui.Animations.Animation(
        (progress) => {
            drawable.AnimationPercent = start.Lerp(end, progress);
            Invalidate();
        },
        duration: 0.25,
        easing: Easing.SinInOut,
        finished: () => {
            drawable.AnimationPercent = 0;
        }));
}

在上述代码中通过 Microsoft.Maui.Animations.Animation 计算出了动画进度,并更新 MagicButtonDrawable 中的 AnimationPercent 值,然后调用 Invalidate 方法进行重绘。

定义 OnStartInteraction 方法来处理 StartInteraction 事件,将点击位置坐标赋值给 MagicButtonDrawable,并调用定义的 AnimateRippleEffect 方法,来实现点击时的动画效果。

public MagicButton() {
    // ......

    StartInteraction += OnStartInteraction;
}

private void OnStartInteraction(object sender, TouchEventArgs e) {
    if (Drawable is not MagicButtonDrawable drawable) {
        return;
    }

    drawable.TouchPoint = e.Touches[0];
    AnimateRippleEffect();
}

运行并点击按钮,效果如下:

./animation.gif
Animation

推荐内容

源码获取

扫描下方二维码,关注公众号捕获异常,回复 maui 获取源码。

关注微信公众号“捕获异常”,获取最新文章推送,提升你的技能。

捕获异常微信公众号二维码