我有一个Label,其Text属性是一个数值。当该数字更改时,我想为数字更改添加动画效果。因此,例如,如果“文本”设置为100并更改为120,我想显示它每100毫秒从100递增到101到102等,直到达到新值120。
我可以在背后的代码中手动完成此操作,但是由于我使用的是MVVM,因此我想找到一种在XAML中执行此操作的方法(例如行为,效果等)。我确定我也可以通过使用自定义渲染器来做到这一点,但是感觉应该有一种我不知道的更简单的方法来做到这一点。有什么想法吗?
谢谢!
答案 0 :(得分:0)
我有有效的代码,以防其他人使用。希望有人会发布更好的答案,但这至少现在对我有用。
我创建了一个行为,用于监视Label上的PropertyChanged事件。当Text属性更改时,我将标签的新值解析为long并将其与标签的先前值进行比较。如果两者之间存在差异,我将在每次等待时将Task.Delay(300)递增一次,以使计数减慢。我使用静态字典来跟踪先前的值。下面的工作代码-尽管仍在测试中...
public class LabelHighlightAndStepOnChangeBehavior : Behavior<Label>
{
public int EndHighlightDuration { get; set; } = 3000;
public string Property { get; set; }
public static Dictionary<string, long> _previousValues = new Dictionary<string, long>();
private bool _watchingTextChanges = true;
protected override void OnAttachedTo(Label element)
{
try
{
element.PropertyChanged += Label_PropertyChanged;
base.OnAttachedTo(element);
}
catch (Exception ex)
{
Logger.LogError(ex, false);
}
}
private async void Label_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
try
{
if (_watchingTextChanges && e.PropertyName == nameof(Label.Text))
{
_watchingTextChanges = false;
var label = (Label)sender;
var model = label.BindingContext as BaseModel;
var key = model.Id + Property;
if (_previousValues.ContainsKey(key) && _previousValues[key] != model.GetPropertyValue<long>(Property))
{
// Change background color.
var originalBackgroundColor = label.BackgroundColor;
label.BackgroundColor = Color.Yellow;
// Step the number up or down to the new value.
var originalValue = _previousValues[key];
var newValue = model.GetPropertyValue<long>(Property);
_previousValues[key] = newValue;
if (originalValue < newValue)
{
var step = Math.Max(1, Convert.ToInt32((newValue - originalValue) / 50.0) - 1);
while (originalValue < newValue)
{
if ((originalValue + step) <= newValue)
originalValue += step;
else
originalValue = newValue;
model.SetPropertyValue<long>(Property, originalValue);
await Task.Delay(50);
}
}
else if (originalValue > newValue)
{
var step = -Math.Max(1, Convert.ToInt32((originalValue - newValue) / 50.0) - 1);
while (originalValue > newValue)
{
if ((originalValue + step) <= newValue)
originalValue += step;
else
originalValue = newValue;
model.SetPropertyValue<long>(Property, originalValue);
await Task.Delay(50);
}
}
// Change the background color back.
await Task.Delay(EndHighlightDuration);
label.BackgroundColor = originalBackgroundColor;
}
else if (!_previousValues.ContainsKey(key))
{
_previousValues.Add(key, model.GetPropertyValue<long>(Property));
}
}
}
catch (Exception ex)
{
Logger.LogError(ex, false);
}
finally
{
_watchingTextChanges = true;
}
}
protected override void OnDetachingFrom(Label element)
{
try
{
element.PropertyChanged -= Label_PropertyChanged;
base.OnDetachingFrom(element);
}
catch (Exception ex)
{
Logger.LogError(ex, false);
}
}
}
答案 1 :(得分:0)
您可以使用Animation类在开始值和结束值之间更改数字,使用缓动功能指定数字更改的发生方式以及持续时间。
然后您可以将标签绑定到一个“金额”属性,设置一个_targetAmount,然后使用所需的动画属性在当前金额和_targetAmount之间设置“金额”动画。标签将通过绑定进行相应的更新。
要为视图模型上的属性设置动画,必须首先将视图模型类标记为IAnimatable。然后只需设置_targetAmount并调用AnimateAmountChange()即可以动画样式更新标签。
private void AnimateAmountChange()
{
var change = new Animation(x => Amount = (int)x, Amount, _targetAmount);
change.Commit(this, "ChangeAmount", 10, 300, Easing.SinOut);
}
#region IAnimatable
public void BatchBegin()
{
}
public void BatchCommit()
{
}
#endregion