通过自定义渲染器执行此操作将是利用每个平台功能的最佳方式:
iOS:这可以通过将UIImages 的数组应用于UIImageView.AnimationImage 属性来完成。
Android:一种方法,将“动画列表”设置为ImageView的背景。
(gif 有问题,但这两种技术在设备(和大多数模拟器)上运行流畅;-)
注意:此示例代码使用了 10 张图片 (frame_X.png),它们链接在 iOS Resources 和 Android Resources/drawable 下。
Xamarin.Forms 自定义 Image 带有可绑定 Animate 属性的控件:
public class AnimatedImage : Image
{
public static readonly BindableProperty AnimateProperty = BindableProperty.Create(
propertyName: "Animate",
returnType: typeof(bool),
declaringType: typeof(AnimatedImage),
defaultValue: false);
public bool Animate
{
get { return (bool)GetValue(AnimateProperty); }
set { SetValue(AnimateProperty, value); }
}
}
iOS 自定义ImageRenderer:
[assembly: ExportRenderer(typeof(AnimatedImage), typeof(AnimatedImageRenderer_iOS))]
namespace AnimImage.iOS
{
public class AnimatedImageRenderer_iOS : ImageRenderer
{
const int imageCount = 10;
NSMutableArray imageArray;
public AnimatedImageRenderer_iOS() {
imageArray = new NSMutableArray(imageCount);
for (int i = 0; i < imageCount; i++)
imageArray.Add(UIImage.FromFile(new NSString($"frame_{i}.png")));
}
protected override void OnElementChanged(ElementChangedEventArgs<Image> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.AnimationImages = NSArray.FromArray<UIImage>(imageArray);
Control.AnimationDuration = 1;
Control.AnimationRepeatCount = 0;
if (e.NewElement != null)
{
if ((e.NewElement as AnimatedImage).Animate)
Control.StartAnimating();
}
}
}
protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == "Animate")
{
if ((sender as AnimatedImage).Animate)
Control?.StartAnimating();
else
Control?.StopAnimating();
}
}
}
}
Android 自定义ImageRenderer:
[assembly: ExportRenderer(typeof(AnimatedImage), typeof(AnimatedImageRenderer_Droid))]
namespace AnimImage.Droid
{
public class AnimatedImageRenderer_Droid : ImageRenderer
{
public AnimatedImageRenderer_Droid() { }
AnimationDrawable anim;
protected override void OnElementChanged(ElementChangedEventArgs<Image> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.SetBackgroundResource(Resource.Drawable.animatedlogo);
if (e.NewElement != null)
{
if ((e.NewElement as AnimatedImage).Animate)
{
(Control.Background as AnimationDrawable)?.Start();
Control.ImageAlpha = 0;
}
}
}
}
protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == "Animate")
{
if ((sender as AnimatedImage).Animate)
{
(Control.Background as AnimationDrawable)?.Start();
Control.ImageAlpha = 0;
}
else
{
Control.ImageAlpha = 255;
(Control.Background as AnimationDrawable)?.Stop();
}
}
}
}
}
Androidanimation-listDrawable:
<?xml version="1.0" encoding="UTF-8" ?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item android:drawable="@drawable/frame_0" android:duration="100" />
<item android:drawable="@drawable/frame_1" android:duration="100" />
<item android:drawable="@drawable/frame_2" android:duration="100" />
<item android:drawable="@drawable/frame_3" android:duration="100" />
<item android:drawable="@drawable/frame_4" android:duration="100" />
<item android:drawable="@drawable/frame_5" android:duration="100" />
<item android:drawable="@drawable/frame_6" android:duration="100" />
<item android:drawable="@drawable/frame_7" android:duration="100" />
<item android:drawable="@drawable/frame_8" android:duration="100" />
<item android:drawable="@drawable/frame_9" android:duration="100" />
</animation-list>