Xamarin.Forms 多个 WebView,但 OnPageFinished 似乎只适用于最后一个 Webview?
Xamarin.Forms multiple WebViews but OnPageFinished only seems to apply to last Webview?
我有一个 ListView,其中包含三个独立的 WebView。每个 Webview 都有自己的 HTML 内容。这些 Webview 需要响应(高度应该根据它加载的内容进行调整)。
由于这些网页视图的高度不同,我使用 Javascript 来计算高度。出于某种原因,这在使用多个 webview 时不起作用。它似乎只适用于最后一个。
我不确定发生了什么 - 它似乎多次触发 OnPageFinished 事件,但 heightrequest 几乎被忽略了。它甚至在没有 Javascript 的情况下发生(因此,如果我改为硬编码高度请求的设定值)
这是 WebView 的代码:
public class HybridWebViewLeft : WebView
{
public static readonly BindableProperty messageContentProperty =
BindableProperty.Create(nameof(messageContent), typeof(string), typeof(HybridWebViewLeft), string.Empty);
public string messageContent
{
get { return (string)GetValue(messageContentProperty).ToString(); }
set { SetValue(messageContentProperty, value); }
}
public HybridWebViewLeft()
{
HorizontalOptions = LayoutOptions.Fill;
VerticalOptions = LayoutOptions.FillAndExpand;
Margin = 0;
HeightRequest = 10;
Source = "";
this.PropertyChanged += HybridWebViewLeft_PropertyChanged;
}
private void HybridWebViewLeft_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName.Equals(nameof(messageContent)))
{
var htmlSource = new HtmlWebViewSource();
htmlSource.Html = @"<html>
<head>
<meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no'>
<link rel=""stylesheet"" href=""chatmessage-content.css"">
</head>
<body style=""background-color: #DDDDDD;"">Test1<br>Test2<br>Test3<br>Test4<br>Test5<br>Test6<br>Test7<br>Test8 " +
"<script>function setresponseandsubmit(content) { console.log(content); CSharp.setresponseandsubmit(content); }</script></body></html>";
htmlSource.BaseUrl = DependencyService.Get<IBaseUrl>().Get();
Source = htmlSource;
}
}
这里是 Android 上的代码:
class HybridWebViewLeftClient : WebViewClient
{
WebView _webView;
public async override void OnPageFinished(WebView view, string url)
{
try
{
_webView = view;
if (_xwebView != null)
{
view.Settings.JavaScriptEnabled = true;
view.Settings.DomStorageEnabled = true;
await Task.Delay(100);
string result = await _xwebView.EvaluateJavaScriptAsync("(function(){return document.body.scrollHeight;})()");
_xwebView.HeightRequest = Convert.ToDouble(result);
}
base.OnPageFinished(view, url);
}
catch (Exception ex)
{
Console.WriteLine($"EXCEPTION: {ex.Message}");
}
}
}
_xwebView.HeightRequest 为最后一个 WebView 正确计算,其他两个返回为 null,因此使用初始高度 10。
原因:
在您的示例中,您将 WebViews 放在 StackLayout 中。但是,StackLayout 将无法在运行时适合其子元素。需要提前设置高度。
解法:
你应该使用 Grid 。并且不要忘记设置 ScrollView 的 Scroll Orientation
。
<ScrollView Orientation="Both">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label Grid.Row="0" Text="Testing multi webviews" BackgroundColor="Pink" HorizontalOptions="FillAndExpand" HeightRequest="50" />
<custom:HybridWebView Grid.Row="0" messageContent="1" />
<custom:HybridWebView Grid.Row="1" messageContent="2" />
<custom:HybridWebView Grid.Row="2" messageContent="3" />
<custom:HybridWebView Grid.Row="3" messageContent="4" />
<custom:HybridWebView Grid.Row="4" messageContent="5" />
<custom:HybridWebView Grid.Row="5" messageContent="6" />
</Grid>
</ScrollView>
此外,如果您想在同一页面中放置多个 WebView。最好将 ListView 与 DataTemplate 一起使用。
我有一个 ListView,其中包含三个独立的 WebView。每个 Webview 都有自己的 HTML 内容。这些 Webview 需要响应(高度应该根据它加载的内容进行调整)。
由于这些网页视图的高度不同,我使用 Javascript 来计算高度。出于某种原因,这在使用多个 webview 时不起作用。它似乎只适用于最后一个。
我不确定发生了什么 - 它似乎多次触发 OnPageFinished 事件,但 heightrequest 几乎被忽略了。它甚至在没有 Javascript 的情况下发生(因此,如果我改为硬编码高度请求的设定值)
这是 WebView 的代码:
public class HybridWebViewLeft : WebView
{
public static readonly BindableProperty messageContentProperty =
BindableProperty.Create(nameof(messageContent), typeof(string), typeof(HybridWebViewLeft), string.Empty);
public string messageContent
{
get { return (string)GetValue(messageContentProperty).ToString(); }
set { SetValue(messageContentProperty, value); }
}
public HybridWebViewLeft()
{
HorizontalOptions = LayoutOptions.Fill;
VerticalOptions = LayoutOptions.FillAndExpand;
Margin = 0;
HeightRequest = 10;
Source = "";
this.PropertyChanged += HybridWebViewLeft_PropertyChanged;
}
private void HybridWebViewLeft_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName.Equals(nameof(messageContent)))
{
var htmlSource = new HtmlWebViewSource();
htmlSource.Html = @"<html>
<head>
<meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no'>
<link rel=""stylesheet"" href=""chatmessage-content.css"">
</head>
<body style=""background-color: #DDDDDD;"">Test1<br>Test2<br>Test3<br>Test4<br>Test5<br>Test6<br>Test7<br>Test8 " +
"<script>function setresponseandsubmit(content) { console.log(content); CSharp.setresponseandsubmit(content); }</script></body></html>";
htmlSource.BaseUrl = DependencyService.Get<IBaseUrl>().Get();
Source = htmlSource;
}
}
这里是 Android 上的代码:
class HybridWebViewLeftClient : WebViewClient
{
WebView _webView;
public async override void OnPageFinished(WebView view, string url)
{
try
{
_webView = view;
if (_xwebView != null)
{
view.Settings.JavaScriptEnabled = true;
view.Settings.DomStorageEnabled = true;
await Task.Delay(100);
string result = await _xwebView.EvaluateJavaScriptAsync("(function(){return document.body.scrollHeight;})()");
_xwebView.HeightRequest = Convert.ToDouble(result);
}
base.OnPageFinished(view, url);
}
catch (Exception ex)
{
Console.WriteLine($"EXCEPTION: {ex.Message}");
}
}
}
_xwebView.HeightRequest 为最后一个 WebView 正确计算,其他两个返回为 null,因此使用初始高度 10。
原因:
在您的示例中,您将 WebViews 放在 StackLayout 中。但是,StackLayout 将无法在运行时适合其子元素。需要提前设置高度。
解法:
你应该使用 Grid 。并且不要忘记设置 ScrollView 的 Scroll Orientation
。
<ScrollView Orientation="Both">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label Grid.Row="0" Text="Testing multi webviews" BackgroundColor="Pink" HorizontalOptions="FillAndExpand" HeightRequest="50" />
<custom:HybridWebView Grid.Row="0" messageContent="1" />
<custom:HybridWebView Grid.Row="1" messageContent="2" />
<custom:HybridWebView Grid.Row="2" messageContent="3" />
<custom:HybridWebView Grid.Row="3" messageContent="4" />
<custom:HybridWebView Grid.Row="4" messageContent="5" />
<custom:HybridWebView Grid.Row="5" messageContent="6" />
</Grid>
</ScrollView>
此外,如果您想在同一页面中放置多个 WebView。最好将 ListView 与 DataTemplate 一起使用。