如何停止用于异步翻译图像的 Xamarin.Forms 行为?

How to stop a Xamarin.Forms behavior used to asynchronously translate an image?

在一个 Xamarin.Forms 项目中,我试图重复将图像从位置 A(x,y) 转换到位置 B(x,y) 并返回,从 B 到 A。到实现这一点,我读到可以自定义行为。

我扩展了行为 class,覆盖了 OnAttachedTo 和 OnDetachingFrom。在 OnAttachedTo 方法中,我启动了一个任务,该任务重复执行两种翻译。

这是我的行为class:

public class MoveImageBehavior : Behavior<Image>
{
    private Image _Image = null;

    public static readonly BindableProperty AnimatedProperty = BindableProperty.Create("Animated", typeof(bool), typeof(ImageAnimatedBehavior), defaultValue: false);
    public bool Animated
    {
        get { return (bool)GetValue(AnimatedProperty); }
        set { SetValue(AnimatedProperty, value); }
    }

    protected override void OnAttachedTo(Image image)
    {
        base.OnAttachedTo(image);

        _Image = image;
        Animated = true;
        Task.Run(AnimateImage);
    }

    protected override void OnDetachingFrom(Image image)
    {
        base.OnDetachingFrom(image);
        _Image = null;
    }

    private async void AnimateImage()
    {
        while (_Image != null && Animated)
        {
            await _Image.TranslateTo(100, 100, 1000);
            await _Image.TranslateTo(0, 0, 1000);
        }
    }
}

xaml 文件中的图像:

<ContentView>
    <Grid>
        <Image x:Name="image_translating" Source="my_icon" Aspect="AspectFit">
            <Image.Behaviors>
                <behaviors:MoveImageBehavior Animated="{Binding ImageTranslating}" BindingContext="{Binding BindingContext, Source={x:Reference image_translating}}"/>
            </Image.Behaviors>
        </Image>
    </Grid>
</ContentView>

图像按照我的意愿反复正确翻译,但我无法停止 while 例程。当 ViewModel 中的 Animated 设置为 false 且从不调用 OnDetachingFrom 时,属性 绑定不起作用。 我究竟做错了什么?有什么建议吗?

通过文档可以看出:

The OnDetachingFrom method is fired when the behavior is removed from the control. This method receives a reference to the control to which it is attached, and is used to perform any required cleanup. For example, you could unsubscribe from an event on a control to prevent memory leaks.

它只会在您从图像中删除行为时触发。我会给你一个关于如何停止动画的例子:

我在后面的代码里定义了一个bool 属性来控制停不停:

  public bool showA  = true;

并且我添加一个按钮作为停止动画的例子:

private void Button_Clicked(object sender, EventArgs e)
{
    showA = !showA;

    if (showA)
    {
        image_translating.Behaviors.Add(new MoveImageBehavior());

    }
    else
    {
        var toRemove = image_translating.Behaviors.FirstOrDefault(b => b is MoveImageBehavior);
        if (toRemove != null)
        {
            image_translating.Behaviors.Remove(toRemove);
        }
    }
}

同样在你的 OnDetachingFrom 方法中,不要将图像设置为 null,它会导致 null 预期,只需将 Animated 设置为 false :

protected override void OnDetachingFrom(Image image)
{
    base.OnDetachingFrom(image);
    Animated = false;
}

您可以将我的点击事件转换为您项目中的某些绑定并使其工作。

参考:creating-a-xamarinforms-behaviorer