使用MVVM时在View中为对象设置动画的最佳方法是什么?

问题描述 投票:0回答:2

我有一个简单的Xamarin Forms应用程序。我正在使用棱镜表格。当旧值和新值不相等时,我想在View中使用基本淡入淡出动画为Label设置动画。在View中为对象设置动画的最佳方法是什么?预先谢谢你。

MainPageViewModel.cs

public class MainPageViewModel : BindableBase
{
    public HomePageViewModel()
    {       
            Title = "First";
            ChangeTitle();
    }

    private async void ChangeTitle()
    {

        await Task.Delay(5000);

        if(Title == "First")
        {
            Title = "Second";
        }
        else
        {
            Title = "First";
        }

        ChangeTitle();
    }



    private string title;
    public string Title
    {
        get { return title; }
        set { SetProperty(ref title, value); }
    }

}

MainPage.xml

<ContentPage
    x:Class="SmapleApp.Views.MainPage"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:prism="http://prismlibrary.com"
    prism:ViewModelLocator.AutowireViewModel="True"
    Title="Main Page">

    <Label Text="{Binding Title}" />

</ContentPage>
xaml xamarin xamarin.forms prism
2个回答
1
投票

动画逻辑应仅限于视图。推荐的选择是使用附加的行为,侦听文本更改并相应地给关联的标签添加动画效果。

public class FadingLabelAnimationBehavior : Behavior<Label>
{
    private Label _associatedObject;

    private uint DesiredDuration { get; set; } = 750;

    protected override void OnAttachedTo(Label bindable)
    {
        base.OnAttachedTo(bindable);
        _associatedObject = bindable;

        _associatedObject.PropertyChanged += OnTextChangedHandler;
    }

    private async void OnTextChangedHandler(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == Label.TextProperty.PropertyName)
        {
            _associatedObject.Opacity = 0f;
            await _associatedObject.FadeTo(1f, DesiredDuration);
        }
    }

    protected override void OnDetachingFrom(Label bindable)
    {
        _associatedObject = null;
        base.OnDetachingFrom(bindable);

        _associatedObject.PropertyChanged -= OnTextChangedHandler;
    }
}

用法:

<Label Text="{Binding Title}" ... >
    <Label.Behaviors>
        <local:FadingLabelAnimationBehavior />
    </Label.Behaviors>
</Label>

更多可供探索的选项:

  1. How do you have UI animations in an MVVM implementation?
  2. Complex Animations in Xamarin.Forms using Finite State Machine

1
投票

我实现它的方法是创建一个可重用的自定义控件,该控件应包含所有逻辑/动画/ xaml。所以应该是这样的:

您的自定义控件Xaml:

<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="TestingXamarin.MyCustomText"
             x:Name="mycontrol">
  <ContentView.Content>
      <StackLayout>
          <Label x:Name="mytext" />
      </StackLayout>
  </ContentView.Content>
</ContentView>

您在自定义控件后面的代码:

public partial class MyCustomText : ContentView
{
    public static readonly BindableProperty TextProperty = BindableProperty.Create(nameof(Text), typeof(string), typeof(MyCustomText),
        propertyChanged: async(s, ea, eas) =>
        {
            var myControl = s as MyCustomText;
            var myTextControl = myControl.mytext;
            await myTextControl.FadeTo(0, 100);
            myTextControl.Text = eas.ToString();
            await myTextControl.FadeTo(1, 100);
        });

    public string Text
    {
        get
        {
            return (string)GetValue(TextProperty);
        }
        set
        {
            SetValue(TextProperty, value);
        }
    }

    public MyCustomText()
    {
        InitializeComponent();
    }
}

然后您可以像这样使用它:您的页面:

<StackLayout 
           HorizontalOptions="Center"
           VerticalOptions="CenterAndExpand">
        <!-- Place new controls here -->
        <Label Text="This is my control:"  />
        <myapp:MyCustomText Text="{Binding Title}" />
        <Button Text="Change text" Command="{Binding ChangeTextCommand}" />
    </StackLayout>

然后,最后是您的ViewModel(无论您使用什么框架):

public class MainViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private string title;
    public string Title
    {
        get => title;
        set
        {
            if(value != title)
            {
                title = value;
                if (this.PropertyChanged != null)
                    this.PropertyChanged(this, new PropertyChangedEventArgs("Title"));
            }
        }
    }

    public Command ChangeTextCommand
    {
        get => new Command(() => Title = $"Time Now is {DateTime.Now}");
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.