我正在尝试在MvxImageView
(在Android CardView中)实现可触发动画,以便在卡片的ViewModel上更改属性时将颜色(绿色或红色)覆盖到图像上。我使用Stuart Lodge的示例here创建了自定义类DynamicImageView。
public class DynamicImageView : MvxImageView
{
public DynamicImageView(Context context) : base(context)
{
}
public DynamicImageView(Context context, IAttributeSet attrs) : base(context, attrs)
{
}
public DynamicImageView(Context context, IAttributeSet attrs, int defStyleAttr) : base(context, attrs, defStyleAttr)
{
}
protected DynamicImageView(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
{
}
protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
Drawable d = this.Drawable;
if (d != null)
{
// ceil not round - avoid thin vertical gaps along the left/right edges
int width = MeasureSpec.GetSize(widthMeasureSpec);
int height = (int)Math.Ceiling(width * (float)d.IntrinsicHeight / d.IntrinsicWidth);
this.SetMeasuredDimension(width, height);
}
else
{
base.OnMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
private ObjectAnimator colorFilterAnimation;
private string _animatingColor;
public string AnimatingColor
{
set
{
System.Diagnostics.Debug.WriteLine("Animation triggered");
if (value != _animatingColor)
{
_animatingColor = value;
colorFilterAnimation = ObjectAnimator.OfObject((ImageView)this, "colorFilter", new ArgbEvaluator(), 0, 0);
switch (value)
{
case "red":
colorFilterAnimation.SetObjectValues(0, new Color(100, 0, 0, 80).ToArgb());
System.Diagnostics.Debug.WriteLine("Starting Red Animation");
break;
case "green":
colorFilterAnimation.SetObjectValues(0, (int)Color.Green);
System.Diagnostics.Debug.WriteLine("Starting Green Animation");
break;
}
colorFilterAnimation.SetDuration(1000);
colorFilterAnimation.Start();
}
}
}
}
在此控件的ViewModel中,我也按照标准MvvmCross表示法定义了匹配属性:
private string _animatingColor;
public string AnimatingColor {
get
{
return _animatingColor;
}
set
{
_animatingColor = value;
Debug.WriteLine("AnimatingColor set to " + value);
RaisePropertyChanged(() => AnimatingColor);
}
}
单击该卡时更改了此属性,当我单击时,我会在属性set
中看到Debug打印,但它似乎没有触发AnimatingColor的set
在控制之内。 axml中的控件正常引用:
<DynamicImageView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
local:MvxBind="ImageUrl 'http:'+Profile.Headshot.Url; AnimatingColor .AnimatingColor" />
并且值得,imageUrl确实正确绑定,并在ViewModel中更改Url时按预期更新。此外,Debug.PrintLine("Animation triggered")
会在创建卡时打印,但从不在ViewModel上更改属性时打印。
答案 0 :(得分:0)
正如评论所示,我认为您需要为DynamicImageView控件创建自定义绑定。这样的事情应该这样做:
public class DynamicImageViewAnimatingColorBinding : MvxTargetBinding
{
public DynamicImageViewAnimatingColorBinding(DynamicImageView target) : base(target)
{
}
protected DynamicImageView View => Target as DynamicImageView;
public override MvxBindingMode DefaultMode => MvxBindingMode.OneWay;
public override Type TargetType => typeof(string);
public override void SetValue(object value)
{
var view = View;
if (view == null)
return;
view.AnimatingColor = (string) value;
}
}
然后在您的安装程序类中,您需要注册它以便MvvmCross可以使用它:
protected override void FillTargetFactories(IMvxTargetBindingFactoryRegistry registry)
{
registry.RegisterCustomBindingFactory<DynamicImageView>(
nameof(DynamicImageView.AnimatingColor),
image => new DynamicImageViewAnimatingColorBinding (image));
base.FillTargetFactories(registry);
}
我没有测试过这段代码,它基于我在iOS上使用的一些非常相似的代码,但它在Android上运行良好。希望这会有所帮助。
答案 1 :(得分:0)
James Mundy的问题使我意识到底层问题是我没有在列表中使用ObservableCollection,因此底层ViewModel的更改没有反映在UI中。