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