自动调整WebView大小以适应内容

时间:2018-04-23 04:06:05

标签: c# xamarin xamarin.forms xamarin.ios xamarin.android

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

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

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

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

我尝试研究自定义渲染器,然后跟着this tutorial,最后得到以下代码

对于Android我使用

#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 ());
        }         

    }       
}

适用于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;
        }
    }
}

然后将其应用于XAML中

<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>

在Android上它会剪掉帖子的一半。

Android Example

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

iOS Example

2 个答案:

答案 0 :(得分:4)

首先,你应该将ListView的HasUnevenRows设置为true,然后我推荐 您可以使用Grid打包webView并删除XAML中的HeightRequest。你可以参考我的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>

对于您的Android渲染器:

当我们获得实际_xwebView时,请不要在LoadingFinished()HeightRequest中使用静态标识符,请使用ViewCell刷新ForceUpdateSize(),如下所示:

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);
        }
    }
}

对于iOS:

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

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();
    }
}

答案 1 :(得分:0)

要显示 HTML 内容,您可以使用它,它对我来说很有吸引力,我们不需要使用渲染器来适应内容大小。

<Label BackgroundColor="White" Text="{Binding description}" TextType="Html"/>