Skip to content

Commit

Permalink
feat(frameworkelement): Add VisualTreeHelper.AdaptNative()/TryAdaptNa…
Browse files Browse the repository at this point in the history
…tive()

These methods support adding a native view (on Android, iOS, and MacOS) to Uno's visual tree where an instance of type UIElement is expected.
  • Loading branch information
davidjohnoliver committed Jul 14, 2020
1 parent dd4b33b commit 9bdc1a4
Showing 1 changed file with 43 additions and 4 deletions.
47 changes: 43 additions & 4 deletions src/Uno.UI/UI/Xaml/Media/VisualTreeHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
using _ViewGroup = AppKit.NSView;
#elif XAMARIN_ANDROID
using _ViewGroup = Android.Views.ViewGroup;
using _View = Android.Views.ViewGroup;
using _View = Android.Views.View;
#else
using _View = System.Object;
#endif
Expand Down Expand Up @@ -58,15 +58,15 @@ public static IEnumerable<UIElement> FindElementsInHostCoordinates(Point interse
{
if (subtree != null)
{
if(IsElementIntersecting(intersectingPoint, subtree))
if (IsElementIntersecting(intersectingPoint, subtree))
{
yield return subtree;
}

foreach (var child in subtree.GetChildren().OfType<UIElement>())
{
var canTest = includeAllElements
|| ( child.IsHitTestVisible && child.IsViewHit());
|| (child.IsHitTestVisible && child.IsViewHit());

if (child is UIElement uiElement && canTest)
{
Expand Down Expand Up @@ -139,7 +139,7 @@ public static IReadOnlyList<Popup> GetOpenPopups(Window window)
public static DependencyObject GetParent(DependencyObject reference)
{
#if XAMARIN
return (reference as _View)?
return (reference as _ViewGroup)?
.FindFirstParent<DependencyObject>();
#else
return reference.GetParent() as DependencyObject;
Expand All @@ -153,5 +153,44 @@ internal static void CloseAllPopups()
popup.IsOpen = false;
}
}

/// <summary>
/// Adapts a native view by wrapping it in a <see cref="FrameworkElement"/> container so that it can be added to the managed visual tree.
/// </summary>
/// <remarks>
/// This method is present to support adding native view types on Android, iOS and MacOS to Uno's visual tree.
///
/// Calling it with a type that's already a <see cref="FrameworkElement"/> will throw an <see cref="InvalidOperationException"/>.
/// If there's a possibility that the wrapped type may be a <see cref="FrameworkElement"/>, use <see cref="TryAdaptNative(_View)"/>
/// instead.
/// </remarks>
public static FrameworkElement AdaptNative(_View nativeView)
{
if (nativeView is FrameworkElement)
{
throw new InvalidOperationException($"{nameof(AdaptNative)}() should only be called for non-{nameof(FrameworkElement)} native views." +
$"Use {nameof(TryAdaptNative)} if it's not known whether view will be native.");
}

return new ContentPresenter
{
Content = nativeView
};
}

/// <summary>
/// Adapts a native view by wrapping it in a <see cref="FrameworkElement"/> container so that it can be added to the managed visual tree.
///
/// This method is safe to call for any view. If <paramref name="view"/> is a <see cref="FrameworkElement"/>, it will simply be returned unmodified.
/// </summary>
public static FrameworkElement TryAdaptNative(_View view)
{
if (view is FrameworkElement fe)
{
return fe;
}

return AdaptNative(view);
}
}
}

0 comments on commit 9bdc1a4

Please sign in to comment.