Search code examples
c#windows-phonewindows-phone-8.1

Windows Phone 8.1 dynamic WebView content with scrollviewer


I am creating a Windows Phone 8.1 (RT, not silverlight) news reader app. Our client gave us an API and the news content are using html tag. This approach lead us to use the WebView to render the content.

In the news reader page, there are related content that will be placed below the webview. With this condition, I think I cannot use the WebView scroller to navigate to related article below the webview. After some browsing in Stackoverflow, i found some workaround for this problem.

here are the code sample for the layout:

<Grid Name="MainGrid" Margin="0,-30,0,0">
    <ScrollViewer Name="ScrollViewer">
        <Grid x:Name="LayoutRoot" Height="Auto">
            <Grid.RowDefinitions>
                <RowDefinition Height="200"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <Grid Name="GridHeader">
                <Image Stretch="UniformToFill" Source="ms-appx:///Assets/img_default_header.jpg" />
             </Grid>                
            <Grid Grid.Row="1" x:Name="GridNews" Margin="12,0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <WebView Margin="-6,12,0,-6" Grid.Row="0" x:Name="WebviewContent" VerticalAlignment="Top" DefaultBackgroundColor="Transparent" /> 
                <Rectangle Margin="0,12,0,0" Height="{Binding Height, ElementName=WebviewContent}" Name="RecWeb" VerticalAlignment="Top" Fill ="#00000000" Tapped="RecWeb_Tapped" />
            </Grid>
            <Grid Name="GridRelatedNews" Grid.Row="2" Margin="12,0">
                <ListView ItemsSource="{Binding NewsDetail.RelatedStory}" ScrollViewer.VerticalScrollBarVisibility="Hidden">  
                </ListView>
            </Grid>
</Grid>

Im using rectangle as overlay in webview so user can scroll using scrollviewer. I'm also adding a javascript in each of html string returned from API:

string htmlFragment = @"
                                        <html>
                                            <head>
                                            <meta name=""viewport"" content=""width="+width+@", initial-scale=1, user-scalable=no"" />
                                                <script type=""text/javascript"">
                                                    function loadLink(x,y){
                                                    window.external.notify('x='+x+'y='+y);
                                                    var el = document.elementFromPoint(x, y);
                                                    el.click();};                                                   
                                                </script>
                                            <style>
                                            " + CSS + @"
                                            </style>
                                            </head>
                                            <body onLoad=""window.external.notify('rendered_height='+document.getElementById('content').offsetHeight);"">
                                                <div id='content' style=""font-size:" + AppManager.Instance.CurrentSetting.FontOption + @"px; color:#222222;"">" + original +
                                              @"</div>
                                            </body>
                                        </html>";

and added the webview webscript notify event to determine the rendered height of the webview (and rectangle):

void WebviewContent_ScriptNotify(object sender, NotifyEventArgs e)
    {
        if (e.Value.Contains("rendered_height"))
        {
            if (valuePair != null && valuePair[0] == "rendered_height")
            {
                double renderedHeight = double.Parse(valuePair[1]);                 
                WebviewContent.Height = renderedHeight;

            }
        }
     }

This solution work most of the times in shorter content, but the main problem are whenever some long content (approx above 5000 pixels WebView height) rendered, there will be some odd white layer above my rectangle/WebView in some parts (strangely the middle part of the long content are rendered).

The screenshot is here: https://i.sstatic.net/nxzRr.jpg

Are there any workaround for this? Or maybe if you have another solution to handle this condition (header, html content, and grid below the html content), please advise me.

Thanks


Solution

  • After testing in my devices and emulator, this weird behavior can be reproduce in following device:

    1. Lumia 920 with Windows Phone 8.1 (1GB of ram)
    2. Emulator 8.1 WVGA 4 inch 512 MB
    3. Emulator 8.1 WVGA 4 inch
    4. Emulator 8.1 WXGA 4.5 inch
    5. Emulator 8.1 720P 4.7 inch
    6. Lumia 520 with Windows Phone 8.1

    The webview show the content normally in following device:

    1. Lumia 730 with Windows Phone 10 Tech Preview
    2. Lumia 920 with Windows Phone 10 Tech Preview
    3. Lumia 930 with Windows Phone 8.1 (2GB of RAM)
    4. Emulator 8.1 1080P (both 5.5 and 6 inch, and Take 2GB of My PC RAM)

    Seems like this is a bug from Microsoft sides which is weird. You need either big ram (2GB) in WP 8.1 or Windows 10 Webview. Hope it can help.