如何在 Xamarin Forms 渲染器中获取 NavigationPage 控件的 CGContext?
How to get the CGContext for a NavigationPage control in a Xamarin Forms Renderer?
我正在尝试为我的应用创建全屏覆盖。为此,我需要覆盖 NavigationPage
的渲染器,因为即使使用绝对定位,也无法将其他项目定位在导航栏上。
我有一个自定义渲染器,我正在尝试像这样绘制导航栏:
[assembly: ExportRenderer(typeof(NavigationPage), typeof(CustomNavigationPageRenderer))]
namespace MyApp.iOS.Controls
{
public class CustomNavigationPageRenderer : NavigationRenderer
{
public override void ViewDidLayoutSubviews()
{
base.ViewDidLayoutSubviews();
using CGContext context = UIGraphics.GetCurrentContext();
...
}
}
}
但是,上下文始终是 null
。在像 this and this 这样的例子中,他们说你需要从覆盖的 Draw()
函数中调用 UIGraphics.GetCurrentContext()
,但 NavigationRenderer
.
中不存在这样的函数
在 Android 上可以通过覆盖 NavigationPageRenderer.DispatchDraw()
来完成,但在 iOS NavigationRenderer
上不存在。 如何在 iOS 中绘制此控件?
我们可以使用依赖服务并在根上添加半透明背景覆盖 window。
示例代码
public interface IMyInterface
{
void present();
}
IMyInterface service = DependencyService.Get<IMyInterface>();
service.present();
[assembly: Dependency(typeof(IMyInterface))]
namespace ColeForms.iOS
{
public class MyInterface : IMyInterface
{
UIView overlay;
public MyInterface()
{
overlay = new UIView();
//full screen
overlay.Frame = UIScreen.MainScreen.Bounds;
//translucent background
overlay.BackgroundColor = UIColor.FromWhiteAlpha(0.5f,0.5f);
//add the tap gesture to dismiss overlap
overlay.AddGestureRecognizer(new UITapGestureRecognizer(()=> {
overlay.RemoveFromSuperview();
}));
}
public void present()
{
UIApplication.SharedApplication.KeyWindow.RootViewController.View.Add(overlay);
}
}
}
屏幕截图
这是我根据上面 ColeX 的回答得出的最终解决方案
MyCustomOverlay.cs
namespace MyApp
{
/// <summary>
/// There's no way to "Draw" over a page in iOS, so we create a custom control that takes up the entire page and draw on that instead
/// </summary>
internal sealed class MyCustomOverlay : UIView
{
public MyCustomOverlay()
{
this.BackgroundColor = UIColor.Clear; // This is *required* or else the entire control is black. lol?
AddGestureRecognizer(new UITapGestureRecognizer(RemoveFromSuperview)); // Close overlay when clicked
}
public override void LayoutSubviews()
{
base.LayoutSubviews();
this.Frame = UIScreen.MainScreen.Bounds;
}
public override void Draw(CGRect rect)
{
base.Draw(rect);
using CGContext context = UIGraphics.GetCurrentContext();
// Include your draw code here
}
}
}
MyNavigationPageRenderer.cs
[assembly: ExportRenderer(typeof(NavigationPage), typeof(MyNavigationPageRenderer))]
namespace MyApp
{
public class MyNavigationPageRenderer : NavigationRenderer
{
private UIView RootView => UIApplication.SharedApplication.KeyWindow.RootViewController.View;
public override void ViewWillLayoutSubviews()
{
base.ViewWillLayoutSubviews();
if (!RootView.Subviews.Any(o => o is MyCustomOverlay))
{
RootView.Add(new MyCustomOverlay());
}
}
}
}
我正在尝试为我的应用创建全屏覆盖。为此,我需要覆盖 NavigationPage
的渲染器,因为即使使用绝对定位,也无法将其他项目定位在导航栏上。
我有一个自定义渲染器,我正在尝试像这样绘制导航栏:
[assembly: ExportRenderer(typeof(NavigationPage), typeof(CustomNavigationPageRenderer))]
namespace MyApp.iOS.Controls
{
public class CustomNavigationPageRenderer : NavigationRenderer
{
public override void ViewDidLayoutSubviews()
{
base.ViewDidLayoutSubviews();
using CGContext context = UIGraphics.GetCurrentContext();
...
}
}
}
但是,上下文始终是 null
。在像 this and this 这样的例子中,他们说你需要从覆盖的 Draw()
函数中调用 UIGraphics.GetCurrentContext()
,但 NavigationRenderer
.
在 Android 上可以通过覆盖 NavigationPageRenderer.DispatchDraw()
来完成,但在 iOS NavigationRenderer
上不存在。 如何在 iOS 中绘制此控件?
我们可以使用依赖服务并在根上添加半透明背景覆盖 window。
示例代码
public interface IMyInterface
{
void present();
}
IMyInterface service = DependencyService.Get<IMyInterface>();
service.present();
[assembly: Dependency(typeof(IMyInterface))]
namespace ColeForms.iOS
{
public class MyInterface : IMyInterface
{
UIView overlay;
public MyInterface()
{
overlay = new UIView();
//full screen
overlay.Frame = UIScreen.MainScreen.Bounds;
//translucent background
overlay.BackgroundColor = UIColor.FromWhiteAlpha(0.5f,0.5f);
//add the tap gesture to dismiss overlap
overlay.AddGestureRecognizer(new UITapGestureRecognizer(()=> {
overlay.RemoveFromSuperview();
}));
}
public void present()
{
UIApplication.SharedApplication.KeyWindow.RootViewController.View.Add(overlay);
}
}
}
屏幕截图
这是我根据上面 ColeX 的回答得出的最终解决方案
MyCustomOverlay.cs
namespace MyApp
{
/// <summary>
/// There's no way to "Draw" over a page in iOS, so we create a custom control that takes up the entire page and draw on that instead
/// </summary>
internal sealed class MyCustomOverlay : UIView
{
public MyCustomOverlay()
{
this.BackgroundColor = UIColor.Clear; // This is *required* or else the entire control is black. lol?
AddGestureRecognizer(new UITapGestureRecognizer(RemoveFromSuperview)); // Close overlay when clicked
}
public override void LayoutSubviews()
{
base.LayoutSubviews();
this.Frame = UIScreen.MainScreen.Bounds;
}
public override void Draw(CGRect rect)
{
base.Draw(rect);
using CGContext context = UIGraphics.GetCurrentContext();
// Include your draw code here
}
}
}
MyNavigationPageRenderer.cs
[assembly: ExportRenderer(typeof(NavigationPage), typeof(MyNavigationPageRenderer))]
namespace MyApp
{
public class MyNavigationPageRenderer : NavigationRenderer
{
private UIView RootView => UIApplication.SharedApplication.KeyWindow.RootViewController.View;
public override void ViewWillLayoutSubviews()
{
base.ViewWillLayoutSubviews();
if (!RootView.Subviews.Any(o => o is MyCustomOverlay))
{
RootView.Add(new MyCustomOverlay());
}
}
}
}