diff --git a/src/Controls/tests/CustomAttributes/Test.cs b/src/Controls/tests/CustomAttributes/Test.cs
index 21bb6c59f57d..ae46f9c3a975 100644
--- a/src/Controls/tests/CustomAttributes/Test.cs
+++ b/src/Controls/tests/CustomAttributes/Test.cs
@@ -393,6 +393,7 @@ public enum Image
{
Source,
Source_FontImageSource,
+ IsAnimationPlaying,
Aspect,
IsOpaque,
IsLoading,
diff --git a/src/Controls/tests/TestCases.Android.Tests/snapshots/android/ImageUITests_IsAnimationPlaying_No.png b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/ImageUITests_IsAnimationPlaying_No.png
new file mode 100644
index 000000000000..230d0d9cdeef
Binary files /dev/null and b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/ImageUITests_IsAnimationPlaying_No.png differ
diff --git a/src/Controls/tests/TestCases.Android.Tests/snapshots/android/ImageUITests_IsAnimationPlaying_Yes.png b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/ImageUITests_IsAnimationPlaying_Yes.png
new file mode 100644
index 000000000000..3b9d7495e91b
Binary files /dev/null and b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/ImageUITests_IsAnimationPlaying_Yes.png differ
diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/ImageUITests.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/ImageUITests.cs
index 940c821c5b9d..5a5844353d69 100644
--- a/src/Controls/tests/TestCases.Shared.Tests/Tests/ImageUITests.cs
+++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/ImageUITests.cs
@@ -36,4 +36,16 @@ public void Source_FontImageSource()
remote.TapStateButton();
VerifyScreenshot("ImageUITests_Source_FontImageSource_FontAwesome");
}
+
+ [Test]
+ public async Task IsAnimationPlaying()
+ {
+ var remote = GoToStateRemote();
+ await Task.Delay(500); // make sure the gif is NOT playing
+ VerifyScreenshot("ImageUITests_IsAnimationPlaying_No");
+
+ remote.TapStateButton();
+ await Task.Delay(500); // make sure the gif IS playing
+ VerifyScreenshot("ImageUITests_IsAnimationPlaying_Yes");
+ }
}
diff --git a/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/ImageUITests_IsAnimationPlaying_No.png b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/ImageUITests_IsAnimationPlaying_No.png
new file mode 100644
index 000000000000..02ea4b0fec3e
Binary files /dev/null and b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/ImageUITests_IsAnimationPlaying_No.png differ
diff --git a/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/ImageUITests_IsAnimationPlaying_Yes.png b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/ImageUITests_IsAnimationPlaying_Yes.png
new file mode 100644
index 000000000000..511fab7ea991
Binary files /dev/null and b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/ImageUITests_IsAnimationPlaying_Yes.png differ
diff --git a/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/ImageUITests_IsAnimationPlaying_No.png b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/ImageUITests_IsAnimationPlaying_No.png
new file mode 100644
index 000000000000..a406b28f23b3
Binary files /dev/null and b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/ImageUITests_IsAnimationPlaying_No.png differ
diff --git a/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/ImageUITests_IsAnimationPlaying_Yes.png b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/ImageUITests_IsAnimationPlaying_Yes.png
new file mode 100644
index 000000000000..1e2b649ae33b
Binary files /dev/null and b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/ImageUITests_IsAnimationPlaying_Yes.png differ
diff --git a/src/Controls/tests/TestCases/Controls.TestCases.App.csproj b/src/Controls/tests/TestCases/Controls.TestCases.App.csproj
index 830011f59e46..57218d432616 100644
--- a/src/Controls/tests/TestCases/Controls.TestCases.App.csproj
+++ b/src/Controls/tests/TestCases/Controls.TestCases.App.csproj
@@ -5,6 +5,7 @@
Exe
true
false
+ enable
maccatalyst-x64
maccatalyst-arm64
diff --git a/src/Controls/tests/TestCases/Elements/ImageCoreGalleryPage.cs b/src/Controls/tests/TestCases/Elements/ImageCoreGalleryPage.cs
index 6d3e0bb1bb8e..427469be0034 100644
--- a/src/Controls/tests/TestCases/Elements/ImageCoreGalleryPage.cs
+++ b/src/Controls/tests/TestCases/Elements/ImageCoreGalleryPage.cs
@@ -33,5 +33,20 @@ protected override void Build()
};
Add(familyContainer);
}
+
+ {
+ var image = new Image
+ {
+ Source = "red_is_good.gif",
+ WidthRequest = 100,
+ HeightRequest = 100,
+ };
+ var container = new StateViewContainer(Test.Image.IsAnimationPlaying, image);
+ container.StateChangeButton.Clicked += (s, a) =>
+ {
+ image.IsAnimationPlaying = !image.IsAnimationPlaying;
+ };
+ Add(container);
+ }
}
}
diff --git a/src/Controls/tests/TestCases/Resources/Images/red_is_good.gif b/src/Controls/tests/TestCases/Resources/Images/red_is_good.gif
new file mode 100644
index 000000000000..19b69f382e92
Binary files /dev/null and b/src/Controls/tests/TestCases/Resources/Images/red_is_good.gif differ
diff --git a/src/Core/src/Platform/Android/ImageViewExtensions.cs b/src/Core/src/Platform/Android/ImageViewExtensions.cs
index e08c98dbc78f..80c69d6c5c54 100644
--- a/src/Core/src/Platform/Android/ImageViewExtensions.cs
+++ b/src/Core/src/Platform/Android/ImageViewExtensions.cs
@@ -4,6 +4,7 @@
using Android.Graphics.Drawables;
using Android.Views;
using Android.Widget;
+using Bumptech.Glide.Load.Resource.Gif;
namespace Microsoft.Maui.Platform
{
@@ -29,7 +30,8 @@ public static void UpdateIsAnimationPlaying(this ImageView imageView, IImageSour
public static void UpdateIsAnimationPlaying(this Drawable? drawable, IImageSourcePart image)
{
- if (drawable is IAnimatable animatable)
+ var animatable = drawable.TryJavaCast();
+ if (animatable is not null)
{
if (image.IsAnimationPlaying)
{
diff --git a/src/Core/src/Platform/Android/JavaObjectExtensions.cs b/src/Core/src/Platform/Android/JavaObjectExtensions.cs
index 014c0fed5eaa..ecac7f09b73f 100644
--- a/src/Core/src/Platform/Android/JavaObjectExtensions.cs
+++ b/src/Core/src/Platform/Android/JavaObjectExtensions.cs
@@ -1,10 +1,13 @@
using System;
using System.Diagnostics.CodeAnalysis;
+using Android.Runtime;
namespace Microsoft.Maui
{
static class JavaObjectExtensions
{
+ const DynamicallyAccessedMemberTypes Constructors = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors;
+
public static bool IsDisposed(this Java.Lang.Object obj)
{
return obj.Handle == IntPtr.Zero;
@@ -30,5 +33,18 @@ public static bool IsAlive([NotNullWhen(true)] this global::Android.Runtime.IJav
return !obj.IsDisposed();
}
+
+ public static TResult? TryJavaCast<[DynamicallyAccessedMembers (Constructors)] TResult>(this IJavaObject? instance)
+ where TResult : class, IJavaObject
+ {
+ try
+ {
+ return instance.JavaCast();
+ }
+ catch
+ {
+ return null;
+ }
+ }
}
}
\ No newline at end of file