【问题标题】:Animation and GridLength in Xamarin formsXamarin 表单中的动画和 GridLength
【发布时间】:2018-09-13 01:26:46
【问题描述】:

我有班级模型

public class Model : INotifyPropertyChanged
...
private GridLength detailsPanelHeight { get; set; }
public GridLength DetailsPanelHeight
{
    get { return detailsPanelHeight; }
    set
    {
        if (!GridLength.Equals(detailsPanelHeight, value))
        {
            detailsPanelHeight = value;
            OnPropertyChanged("DetailsPanelHeight");
        }
    }
}
...

部分 XAML 代码:

<RowDefinition Height="{Binding DetailsPanelHeight}" />

做动画的代码(平滑地改变行高):

var animate = new Animation(d => currentItem.DetailsPanelHeight = d, 0, 100);
animate.Commit(this, "ExpandAnimation", 50, 1000, Easing.SpringOut);

折叠行的代码: var animate = new Animation(d => currentItem.DetailsPanelHeight = d, 100, 0); animate.Commit(this, "CollapseAnimation", 50, 1000, Easing.SpringOut);

它第一次工作,但第二次我得到一个错误:“值小于 0 或不是数字\n参数名称:值”。我看到d 的值小于零。

我能做些什么来解决这个问题?

【问题讨论】:

  • @Diego,它没有帮助。我用 0.001 代替 0:var animate = new Animation(d => currentItem.DetailsPanelHeight = d, 100, 0.001);
  • 也许问题在于 double 和 GridLength 之间的转换。有可能吗?

标签: animation xamarin.forms gridlength


【解决方案1】:

我使用过类似的东西,对我来说非常有效。我希望它也适合你。

此动画在 delete 操作调用后调用命令时折叠视图单元格。代码如下:

点击事件处理程序:

private async void RemoveButtonTapped(object sender, EventArgs e)
{
    Parallel.Invoke(() =>
        {
             if (RemoveCommand?.CanExecute(RemoveCommandParameter) ?? false)
                 RemoveCommand.Execute(RemoveCommandParameter);
        },
        AnimatedDestruction);
}

动画方法

private async void AnimatedDestruction()
{
    uint transitionTime = 300;
    decimal delayFactor = 1.2m;

    // Note: stackPanel is the viewCell's top-level container

    await Task.WhenAll(
        stackPanel.FadeTo(0, Convert.ToUInt32(transitionTime * delayFactor), Easing.CubicInOut),
        View.InterpolateValue(stackPanel.Height, 0, Transition, transitionTime, Easing.CubicInOut)
        );
}

过渡回调函数

private void Transition(double value)
{
    const double minHeightValue = 0.001;

    value = value <= minHeightValue ? minHeightValue : value;

    Height = value;
    ForceUpdateSize();
}   

InterpolateValue 函数作为扩展方法(非常可重用)

public static Task<bool> InterpolateValue(this View view, double initialValue, double endValue, Action<double> transformIteration, uint length, Easing easing)
{
    Task<bool> ret = new Task<bool>(() => false);

    if (!view.AnimationIsRunning(nameof(InterpolateValue)))
    {
        try
        {
            easing = easing ?? Easing.Linear;
            var taskCompletionSource = new TaskCompletionSource<bool>();

            view.Animate(nameof(InterpolateValue), ((_double) => initialValue - (initialValue * _double)), transformIteration, 16, length, easing, (v, c) => taskCompletionSource.SetResult(c));
            ret = taskCompletionSource.Task;
        }
        catch
        {
            // supress animation overlapping errors 
        }
    }

    return ret;
}

我希望它对你有用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-14
    • 2019-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多