【问题标题】:Auto resize WebView to fit content自动调整 WebView 大小以适应内容
【发布时间】:2018-04-23 04:06:05
【问题描述】:

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

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

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

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

我尝试研究自定义渲染器并关注 this tutorial 并最终得到以下代码

我用的是安卓

#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 上,它会剪掉一半的帖子正文。

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

【问题讨论】:

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


    【解决方案1】:

    首先你应该将 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 时,使用ForceUpdateSize() 刷新ViewCell,例如:

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

    【讨论】:

    • Android 版本运行良好,但当我尝试在 iOS 版本的 Xamarin Live Player 上运行它时,高度保持在 0,从不显示内容。
    • 它在我的 iOS 上运行良好。我做了一个样本here。尝试检查这个。
    • 你在 Xamarin Live Player 上试过了吗?
    • Xamarin Live Player 不是为调试而设计的,它只是临时显示一些视图。它有几个限制,尤其是使用渲染器。但这在模拟器或真实设备上可以正常工作。请阅读此documentation,了解有关 Xamarin Live Player 及其限制的更多详细信息。
    • 不幸的是,这个解决方案使用了同时被 Apple 弃用的 UIWebView
    【解决方案2】:

    要显示 HTML 内容,您可以使用它,它对我来说就像魅力一样,我们不需要使用渲染器来适应内容大小。

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

    【讨论】:

    • 我喜欢这个作为简单文本的解决方案。但是如果你必须显示更复杂的 HTML,或者你不知道要显示什么 HTML 内容,那就行不通了。
    • @pseudoabdul,是的,仅用于格式化文本,我们可以使用它。如果包含其他内容,它将不起作用,,,
    猜你喜欢
    • 2014-07-02
    • 2013-06-05
    • 2021-09-16
    • 2011-11-03
    • 2011-08-20
    • 1970-01-01
    • 2021-12-17
    • 2015-12-27
    • 2019-07-07
    相关资源
    最近更新 更多