WebView
提供本地或网络Web内容和文档。
WebView是在您的应用程序中显示网页和HTML内容的视图。不同的是OpenUri
,将用户带到设备上的Web浏览器,在WebView
应用程序中显示HTML内容。
本指南由以下部分组成:
- 内容 - WebView支持各种内容源,包括嵌入式HTML,网页和HTML字符串。
- 导航 - WebView包括导航到特定页面并返回的支持。
- 事件 - 听取并回应用户在WebView中采取的行动。
- 性能 - 了解WebView在每个平台上的性能特征。
- 权限 - 了解如何设置权限,以便WebView可以在您的应用程序中运行。
- 布局 - WebView对它的布局有一些非常特殊的要求。了解如何确保WebView正确显示:
内容
WebView支持以下类型的内容:
- HTML和CSS网站 - WebView完全支持使用HTML和CSS编写的网站,包括JavaScript支持。
- 文档 - 由于WebView是使用每个平台上的本机组件实现的,所以WebView能够显示每个平台上可查看的文档。这意味着PDF文件适用于iOS和Android,但不适用于Windows Phone。
- HTML字符串 - WebView可以显示内存中的HTML字符串。
- 本地文件 - WebView可以显示上述嵌入在应用程序中的任何内容类型。
注意:WebView
Windows和Windows Phone不支持Silverlight,Flash或任何ActiveX控件,即使该平台上的Internet Explorer支持它们。
网站
要显示从互联网网站,设置WebView
的Source
属性为字符串URL:
var browser = new WebView {
Source = "http://xamarin.com"
};
注意:URL必须使用指定的协议完全形成(即它必须有“http://”或“https://”)。
iOS和ATS
自版本9以来,iOS将只允许您的应用程序与默认实现最佳实践安全性的服务器进行通信。必须设置值Info.plist
以实现与不安全的服务器的通信。
以下演示如何启用特定域(在这种情况下为xamarin.com)来绕过ATS要求:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>xamarin.com</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSTemporaryExceptionMinimumTLSVersion</key>
<string>TLSv1.1</string>
</dict>
</dict>
</dict>
最好的做法是只允许某些域绕过ATS,允许您使用受信任的站点,同时从不受信任的域上的附加安全性中受益。以下演示了对应用程序禁用ATS的安全性较低的方法:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads </key>
<true/>
</dict>
有关iOS 9中此新功能的详细信息,请参阅应用程序传输安全性。
HTML字符串
如果要在代码中呈现动态定义的HTML字符串,则需要创建一个实例HtmlWebViewSource
:
var browser = new WebView();
var htmlSource = new HtmlWebViewSource();
htmlSource.Html = @"<html><body>
<h1>Xamarin.Forms</h1>
<p>Welcome to WebView.</p>
</body></html>";
browser.Source = htmlSource;
在上面的代码中,@
用于将HTML标记为字符串文字,这意味着所有常见的转义字符都将被忽略。
本地HTML内容
WebView可以显示嵌入在应用程序中的HTML,CSS和Javascript内容。例如:
<html>
<head>
<title>Xamarin Forms</title>
</head>
<body>
<h1>Xamrin.Forms</h1>
<p>This is an iOS web page.</p>
<img src="XamarinLogo.png" />
</body>
</html>
CSS:
html,body {
margin:0;
padding:10;
}
body,p,h1 {
font-family: Chalkduster;
}
请注意,上述CSS中指定的字体需要为每个平台定制,因为并非每个平台都具有相同的字体。
要使用a显示本地内容WebView
,您需要像其他任何一样打开HTML文件,然后将内容作为字符串加载到Html
属性中HtmlWebViewSource
。有关打开文件的更多信息,请参阅使用文件。
以下屏幕截图显示了在每个平台上显示本地内容的结果:
虽然第一页已经加载,但WebView
不知道HTML来自哪里。在处理引用本地资源的页面时,这是一个问题。何时可能发生的示例包括当本地页面彼此链接时,页面使用单独的JavaScript文件或链接到CSS样式表的页面。
要解决这个问题,您需要告诉在WebView
哪里找到文件系统上的文件。通过设置BaseUrl
所HtmlWebViewSource
使用的属性来做到这一点WebView
。
由于每个操作系统上的文件系统不同,因此您需要在每个平台上确定该URL。Xamarin.Forms DependencyService
在每个平台上公开了在运行时解析依赖关系。
要使用DependencyService
,首先定义一个可以在每个平台上实现的接口:
public interface IBaseUrl { string Get(); }
请注意,在每个平台上实现该界面之前,应用程序将不会运行。在通用项目中,请确保您记得BaseUrl
使用以下设置DependencyService
:
var source = new HtmlWebViewSource();
source.BaseUrl = DependencyService.Get<IBaseUrl>().Get();
那么必须提供每个平台的接口的实现。
iOS版
在iOS上,Web内容应位于项目的根目录或资源目录中,其中包含构建操作BundleResource,如下所示:
该BaseUrl
应设置主束的路径:
[assembly: Dependency (typeof (BaseUrl_iOS))]
namespace WorkingWithWebview.iOS{
public class BaseUrl_iOS : IBaseUrl {
public string Get() {
return NSBundle.MainBundle.BundlePath;
}
}
}
Android的
在Android上,将HTML,CSS和图像放在资产文件夹中,其中包含构建动作AndroidAsset,如下所示:
在Android上,BaseUrl
应该设置为"file:///android_asset/"
:
[assembly: Dependency (typeof(BaseUrl_Android))]
namespace WorkingWithWebview.Android {
public class BaseUrl_Android : IBaseUrl {
public string Get() {
return "file:///android_asset/";
}
}
}
在Android上,资源文件夹中的文件也可以通过Forms.Context.Assets
属性访问,如下面的代码示例所示:
var assetManager = Xamarin.Forms.Forms.Context.Assets;
using (var streamReader = new StreamReader (assetManager.Open ("local.html"))) {
var html = streamReader.ReadToEnd ();
}
Windows Phone
在Windows Phone上,将HTML,CSS和图像放在项目根目录中,将构建操作设置为Content,如下所示:
在Windows Phone上,BaseUrl
应该设置为""
:
[assembly: Dependency (typeof(BaseUrl_Windows))]
namespace WorkingWithWebview.Windows {
public class BaseUrl_Windows : IBaseUrl {
public string Get() {
return "";
}
}
}
Windows运行时和通用Windows平台
在Windows运行时和通用Windows平台(UWP)项目中,将HTML,CSS和图像放在项目根目录中,并将构建操作设置为“ 内容”。
该BaseUrl
应设置为"ms-appx-web:///"
:
[assembly: Dependency(typeof(BaseUrl))]
namespace WorkingWithWebview.UWP
{
public class BaseUrl : IBaseUrl
{
public string Get()
{
return "ms-appx-web:///";
}
}
}
导航
WebView支持导航通过它提供的几种方法和属性:
- GoForward() - 如果
CanGoForward
是true,调用GoForward
导航到下一个访问页面。 - GoBack() - 如果
CanGoBack
为true,则调用GoBack
将导航到最后访问的页面。 - CanGoBack -
true
如果false
浏览器处于起始URL ,那么有页面可以导航回来。 - CanGoForward -
true
如果用户已经向后导航,并且可以前进到已访问的页面。
在页面内,WebView
不支持多点触控手势。重要的是确保内容是移动设备优化的,不需要缩放即可显示。
应用程序通常在一个WebView
而不是设备的浏览器中显示链接。在这些情况下,允许正常导航是有用的,但是当用户在启动链接上点击时,应用程序应该返回到正常的应用程序视图。
使用内置的导航方法和属性启用此方案。
首先创建浏览器视图的页面:
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="WebViewDemo.InAppDemo"
Title="In App Browser">
<ContentPage.Content>
<StackLayout>
<StackLayout Orientation="Horizontal" Padding="10,10">
<Button Text="Back" HorizontalOptions="StartAndExpand" Clicked="backClicked" />
<Button Text="Forward" HorizontalOptions="End" Clicked="forwardClicked" />
</StackLayout>
<WebView x:Name="Browser" WidthRequest="1000" HeightRequest="1000" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
在我们的代码隐藏中:
public partial class InAppDemo : ContentPage
{
//sets the URL for the browser in the page at creation
public InAppDemo (string URL)
{
InitializeComponent ();
Browser.Source = URL;
}
private void backClicked(object sender, EventArgs e)
{
// Check to see if there is anywhere to go back to
if (Browser.CanGoBack) {
Browser.GoBack ();
} else { // If not, leave the view
Navigation.PopAsync ();
}
}
private void forwardClicked(object sender, EventArgs e)
{
if (Browser.CanGoForward) {
Browser.GoForward ();
}
}
}
而已!
活动
WebView引发两个事件来帮助您响应状态更改:
- 浏览 - WebView开始加载新页面时引发的事件。
- 导航 - 页面加载并导航停止时引发的事件。
如果您预期使用需要很长时间加载的网页,请考虑使用这些事件来实现状态指示器。例如:
我们的XAML:
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="WebViewDemo.LoadingDemo" Title="Loading Demo">
<ContentPage.Content>
<StackLayout>
<Label x:Name="LoadingLabel"
Text="Loading..."
HorizontalOptions="Center"
isVisible="false" />
<WebView x:Name="Browser"
HeightRequest="1000"
WidthRequest="1000"
Navigating="webOnNavigating"
Navigated="webOnEndNavigating" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
我们的两个事件处理程序:
void webOnNavigating (object sender, WebNavigatingEventArgs e)
{
LoadingLabel.IsVisible = true;
}
void webOnEndNavigating (object sender, WebNavigatedEventArgs e)
{
LoadingLabel.IsVisible = false;
}
这导致以下输出(加载):
已完成装载:
性能
最近的进展已经看到每个流行的Web浏览器都采用硬件加速渲染和JavaScript编译等技术。不幸的是,由于安全限制,大多数的进步都不在的iOS的-equaivalent可用WebView
,UIWebView
。Xamarin.Forms WebView
使用UIWebView
。如果这是一个问题,您需要编写一个使用的自定义渲染器WKWebView
,这支持更快的浏览。请注意,WKWebView
只有iOS 8和更高版本才支持。
默认情况下,Android上的WebView与内置浏览器的速度一样快。
将WebBrowser
在Windows Phone 8和Windows Phone 8.1控件不支持最新的HTML5功能,可以经常有表现不佳。请注意网站在Windows Phone中的显示方式WebView
。在Internet Explorer中测试还不够。
权限
为了WebView
工作,您必须确保为每个平台设置权限。请注意,在某些平台上,WebView
将在调试模式下工作,但不能在内置版本时发布。这是因为在调试模式下,Xamarin Studio默认设置了一些权限,如Android上的互联网访问权限。
- Windows Phone 8.0 - 需要
ID_CAP_WEBBROWSERCOMPONENT
控制和ID_CAP_NETWORKING
互联网访问。 - Windows Phone 8.1和UWP - 在显示网络内容时需要Internet(客户端和服务器)功能。
- Android -
INTERNET
仅在从网络显示内容时才需要。本地内容不需要特殊权限。 - iOS - 不需要特殊权限。
布局
与大多数其他Xamarin.Forms视图不同,WebView
需要HeightRequest
并WidthRequest
在StackLayout或RelativeLayout中包含该参数。如果您无法指定这些属性,WebView
则不会呈现。
以下示例演示导致工作的渲染WebView
:
StackLayout with WidthRequest&HeightRequest:
<StackLayout>
<Label Text="test" />
<WebView Source="http://www.xamarin.com/"
HeightRequest="1000"
WidthRequest="1000" />
</StackLayout>
RelativeLayout with WidthRequest&HeightRequest:
<RelativeLayout>
<Label Text="test"
RelativeLayout.XConstraint= "{ConstraintExpression
Type=Constant, Constant=10}"
RelativeLayout.YConstraint= "{ConstraintExpression
Type=Constant, Constant=20}" />
<WebView Source="http://www.xamarin.com/"
RelativeLayout.XConstraint="{ConstraintExpression Type=Constant,
Constant=10}"
RelativeLayout.YConstraint="{ConstraintExpression Type=Constant,
Constant=50}"
WidthRequest="1000" HeightRequest="1000" />
</RelativeLayout>
没有 WidthRequest和HeightRequest的AbsoluteLayout :
<AbsoluteLayout>
<Label Text="test" AbsoluteLayout.LayoutBounds="0,0,100,100" />
<WebView Source="http://www.xamarin.com/"
AbsoluteLayout.LayoutBounds="0,150,500,500" />
</AbsoluteLayout>
没有 WidthRequest和HeightRequest的网格。网格是不需要指定请求的高度和宽度的少数布局之一:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="100" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Text="test" Grid.Row="0" />
<WebView Source="http://www.xamarin.com/" Grid.Row="1" />
</Grid>