Skip to content

[iOS] Inherit UIContainerView from MauiView #26576

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ void OnFooterMeasureInvalidated(object sender, System.EventArgs e)

void ReMeasureFooter()
{
var size = _footerView?.SizeThatFits(new CGSize(View.Frame.Width, double.PositiveInfinity));
var size = _footerView?.UpdateSize(new CGSize(View.Frame.Width, double.PositiveInfinity));
if (size is not null)
UpdateFooterPosition(size.Value.Height);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ void OnHeaderViewMeasureChanged(object sender, EventArgs e)
if (HeaderView is null || ContentView?.Superview is null)
return;

HeaderView.SizeThatFits(new CGSize(ContentView.Superview.Frame.Width, double.PositiveInfinity));
HeaderView.UpdateSize(new CGSize(ContentView.Superview.Frame.Width, double.PositiveInfinity));
UpdateHeaderSize();
}

Expand All @@ -196,7 +196,7 @@ internal void UpdateHeaderSize()
// If the HeaderView hasn't been measured we need to measure it
if (double.IsNaN(MeasuredHeaderViewHeightWithMargin))
{
HeaderView.SizeThatFits(new CGSize(ContentView.Superview.Frame.Width, double.PositiveInfinity));
HeaderView.UpdateSize(new CGSize(ContentView.Superview.Frame.Width, double.PositiveInfinity));
}

SetHeaderContentInset();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,10 @@ protected virtual void UpdateTitleView()
{
var view = NavigationItem.TitleView;
NavigationItem.TitleView = null;
view?.Dispose();
if(view is TitleViewContainer titleViewContainer)
{
titleViewContainer.Disconnect();
}
}
else
{
Expand Down Expand Up @@ -899,7 +902,7 @@ protected virtual void Dispose(bool disposing)
if (_context.Shell.Toolbar != null)
_context.Shell.Toolbar.PropertyChanged -= OnToolbarPropertyChanged;

if (NavigationItem?.TitleView is TitleViewContainer tvc)
if (IsRootPage && NavigationItem?.TitleView is TitleViewContainer tvc)
tvc.Disconnect();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,44 +7,23 @@

namespace Microsoft.Maui.Controls.Platform.Compatibility
{
public class UIContainerView : UIView
public class UIContainerView : MauiView
{
readonly View _view;
IPlatformViewHandler _renderer;
UIView _platformView;
WeakReference<IView> _childview;
bool _disposed;
double _measuredHeight;

internal event EventHandler HeaderSizeChanged;

public UIContainerView(View view)
{
_view = view;

_childview = new(view);
UpdatePlatformView();
ClipsToBounds = true;
MeasuredHeight = double.NaN;
Margin = new Thickness(0);
}

internal void UpdatePlatformView()
{
_renderer = _view.ToHandler(_view.FindMauiContext());
_platformView = _view.ToPlatform();

if (_platformView.Superview != this)
AddSubview(_platformView);
}

bool IsPlatformViewValid()
{
if (View == null || _platformView == null || _renderer == null)
return false;

return _platformView.Superview == this;
}

internal View View => _view;
internal new View View => _childview != null && _childview.TryGetTarget(out var v) ? v as View : null;

internal bool MatchHeight { get; set; }

Expand Down Expand Up @@ -83,39 +62,46 @@ private protected void OnHeaderSizeChanged()
HeaderSizeChanged?.Invoke(this, EventArgs.Empty);
}

public override CGSize SizeThatFits(CGSize size)
internal void UpdatePlatformView()
{
var measuredSize = (_view as IView).Measure(size.Width, size.Height);
GeneralWrapperView.UpdatePlatformView(this, View, View.FindMauiContext(), out _childview);
}

if (Height != null && MatchHeight)
{
MeasuredHeight = Height.Value;
}
else
internal CGSize UpdateSize(CGSize size)
{
var newSize = SizeThatFits(size);
if (MeasuredHeight != newSize.Height)
{
MeasuredHeight = measuredSize.Height;
MeasuredHeight = newSize.Height;
SetNeedsLayout();
}
return newSize;
}

public override CGSize SizeThatFits(CGSize size)
{
var measuredSize = View.Measure(size.Width, size.Height);
var height = Height != null && MatchHeight ? Height.Value : measuredSize.Height;
return new CGSize(size.Width, height);
}

return new CGSize(size.Width, MeasuredHeight);
internal void Disconnect()
{
GeneralWrapperView.Disconnect(this, _childview);
}

public override void WillRemoveSubview(UIView uiview)
{
Disconnect();
base.WillRemoveSubview(uiview);
}

public override void AddSubview(UIView view)
{
base.AddSubview(view);

}

public override void LayoutSubviews()
{
if (!IsPlatformViewValid())
return;

var height = Height ?? MeasuredHeight;
var width = Width ?? Frame.Width;

Expand All @@ -124,18 +110,14 @@ public override void LayoutSubviews()

var platformFrame = new Rect(0, 0, width, height);


if (MatchHeight)
{
(_view as IView).Measure(width, height);
View.Measure(width, height);
}

(_view as IView).Arrange(platformFrame);
View.Arrange(platformFrame);
}

internal void Disconnect()
{
}

protected override void Dispose(bool disposing)
{
Expand All @@ -145,12 +127,6 @@ protected override void Dispose(bool disposing)
if (disposing)
{
Disconnect();

if (_platformView.Superview == this)
_platformView.RemoveFromSuperview();

_renderer = null;
_platformView = null;
_disposed = true;
}

Expand Down
81 changes: 49 additions & 32 deletions src/Core/src/Platform/iOS/GeneralWrapperView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,45 +13,62 @@ public GeneralWrapperView(IView childView, IMauiContext mauiContext)
UpdatePlatformView(childView, mauiContext);
}

public void Disconnect()
{
if (ChildView is null || !ChildView.TryGetTarget(out var childView))
{
return;
}
public static void Disconnect(MauiView view, WeakReference<IView>? childViewRef)
{
view.RemoveFromSuperview();

childView.DisconnectHandlers();
}
if (childViewRef is not null && childViewRef.TryGetTarget(out var childView))
{
childView.DisconnectHandlers();
}

public void UpdatePlatformView(IView? newChildView, IMauiContext mauiContext)
{
if (Subviews.Length > 0)
{
Subviews[0].RemoveFromSuperview();
}
for (int i = view.Subviews.Length - 1; i >= 0; i--)
{
view.Subviews[i].RemoveFromSuperview();
}
}

public void Disconnect()
{
Disconnect(this, ChildView);
}

if (newChildView is null)
{
ChildView = null;
return;
}
public static void UpdatePlatformView(MauiView view, IView? newChildView, IMauiContext mauiContext, out WeakReference<IView>? childViewRef)
{
if (view.Subviews.Length > 0)
{
view.Subviews[0].RemoveFromSuperview();
}

ChildView = new(newChildView);
if (newChildView is null)
{
view.View = null;
childViewRef = null;
return;
}

childViewRef = new(newChildView);

var nativeView = newChildView.ToPlatform(mauiContext);

if (nativeView is WrapperView)
{
// Disable clipping for WrapperView to allow the shadow to be displayed
ClipsToBounds = false;
}
else
{
ClipsToBounds = true;
}

AddSubview(nativeView);
}
if (nativeView is WrapperView)
{
// Disable clipping for WrapperView to allow the shadow to be displayed
view.ClipsToBounds = false;
}
else
{
view.ClipsToBounds = true;
}

view.AddSubview(nativeView);
}

public void UpdatePlatformView(IView? newChildView, IMauiContext mauiContext)
{
UpdatePlatformView(this, newChildView, mauiContext, out var weakReference);
ChildView = weakReference;
}

public Size CrossPlatformArrange(Rect bounds)
{
Expand Down