自动调整 WebView 的大小以适应内容 [英] Auto resize WebView to fit content

查看:49
本文介绍了自动调整 WebView 的大小以适应内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个 Xamarin.Forms PCL 项目,该项目以 WebView 的形式显示帖子,因此我添加了可点击的内容,例如主题标签.

我遇到的问题是 WebView 无法适应其内容的大小.WebView 不加载实际站点 我使用

将 HTML 绑定到 ListView 中的每个帖子

"

"+ 正文 + "</p></html>"

我尝试研究自定义渲染器并遵循

在 iOS 上,它不会正确分隔帖子并切断其上方帖子的时间戳.我的猜测是 ViewCell 的高度会根据内容进行调整,但没有考虑其他帖子.同样对于 iOS,如果文本需要两行,则需要您滚动查看其余部分.

解决方案

首先你应该将 ListView 的 HasUnevenRows 设置为 true,然后我推荐您可以使用 Grid 包装您的 webView 并删除 XAML 中的 HeightRequest.你可以参考我的XAML:

<local:MyListView.ItemTemplate><数据模板><ViewCell><网格><local:AutoWebView><local:AutoWebView.Source><HtmlWebViewSource Html="{Binding}"/></local:AutoWebView.Source></local:AutoWebView></网格></ViewCell></数据模板></local:MyListView.ItemTemplate></local:MyListView>

对于您的 Android 渲染器:

不要为 _xwebView 使用静态标识符,并且在 LoadingFinished() 中,当我们获得实际的 HeightRequest 时,刷新 ViewCell 使用 ForceUpdateSize() 像:

公共类 MyWebViewAndroidRenderer : WebViewRenderer{protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e){base.OnElementPropertyChanged(sender, e);Control.SetWebViewClient(new ExtendedWebViewClient(Element as AutoWebView));}类 ExtendedWebViewClient : Android.Webkit.WebViewClient{AutoWebView xwebView;public ExtendedWebViewClient(AutoWebView webView){xwebView = webView;}异步公共覆盖 void OnPageFinished(Android.Webkit.WebView 视图,字符串 url){如果(xwebView != null){国际我= 10;while (view.ContentHeight == 0 && i-- > 0)//在这里等待直到内容被渲染等待 System.Threading.Tasks.Task.Delay(100);xwebView.HeightRequest = view.ContentHeight;//这里使用 parent 来查找 ViewCell,您可以根据您的 XAML 调整父级的数量(xwebView.Parent.Parent 作为 ViewCell).ForceUpdateSize();}base.OnPageFinished(视图,网址);}}}

对于 iOS:

我们还需要在 webView 加载完成后刷新单元格:

public override void LoadingFinished(UIWebView webView){var wv = webViewRenderer.Element 作为 AutoWebView;如果 (wv.HeightRequest <0){wv.HeightRequest = (double)webView.ScrollView.ContentSize.Height;(wv.Parent.Parent 作为 ViewCell).ForceUpdateSize();}}

I am working on a Xamarin.Forms PCL project that displays posts in the form of a WebView so I add clickable content such as hashtags.

The problem I am having is the WebView doesn't adjust to the size of its content. The WebView does not load an actual site I am binding the HTML to each post in a ListView using

"<html><p>" + body + "</p></html>"

I tried researching for custom renderers and followed this tutorial and ended up with the following code

For Android I used

#pragma warning disable CS0618 // Type or member is obsolete
public class CustomWebViewAndroid : WebViewRenderer
{
    static CustomWebView _xwebView = null;
    WebView _webView;            

    class ExtendedWebViewClient : Android.Webkit.WebViewClient
    {
        public override async void OnPageFinished (WebView view, string url)
        {
            if (_xwebView != null) {
                int i = 10;
                while (view.ContentHeight == 0 && i-- > 0) // wait here till content is rendered
                    await System.Threading.Tasks.Task.Delay (100);
                _xwebView.HeightRequest = view.ContentHeight;
            }
            base.OnPageFinished (view, url);
        }
    }

    protected override void OnElementChanged (ElementChangedEventArgs<Xamarin.Forms.WebView> e)
    {
        base.OnElementChanged (e); 
        _xwebView = e.NewElement as CustomWebView;
        _webView = Control;

        if (e.OldElement == null) {                
            _webView.SetWebViewClient (new ExtendedWebViewClient ());
        }         

    }       
}

And for iOS

public class CustomWebViewiOS : WebViewRenderer
{
    protected override void OnElementChanged(VisualElementChangedEventArgs e)
    {
        base.OnElementChanged(e);
        Delegate = new CustomWebViewDelegate(this);
    }
}

public class CustomWebViewDelegate : UIWebViewDelegate
{
    CustomWebViewiOS webViewRenderer;

    public CustomWebViewDelegate(CustomWebViewiOS _webViewRenderer = null)
    {
        webViewRenderer = _webViewRenderer ?? new CustomWebViewiOS();
    }

    public override async void LoadingFinished(UIWebView webView)
    {
        var wv = webViewRenderer.Element as CustomWebView;
        if (wv != null)
        {
            await System.Threading.Tasks.Task.Delay(100); // wait here till content is rendered
            wv.HeightRequest = (double)webView.ScrollView.ContentSize.Height;
        }
    }
}

And then applied it in XAML as so

<StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
    <local:CustomWebView HeightRequest="20" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
        <local:CustomWebView.Source>
            <HtmlWebViewSource Html="{Binding HtmlContent}"/>
        </local:CustomWebView.Source>
    </local:CustomWebView>
</StackLayout>

On Android it clips off half the post's body.

On iOS it doesn't space the posts correctly and cuts off the timestamp of the one above it. My guess is the height of the ViewCell adjusts to the content but doesn't take into consideration the other posts. Also for iOS if the text takes two lines it requires you to scroll to view the rest.

解决方案

Firstly you should set the ListView's HasUnevenRows to true, then I recommend you to use Grid to wrap your webView and remove the HeightRequest in XAML. You can refer to my XAML:

<local:MyListView x:Name="MyListView" HasUnevenRows="True">
    <local:MyListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <Grid>
                    <local:AutoWebView>
                        <local:AutoWebView.Source>
                            <HtmlWebViewSource Html="{Binding}"/>
                        </local:AutoWebView.Source>
                    </local:AutoWebView>
                </Grid>
            </ViewCell>
        </DataTemplate>
    </local:MyListView.ItemTemplate>
</local:MyListView>

For your Android renderer:

Do not use static identifier for _xwebView and in LoadingFinished() when we get the actual HeightRequest, refresh the ViewCell using ForceUpdateSize() like:

public class MyWebViewAndroidRenderer : WebViewRenderer
{
    protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        base.OnElementPropertyChanged(sender, e);

        Control.SetWebViewClient(new ExtendedWebViewClient(Element as AutoWebView));

    }

    class ExtendedWebViewClient : Android.Webkit.WebViewClient
    {
        AutoWebView xwebView;
        public ExtendedWebViewClient(AutoWebView webView)
        {
            xwebView = webView;
        }

        async public override void OnPageFinished(Android.Webkit.WebView view, string url)
        {
            if (xwebView != null)
            {
                int i = 10;
                while (view.ContentHeight == 0 && i-- > 0) // wait here till content is rendered
                    await System.Threading.Tasks.Task.Delay(100);
                xwebView.HeightRequest = view.ContentHeight;
                // Here use parent to find the ViewCell, you can adjust the number of parents depending on your XAML
                (xwebView.Parent.Parent as ViewCell).ForceUpdateSize();
            }

            base.OnPageFinished(view, url);
        }
    }
}

For iOS:

We also need to refresh the cell when the webView finished loading:

public override void LoadingFinished(UIWebView webView)
{
    var wv = webViewRenderer.Element as AutoWebView;
    if (wv.HeightRequest < 0)
    {
        wv.HeightRequest = (double)webView.ScrollView.ContentSize.Height;
        (wv.Parent.Parent as ViewCell).ForceUpdateSize();
    }
}

这篇关于自动调整 WebView 的大小以适应内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆