Каков наилучший подход для анимации объекта в View при использовании MVVM? - PullRequest
0 голосов
/ 21 марта 2020

У меня есть простое приложение Xamarin Forms. Я использую Prism Forms. Я хотел бы анимировать Label с помощью базового c fade animation в View, когда его старое значение и новое значение не равны. Каков наилучший подход для анимации объекта в 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>

Ответы [ 2 ]

1 голос
/ 22 марта 2020

Логика анимации c должна быть ограничена только просмотрами. Рекомендуемым вариантом будет использование прикрепленного поведения, которое прослушивает изменения текста и соответственно анимирует связанную метку.

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. Как использовать анимацию пользовательского интерфейса в реализация MVVM?
  2. Сложные анимации в Xamarin. Формы с использованием конечного автомата
1 голос
/ 22 марта 2020

Способ, которым я бы это реализовал, - это создать пользовательский элемент управления многократного использования, который должен содержать всю логику / анимацию / 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}");
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...