在xaml xamarin和C#中更改IsVisible时向上滑动动画

时间:2018-10-11 07:24:57

标签: c# xamarin

我有一个动画行为类,例如:

public class BaseAnimationBehavior : Behavior<View>
{
    protected View associatedObject;
    protected Easing _easingFunction;

    private readonly BindableProperty EasingFunctionProperty = BindableProperty.Create(nameof(EasingFunction), typeof(string), typeof(BaseAnimationBehavior), defaultValue: "Linear", propertyChanged: (b, o, n) => OnEasingFunctionChanged(b, (string)o, (string)n));
    private readonly BindableProperty ScaleProperty = BindableProperty.Create(nameof(Scale), typeof(double), typeof(BaseAnimationBehavior), defaultValue: 1.25);

    public string EasingFunction
    {
      get { return (string)GetValue(EasingFunctionProperty); }
      set { SetValue(EasingFunctionProperty, value); }
    }

    public double Scale
    {
      get { return (double)GetValue(ScaleProperty); }
      set { SetValue(ScaleProperty, value); }
    }

    protected override void OnAttachedTo(View bindable)
    {
      associatedObject = bindable;
      associatedObject.SizeChanged += AnimateItem;
    }

    protected override void OnDetachingFrom(View bindable)
    {
      associatedObject.SizeChanged -= AnimateItem;
    }

    private static Easing GetEasing(string easingName)
    {
      switch (easingName)
      {
        case "BounceIn": return Easing.BounceIn;
        case "BounceOut": return Easing.BounceOut;
        case "CubicInOut": return Easing.CubicInOut;
        case "CubicOut": return Easing.CubicOut;
        case "Linear": return Easing.Linear;
        case "SinIn": return Easing.SinIn;
        case "SinInOut": return Easing.SinInOut;
        case "SinOut": return Easing.SinOut;
        case "SpringIn": return Easing.SpringIn;
        case "SpringOut": return Easing.SpringOut;
        default: throw new ArgumentException(easingName + " is not valid");
      }
    }

    private static void OnEasingFunctionChanged(BindableObject bindable, string oldvalue, string newvalue)
    {
      var obj = bindable as BaseAnimationBehavior;
      if (obj == null)
      {
        return;
      }

      obj.EasingFunction = newvalue;
      obj._easingFunction = GetEasing(newvalue);
    }

    private void AnimateItem(object sender, EventArgs e) 
    {
      await associatedObject.TranslateTo(associatedObject.TranslationX, associatedObject.TranslationY - 10, 10, _easingFunction);
      await associatedObject.TranslateTo(associatedObject.TranslationX, associatedObject.TranslationY + 10, 900, _easingFunction);
    }
}

在XAML页面中,我应用如下动画:

<StackLayout IsVisible="{Binding AProp}">
  <Entry Text="{Binding AField}" IsEnabled="True">
      <Entry.Behaviors>
        <Entry.Behaviors:BaseAnimationBehavior EasingFunction="SinInOut" />
    </Entry.Behaviors>
  </Entry>
</StackLayout>

AProp变为true时,就会由于SizeChanged事件而产生动画。

AProp变为false时,由于整个StackLayout被隐藏,动画将无法运行或不可见。

我使用MVVM,并且有一个视图模型,它被绑定到如下视图:

public class MyViewModel
{
   public bool AProp { get { return _prop; } set { _prop = value; RaisePropertyChanged ....; } }
   public string AField { get { return _field; } set { _field = value; RaisePropertyChanged ....; } }

   public void DoSomething() {
     if(condition) { AProp = true; } else { AProp = false; }
   }
}

如何实现隐藏元素时先进行动画处理然后隐藏它的情况?

1 个答案:

答案 0 :(得分:0)

如果使用视图模型隐藏,则需要向视图发送某种信号,表明该属性已更改。

如果出于某种原因必须从视图模型中隐藏控件,我建议

  • 在视图模型中覆盖RaisePropertyChanged
  • 在属性名称为AProb上引发事件
  • 在视图中订阅该事件
  • 最后通过为条目指定名称来手动开始动画