Xamarin.Forms WebView
WebView
— это представление для отображения веб-содержимого и HTML в приложении:
Содержимое
WebView
поддерживает следующие типы содержимого:
- Веб-сайты HTML и CSS — WebView имеет полную поддержку веб-сайтов, написанных с помощью HTML и CSS, включая поддержку JavaScript.
- Документы. Так как WebView реализуется с помощью собственных компонентов на каждой платформе, WebView может отображать документы в форматах, поддерживаемых базовой платформой.
- СТРОКИ HTML — WebView может отображать HTML-строки из памяти.
- Локальные файлы — WebView может представить любой из типов контента, указанных выше, внедренных в приложение.
Примечание.
WebView
В Windows не поддерживается Silverlight, Flash или какие-либо элементы ActiveX, даже если они поддерживаются Internet Explorer на этой платформе.
Веб-сайты
Чтобы отобразить веб-сайт из Интернета, задайте WebView
Source
для свойства строковый URL-адрес:
var browser = new WebView
{
Source = "https://dotnet.microsoft.com/apps/xamarin"
};
Примечание.
URL-адреса должны быть полностью сформированы с указанным протоколом (т. е. он должен иметь "http://" или "https://" предварительно добавлен к нему).
iOS и ATS
С версии 9 iOS позволит приложению взаимодействовать только с серверами, реализующими оптимальную безопасность по умолчанию. Значения должны быть заданы для Info.plist
включения связи с небезопасными серверами.
Примечание.
Если приложению требуется подключение к небезопасным веб-сайту, всегда следует ввести домен в качестве исключения, используя NSExceptionDomains
вместо того, чтобы полностью отключить NSAllowsArbitraryLoads
ATS. NSAllowsArbitraryLoads
следует использовать только в чрезвычайных ситуациях.
Ниже показано, как включить определенный домен (в данном случае 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>
...
</key>
Рекомендуется использовать только некоторые домены для обхода ATS, что позволяет использовать доверенные сайты, используя дополнительные возможности безопасности для ненадежных доменов. Ниже показан менее безопасный метод отключения ATS для приложения:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads </key>
<true/>
</dict>
...
</key>
Дополнительные сведения об этой новой функции в 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 как строкового литерала подробной строки, что означает, что большинство escape-символов игнорируются.
Примечание.
Может потребоваться задать WidthRequest
и HeightRequest
свойства для просмотра HTML-содержимого WebView
в зависимости от макета WebView
, который является дочерним. Например, это необходимо в объекте StackLayout
.
Локальное HTML-содержимое
WebView может отображать содержимое из HTML, CSS и JavaScript, внедренных в приложение. Например:
<html>
<head>
<title>Xamarin Forms</title>
</head>
<body>
<h1>Xamarin.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, необходимо настроить для каждой платформы, так как не каждая платформа имеет одинаковые шрифты.
Чтобы отобразить локальное содержимое с помощью, 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 веб-содержимое должно находиться в корневом каталоге проекта или каталоге ресурсов с действием сборки 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 файлы в папке "Активы" также можно получить через текущий контекст Android, который предоставляется свойством MainActivity.Instance
:
var assetManager = MainActivity.Instance.Assets;
using (var streamReader = new StreamReader (assetManager.Open ("local.html")))
{
var html = streamReader.ReadToEnd ();
}
Универсальная платформа 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
, а не в браузере устройства. В таких ситуациях полезно разрешить обычную навигацию, но когда пользователь попадает обратно, пока они находятся на начальной ссылке, приложение должно вернуться в обычное представление приложения.
Используйте встроенные методы навигации и свойства, чтобы включить этот сценарий.
Начните с создания страницы для представления браузера:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="WebViewSample.InAppBrowserXaml"
Title="Browser">
<StackLayout Margin="20">
<StackLayout Orientation="Horizontal">
<Button Text="Back" HorizontalOptions="StartAndExpand" Clicked="OnBackButtonClicked" />
<Button Text="Forward" HorizontalOptions="EndAndExpand" Clicked="OnForwardButtonClicked" />
</StackLayout>
<!-- WebView needs to be given height and width request within layouts to render. -->
<WebView x:Name="webView" WidthRequest="1000" HeightRequest="1000" />
</StackLayout>
</ContentPage>
В коде программной части:
public partial class InAppBrowserXaml : ContentPage
{
public InAppBrowserXaml(string URL)
{
InitializeComponent();
webView.Source = URL;
}
async void OnBackButtonClicked(object sender, EventArgs e)
{
if (webView.CanGoBack)
{
webView.GoBack();
}
else
{
await Navigation.PopAsync();
}
}
void OnForwardButtonClicked(object sender, EventArgs e)
{
if (webView.CanGoForward)
{
webView.GoForward();
}
}
}
Вот и все!
События
WebView создает следующие события, которые помогут вам реагировать на изменения в состоянии:
Navigating
— событие, возникаемое при начале загрузки новой страницы WebView.Navigated
— событие, возникаемое при загрузке страницы и остановке навигации.ReloadRequested
— событие, возникает при выполнении запроса на перезагрузку текущего содержимого.
Объект WebNavigatingEventArgs
, сопровождающий Navigating
событие, имеет четыре свойства:
Cancel
— указывает, следует ли отменять навигацию.NavigationEvent
— событие навигации, которое было создано.Source
— элемент, выполняющий навигацию.Url
— назначение навигации.
Объект WebNavigatedEventArgs
, сопровождающий Navigated
событие, имеет четыре свойства:
NavigationEvent
— событие навигации, которое было создано.Result
— описывает результат навигации с помощьюWebNavigationResult
элемента перечисления. Допустимые значения:Cancel
,Failure
,Success
иTimeout
.Source
— элемент, выполняющий навигацию.Url
— назначение навигации.
Если вы планируете использовать веб-страницы, которые занимают много времени для загрузки, рассмотрите возможность использования Navigating
и Navigated
событий для реализации индикатора состояния. Например:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="WebViewSample.LoadingLabelXaml"
Title="Loading Demo">
<StackLayout>
<!--Loading label should not render by default.-->
<Label x:Name="labelLoading" Text="Loading..." IsVisible="false" />
<WebView HeightRequest="1000" WidthRequest="1000" Source="https://dotnet.microsoft.com/apps/xamarin" Navigated="webviewNavigated" Navigating="webviewNavigating" />
</StackLayout>
</ContentPage>
Два обработчика событий:
void webviewNavigating(object sender, WebNavigatingEventArgs e)
{
labelLoading.IsVisible = true;
}
void webviewNavigated(object sender, WebNavigatedEventArgs e)
{
labelLoading.IsVisible = false;
}
Это приводит к следующим выходным данным (загрузка):
Завершенная загрузка:
Перезагрузить содержимое
WebView
Reload
имеет метод, который можно использовать для перезагрузки текущего содержимого:
var webView = new WebView();
...
webView.Reload();
Reload
При вызове ReloadRequested
метода событие указывает, что запрос был выполнен для перезагрузки текущего содержимого.
Производительность
Популярные веб-браузеры применяют такие технологии, как аппаратное ускорение отрисовки и компиляция JavaScript. Xamarin.Forms До 4.4 он Xamarin.FormsWebView
был реализован в iOS классомUIWebView
. Однако многие из этих технологий были недоступны в этой реализации. Поэтому, начиная с Xamarin.Forms версии 4.4, он Xamarin.FormsWebView
реализуется в iOS классом, который поддерживает более быстрый WkWebView
просмотр.
Примечание.
В iOS WkWebViewRenderer
имеет перегрузку конструктора, принимающую WkWebViewConfiguration
аргумент. Это позволяет отрисовщику настраиваться при создании.
Приложение может вернуться к использованию класса iOS UIWebView
для реализации Xamarin.FormsWebView
по соображениям совместимости. Это можно сделать, добавив следующий код в файл AssemblyInfo.cs в проекте платформы iOS для приложения:
// Opt-in to using UIWebView instead of WkWebView.
[assembly: ExportRenderer(typeof(Xamarin.Forms.WebView), typeof(Xamarin.Forms.Platform.iOS.WebViewRenderer))]
Примечание.
В Xamarin.Forms версии 5.0 WebViewRenderer
класс был удален. Xamarin.Forms Поэтому 5.0 не содержит ссылку на UIWebView
элемент управления.
WebView
По умолчанию в Android используется примерно так же быстро, как встроенный браузер.
В Веб-представлении UWP используется модуль отрисовки Microsoft Edge. Устройства с настольными компьютерами и планшетами должны видеть ту же производительность, что и сам браузер Edge.
Разрешения
Чтобы WebView
обеспечить работу, необходимо убедиться, что для каждой платформы заданы разрешения. Обратите внимание, WebView
что на некоторых платформах будут работать в режиме отладки, но не при создании для выпуска. Это связано с тем, что некоторые разрешения, например для доступа к Интернету в Android, задаются по умолчанию Visual Studio для Mac в режиме отладки.
- UWP — требует возможности Интернета (клиента и сервера) при отображении сетевого содержимого.
- Android — требуется
INTERNET
только при отображении содержимого из сети. Локальное содержимое не требует специальных разрешений. - iOS — не требует специальных разрешений.
Макет
В отличие от большинства других Xamarin.Forms представлений, WebView
требуется, чтобы HeightRequest
они WidthRequest
были указаны в StackLayout или RelativeLayout. Если не указать эти свойства, он WebView
не будет отображаться.
В следующих примерах показаны макеты, которые приводят к работе, отрисовке WebView
:
StackLayout с WidthRequest и HeightRequest:
<StackLayout>
<Label Text="test" />
<WebView Source="https://dotnet.microsoft.com/apps/xamarin"
HeightRequest="1000"
WidthRequest="1000" />
</StackLayout>
RelativeLayout с WidthRequest и HeightRequest:
<RelativeLayout>
<Label Text="test"
RelativeLayout.XConstraint= "{ConstraintExpression
Type=Constant, Constant=10}"
RelativeLayout.YConstraint= "{ConstraintExpression
Type=Constant, Constant=20}" />
<WebView Source="https://dotnet.microsoft.com/apps/xamarin"
RelativeLayout.XConstraint="{ConstraintExpression Type=Constant,
Constant=10}"
RelativeLayout.YConstraint="{ConstraintExpression Type=Constant,
Constant=50}"
WidthRequest="1000" HeightRequest="1000" />
</RelativeLayout>
AbsoluteLayout без WidthRequest и HeightRequest:
<AbsoluteLayout>
<Label Text="test" AbsoluteLayout.LayoutBounds="0,0,100,100" />
<WebView Source="https://dotnet.microsoft.com/apps/xamarin"
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="https://dotnet.microsoft.com/apps/xamarin" Grid.Row="1" />
</Grid>
Вызов JavaScript
WebView
включает возможность вызывать функцию JavaScript из C#и возвращать любой результат вызывающей коду C#. Это выполняется с помощью метода WebView.EvaluateJavaScriptAsync
:
var numberEntry = new Entry { Text = "5" };
var resultLabel = new Label();
var webView = new WebView();
...
int number = int.Parse(numberEntry.Text);
string result = await webView.EvaluateJavaScriptAsync($"factorial({number})");
resultLabel.Text = $"Factorial of {number} is {result}.";
Метод WebView.EvaluateJavaScriptAsync
вычисляет JavaScript, указанный в качестве аргумента, и возвращает любой результат в виде string
. В этом примере factorial
вызывается функция JavaScript, которая возвращает факториал number
в результате. Эта функция JavaScript определена в локальном HTML-файле, который WebView
загружается и показан в следующем примере:
<html>
<body>
<script type="text/javascript">
function factorial(num) {
if (num === 0 || num === 1)
return 1;
for (var i = num - 1; i >= 1; i--) {
num *= i;
}
return num;
}
</script>
</body>
</html>
Файлы cookie
Файлы cookie можно задать в объекте WebView
, который затем отправляется с веб-запросом на указанный URL-адрес. Это достигается путем добавления Cookie
объектов в объект CookieContainer
, который затем устанавливается в качестве значения WebView.Cookies
привязываемого свойства. В приведенном ниже коде показан соответствующий пример:
using System.Net;
using Xamarin.Forms;
// ...
CookieContainer cookieContainer = new CookieContainer();
Uri uri = new Uri("https://dotnet.microsoft.com/apps/xamarin", UriKind.RelativeOrAbsolute);
Cookie cookie = new Cookie
{
Name = "XamarinCookie",
Expires = DateTime.Now.AddDays(1),
Value = "My cookie",
Domain = uri.Host,
Path = "/"
};
cookieContainer.Add(uri, cookie);
webView.Cookies = cookieContainer;
webView.Source = new UrlWebViewSource { Url = uri.ToString() };
В этом примере один Cookie
добавляется в CookieContainer
объект, который затем задается в качестве значения WebView.Cookies
свойства. WebView
Когда веб-запрос отправляется в указанный URL-адрес, файл cookie отправляется с запросом.
Отклонение UIWebView и отклонение Магазина приложений (ITMS-90809)
Начиная с апреля 2020 года Apple отклонит приложения , которые по-прежнему используют устаревший UIWebView
API. Хотя Xamarin.Forms переключился WKWebView
в качестве значения по умолчанию, в двоичных Xamarin.Forms файлах по-прежнему существует ссылка на старый пакет SDK. Текущее поведение компоновщика iOS не удаляет это, и в результате UIWebView
устаревший API по-прежнему будет ссылаться из приложения при отправке в App Store.
Внимание
В Xamarin.Forms версии 5.0 WebViewRenderer
класс был удален. Xamarin.Forms Поэтому 5.0 не содержит ссылку на UIWebView
элемент управления.
Предварительная версия компоновщика доступна для устранения этой проблемы. Чтобы включить предварительную версию, необходимо указать дополнительный аргумент --optimize=experimental-xforms-product-type
компоновщику.
Необходимые условия для работы:
- Xamarin.Forms 4.5 или более поздней версии. Xamarin.Forms 4.6 или более поздней версии требуется, если приложение использует визуальный элемент Материал.
- Xamarin.iOS 13.10.0.17 или более поздней версии. Проверьте версию Xamarin.iOS в Visual Studio. Эта версия Xamarin.iOS входит в состав Visual Studio для Mac 8.4.1 и Visual Studio 16.4.3.
- Удаление ссылок на
UIWebView
. Код не должен содержать ссылки наUIWebView
классы, которые используютсяUIWebView
.
Дополнительные сведения об обнаружении и удалении UIWebView
ссылок см. в разделе О прекращении использования UIWebView.
Настройка компоновщика
Выполните следующие действия, чтобы компоновщик удалил UIWebView
ссылки:
- Откройте свойства проекта iOS— щелкните правой кнопкой мыши проект iOS и выберите "Свойства".
- Перейдите к разделу "Сборка iOS" — выберите раздел "Сборка iOS".
- Обновите дополнительные аргументы mtouch. В дополнительных аргументах mtouch добавьте этот флаг
--optimize=experimental-xforms-product-type
(в дополнение к любому значению, которое уже может быть в нем). Примечание. Этот флаг работает вместе с поведением компоновщика, установленным только для пакета SDK или связывания всех. Если по какой-либо причине при настройке поведения компоновщика для всех возникают ошибки, это, скорее всего, проблема в коде приложения или сторонней библиотеке, которая не является компоновщиком безопасной. Дополнительные сведения о компоновщике см. в разделе "Связывание приложений Xamarin.iOS". - Обновите все конфигурации сборки— используйте списки конфигураций и платформы в верхней части окна, чтобы обновить все конфигурации сборки. Наиболее важной конфигурацией является конфигурация выпуска и iPhone , так как она обычно используется для создания сборок для отправки App Store.
Окно отображается с новым флагом на этом снимке экрана:
Теперь при создании сборки (выпуска) и отправке ее в App Store не должно быть предупреждений об устаревшем API.