【问题标题】:How does Xamarin Forms call different renderers in XAML files for Android and iOSXamarin Forms 如何在 Android 和 iOS 的 XAML 文件中调用不同的渲染器
【发布时间】:2020-02-07 20:36:05
【问题描述】:

所以我的 Xamarin Forms 应用程序中有一个 WebView,但我想通过创建自定义渲染器来更改我的 iOS WebView,如下所示:https://forums.xamarin.com/discussion/129626/how-does-one-implement-wkwebview-ios-in-a-cross-platform-application

我不确定如何更改我的 XAML 文件,以调用我的 iOS 自定义渲染器和 Android 的普通 WebView。目前我的 XAML 文件如下所示:

<WebView Source="{Binding StartUrl}"
               Navigated="OnBrowserNavigated"
               Navigating="OnBrowserNavigating"
               AbsoluteLayout.LayoutFlags="All"
               AbsoluteLayout.LayoutBounds="0.5, 0.5, 1, 1"/>

使用关键字 WebView (Xamarin.Forms.WebView)。但是如果我使用这种方法为 iOS 创建一个自定义渲染器:

// Create a new class:
public class MyWebView : WebView
{
    public static readonly BindableProperty UrlProperty = BindableProperty.Create(...);
    ...
}

// Create custom renderer:
[assembly: ExportRenderer(typeof(MyWebView), typeof(MyWebViewRenderer))]
namespace WKWebViewDemo.iOS
{
...    
}

我应该如何像页面所说的那样调用这个渲染器

<StackLayout>
    <local:MyWebView Url="https://www.microsoft.com" VerticalOptions="FillAndExpand"/>
</StackLayout>

并且仍然像我的 XAML 页面现在正在调用 Android 的 Xamarin.Forms.WebView?

【问题讨论】:

  • 如果 Android 上没有定义自定义渲染器,它将只使用基本渲染器
  • 好的,所以如果我只使用“MyWebView”类,Xamarin 将在 android 应用程序中查找它,但由于它不存在,它会忽略它并使用 Xamarin.Forms.WebView?跨度>
  • 它将寻找渲染器。如果 MyWebView 没有,它将查找基类 WebView 之一。
  • 好的,所以我的 android webview 将使用 source=url,而 iOS 将使用 Url=url,就像您在问题中看到的那样,我会将它们都添加到我的 XAML 布局中吗?
  • 不,那会是个问题。两个平台都需要具有相同的 API 界面。为什么你需要一个与基本控件不同的 url 属性?

标签: xamarin.forms


【解决方案1】:

由于Url 属性是您在MyWebView 中定义的,如果您删除MyWebView 类,则会抛出未定义错误。

如果你想在 Android 和 ios 中都使用Source 属性,你不能定义一个自定义的 webview,并在 ios 中直接使用渲染器中的 WebView 像:

// Create custom renderer:
[assembly: ExportRenderer(typeof(WebView), typeof(MyWebViewRenderer))]
namespace WKWebViewDemo.iOS
{
  public class MyWebViewRenderer : ViewRenderer<WebView, WKWebView>
  {
    WKWebView _wkWebView;
    protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
    {
        base.OnElementChanged(e);

        if (Control == null)
        {
            var config = new WKWebViewConfiguration();
            _wkWebView = new WKWebView(Frame, config);
            SetNativeControl(_wkWebView);
        }
        if (e.NewElement != null)
        {
            Control.LoadRequest(new NSUrlRequest(new NSUrl(((UrlWebViewSource)Element.Source).Url)));
        }
    }
  }
}

【讨论】:

【解决方案2】:
<WebView Source="{Binding StartUrl}"
         Url="{Binding StartUrl}"
               ...>

所以这确实有效,iOS WebView 运行良好,但我想删除 Url 并为两者使用“Source”的方式是这样的。

namespace Apm.Mobile.Core.Controls
{
public class BetterWebView : WebView
{
    public static readonly BindableProperty UrlProperty = BindableProperty.Create(
        propertyName: "Source", // This is now source instead of Url
        returnType: typeof(string),
        declaringType: typeof(BetterWebView),
        defaultValue: default(string));

    public new string Source // This string is now Source instead of Url
    {
        get { return (string)GetValue(UrlProperty); }
        set { SetValue(UrlProperty, value); }
    }
}
}

【讨论】:

  • 它不起作用,但我怀疑我可能必须将 UrlProperty 重命名为 SourceProperty?但是如果我这样做,它会抛出一个警告说它将使用常规 Xamarin.Forms.WebView.Source 除非我添加“new”关键字..这违背了这个 customrenderer 的目的,对吧?
  • 如果 Source 已经存在于基本控件中,则无需重新定义。
  • 是的,所以我删除了 MyWebView 类并只保留了渲染器,但现在渲染器中出现错误 Control.LoadRequest(new NSUrlRequest(new NSUrl(Element.Url))) ;,它说 Element.Url 中的 Url 不是由 WebView 定义的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-27
  • 2018-07-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多