diff --git a/src/Controls/src/Core/Compatibility/Handlers/Android/FrameRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/Android/FrameRenderer.cs
index 6271193e3785..8f319a21ead2 100644
--- a/src/Controls/src/Core/Compatibility/Handlers/Android/FrameRenderer.cs
+++ b/src/Controls/src/Core/Compatibility/Handlers/Android/FrameRenderer.cs
@@ -4,9 +4,7 @@
using Android.Graphics;
using Android.Graphics.Drawables;
using Android.Views;
-using Android.Views.Animations;
using AndroidX.CardView.Widget;
-using AndroidX.Core.View;
using Microsoft.Maui.Controls.Platform;
using Microsoft.Maui.Graphics;
using AColor = Android.Graphics.Color;
@@ -30,7 +28,7 @@ public static IPropertyMapper Mapper
[Frame.BorderColorProperty.PropertyName] = (h, _) => h.UpdateBorderColor(),
[Microsoft.Maui.Controls.Compatibility.Layout.IsClippedToBoundsProperty.PropertyName] = (h, _) => h.UpdateClippedToBounds(),
[Frame.ContentProperty.PropertyName] = (h, _) => h.UpdateContent(),
- [nameof(IView.AutomationId)] = (h, v) => ViewHandler.MapAutomationId(h, v),
+ [nameof(IView.AutomationId)] = (h, v) => ViewHandler.MapAutomationId(h, v)
};
public static CommandMapper CommandMapper
@@ -48,6 +46,9 @@ public static CommandMapper CommandMapper
IMauiContext? _mauiContext;
ViewHandlerDelegator _viewHandlerWrapper;
Frame? _element;
+ bool _hasContainer;
+ AView? _wrapperView;
+
public event EventHandler? ElementChanged;
public event EventHandler? ElementPropertyChanged;
@@ -351,9 +352,31 @@ void UpdateContent()
}
#region IPlatformViewHandler
- bool IViewHandler.HasContainer { get => false; set { } }
- object? IViewHandler.ContainerView => null;
+ bool IViewHandler.HasContainer
+ {
+ get => _hasContainer;
+ set
+ {
+ if (_hasContainer == value)
+ return;
+
+ _hasContainer = value;
+
+ if (value)
+ SetupContainer();
+ else
+ RemoveContainer();
+ }
+ }
+
+ void SetupContainer() =>
+ WrapperView.SetupContainer(this, Context, _wrapperView, (cv) => _wrapperView = cv);
+
+ void RemoveContainer() =>
+ WrapperView.RemoveContainer(this, Context, _wrapperView, () => _wrapperView = null);
+
+ object? IViewHandler.ContainerView => _wrapperView;
IView? IViewHandler.VirtualView => Element;
@@ -365,7 +388,7 @@ void UpdateContent()
AView IPlatformViewHandler.PlatformView => this;
- AView? IPlatformViewHandler.ContainerView => this;
+ AView? IPlatformViewHandler.ContainerView => _wrapperView;
void IViewHandler.PlatformArrange(Graphics.Rect rect) =>
this.PlatformArrangeHandler(rect);
@@ -396,6 +419,7 @@ void IElementHandler.DisconnectHandler()
{
_viewHandlerWrapper.DisconnectHandler();
}
+
#endregion
}
}
diff --git a/src/Controls/tests/DeviceTests/Elements/Frame/FrameHandlerTest.Android.cs b/src/Controls/tests/DeviceTests/Elements/Frame/FrameHandlerTest.Android.cs
index f05babfdc875..0b754454b489 100644
--- a/src/Controls/tests/DeviceTests/Elements/Frame/FrameHandlerTest.Android.cs
+++ b/src/Controls/tests/DeviceTests/Elements/Frame/FrameHandlerTest.Android.cs
@@ -8,24 +8,6 @@ namespace Microsoft.Maui.DeviceTests
{
public partial class FrameHandlerTest
{
- public override Task ContainerViewInitializesCorrectly()
- {
- // https://github.com/dotnet/maui/pull/12218
- return Task.CompletedTask;
- }
-
- public override Task ContainerViewAddsAndRemoves()
- {
- // https://github.com/dotnet/maui/pull/12218
- return Task.CompletedTask;
- }
-
- public override Task ContainerViewRemainsIfShadowMapperRunsAgain()
- {
- // https://github.com/dotnet/maui/pull/12218
- return Task.CompletedTask;
- }
-
public override async Task ReturnsNonEmptyNativeBoundingBox(int size)
{
// Frames have a legacy hard-coded minimum size of 20x20
diff --git a/src/Core/src/Handlers/View/ViewHandlerOfT.Android.cs b/src/Core/src/Handlers/View/ViewHandlerOfT.Android.cs
index 3df16313bae2..996a2202387c 100644
--- a/src/Core/src/Handlers/View/ViewHandlerOfT.Android.cs
+++ b/src/Core/src/Handlers/View/ViewHandlerOfT.Android.cs
@@ -17,52 +17,10 @@ public override void PlatformArrange(Rect frame) =>
public override Size GetDesiredSize(double widthConstraint, double heightConstraint) =>
this.GetDesiredSizeFromHandler(widthConstraint, heightConstraint);
- protected override void SetupContainer()
- {
- if (Context == null || PlatformView == null || ContainerView != null)
- return;
+ protected override void SetupContainer() =>
+ WrapperView.SetupContainer(PlatformView, Context, ContainerView, (cv) => ContainerView = cv);
- var oldParent = (ViewGroup?)PlatformView.Parent;
-
- var oldIndex = oldParent?.IndexOfChild(PlatformView);
- oldParent?.RemoveView(PlatformView);
-
- ContainerView ??= new WrapperView(Context);
- ((ViewGroup)ContainerView).AddView(PlatformView);
-
- if (oldIndex is int idx && idx >= 0)
- oldParent?.AddView(ContainerView, idx);
- else
- oldParent?.AddView(ContainerView);
- }
-
- protected override void RemoveContainer()
- {
- if (Context == null || PlatformView == null || ContainerView == null || PlatformView.Parent != ContainerView)
- {
- CleanupContainerView(ContainerView);
- ContainerView = null;
- return;
- }
-
- var oldParent = (ViewGroup?)ContainerView.Parent;
-
- var oldIndex = oldParent?.IndexOfChild(ContainerView);
- oldParent?.RemoveView(ContainerView);
-
- CleanupContainerView(ContainerView);
- ContainerView = null;
-
- if (oldIndex is int idx && idx >= 0)
- oldParent?.AddView(PlatformView, idx);
- else
- oldParent?.AddView(PlatformView);
-
- void CleanupContainerView(View? containerView)
- {
- if (containerView is ViewGroup vg)
- vg.RemoveAllViews();
- }
- }
+ protected override void RemoveContainer() =>
+ WrapperView.RemoveContainer(PlatformView, Context, ContainerView, () => ContainerView = null);
}
}
diff --git a/src/Core/src/Platform/Android/WrapperView.cs b/src/Core/src/Platform/Android/WrapperView.cs
index d309e9284f56..9c735c1b37a8 100644
--- a/src/Core/src/Platform/Android/WrapperView.cs
+++ b/src/Core/src/Platform/Android/WrapperView.cs
@@ -1,4 +1,5 @@
#nullable disable
+using System;
using Android.Content;
using Android.Graphics;
using Android.Views;
@@ -326,5 +327,55 @@ public override ViewStates Visibility
}
}
}
+
+ internal static void SetupContainer(AView platformView, Context context, AView containerView, Action setWrapperView)
+ {
+ if (context == null || platformView == null || containerView != null)
+ return;
+
+ var oldParent = (ViewGroup)platformView.Parent;
+
+ var oldIndex = oldParent?.IndexOfChild(platformView);
+ oldParent?.RemoveView(platformView);
+
+ containerView ??= new WrapperView(context);
+ setWrapperView.Invoke(containerView);
+
+ ((ViewGroup)containerView).AddView(platformView);
+
+ if (oldIndex is int idx && idx >= 0)
+ oldParent?.AddView(containerView, idx);
+ else
+ oldParent?.AddView(containerView);
+ }
+
+ internal static void RemoveContainer(AView platformView, Context context, AView containerView, Action clearWrapperView)
+ {
+ if (context == null || platformView == null || containerView == null || platformView.Parent != containerView)
+ {
+ CleanupContainerView(containerView, clearWrapperView);
+ return;
+ }
+
+ var oldParent = (ViewGroup)containerView.Parent;
+
+ var oldIndex = oldParent?.IndexOfChild(containerView);
+ oldParent?.RemoveView(containerView);
+
+ CleanupContainerView(containerView, clearWrapperView);
+
+ if (oldIndex is int idx && idx >= 0)
+ oldParent?.AddView(platformView, idx);
+ else
+ oldParent?.AddView(platformView);
+
+ void CleanupContainerView(AView containerView, Action clearWrapperView)
+ {
+ if (containerView is ViewGroup vg)
+ vg.RemoveAllViews();
+
+ clearWrapperView.Invoke();
+ }
+ }
}
}
\ No newline at end of file