question

EJ-5254 avatar image
0 Votes"
EJ-5254 asked ColeXia-MSFT commented

iOS WkWebViewRenderer incorrect height inside CarouselView

Hi,

I've a custom WkWebViewRenderer which has height calculated based on WebView.ScrollView:


  public class CustomWebViewRenderer : WkWebViewRenderer  
     {
         CustomWebView webView;
    
         protected override void OnElementChanged( VisualElementChangedEventArgs e )
         {
             base.OnElementChanged( e );
    
             if (e.NewElement != null)
             {
                 webView = Element as CustomWebView;
    
                 this.NavigationDelegate = new NavigationDelegate( webView );
                 this.ScrollView.Bounces = false;
                 this.ScrollView.ScrollEnabled = false;
             }
         }
     }
    
     public class NavigationDelegate : WKNavigationDelegate
     {
         CustomWebView wv;
         public NavigationDelegate(CustomWebView wv)
         {
             this.wv = wv;
         }
    
         public override void DidFinishNavigation( WKWebView webView, WKNavigation navigation )
         {
            wv.HeightRequest = (double)webView.ScrollView.ContentSize.Height;
         }
     }

When I place this custom WebView inside CarouselView then height is not correct:

 <CarouselView 
          ItemsSource="{Binding Emails}" 
          Loop="False"
          CurrentItemChanged="carousel_CurrentItemChanged">
                
          <CarouselView.ItemsLayout>
              <LinearItemsLayout 
                  Orientation="Horizontal"
                  SnapPointsType="MandatorySingle"
                  SnapPointsAlignment="Start" />
          </CarouselView.ItemsLayout>
                
          <CarouselView.ItemTemplate>
              <DataTemplate>
                  <StackLayout>
                      <ScrollView>
                          <StackLayout>
                              <Label Text="{Binding subject}"/>
                              <ctrl:CustomWebView x:Name="webView">
                                  <WebView.Source>
                                      <HtmlWebViewSource Html="{Binding html}" />
                                  </WebView.Source>
                              </ctrl:CustomWebView>
                          </StackLayout>
                      </ScrollView>
                  </StackLayout>
              </DataTemplate>
          </CarouselView.ItemTemplate>
      </CarouselView>

On Android (also custom WebView with calculated height) height is calculated perfectly, in iOS depending where I place VerticalOptions="FillAndExpand" it's either ~3 times the actual content, or cut of. I've tried setting VerticalOptions on everything - CarouselView, StackLayouts, ScrollView, WebView etc. nothing works.

Any idea how to fix this? I've no clue how everything calculated in Xamarin so having hard time trying to find a solution.

dotnet-xamarin
· 2
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

In my test I set VerticalOptions = "FillAndExpand"on ScrollView ,StackLayout , WebView , everything works fine .


<DataTemplate>
                <StackLayout >
                    <ScrollView  VerticalOptions="FillAndExpand">
                        <StackLayout  VerticalOptions="FillAndExpand">
                            <Label Text="11111"/>
                            <WebView    HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"/>
                        </StackLayout>
                    </ScrollView>
                </StackLayout>
            </DataTemplate>


If possible could you provide us a reproducible project to test ? You can upload it to github and attach the repo link here.

0 Votes 0 ·

Currently in my project I add new items to CarouselView in OnCurrentItemChanged event and noticed that the page for item being added triggers DidFinishNavigation in iOS and OnPageLoaded in Android renderers even if page is not visible yet.

If instead of swiping I add a button which creates new items on click instead of during swiping, then both of above methods are only called when pages gets visible.

So I think there is some issue when swiping and adding new pages as for some reason page rendering is being called even if page is not visible yet. On Android renderer in this case views width is always 0 so I it can't calculate height correctly.

I will try to make an example, but you can easily reproduce above following those steps.

0 Votes 0 ·

1 Answer

EJ-5254 avatar image
0 Votes"
EJ-5254 answered ColeXia-MSFT commented

Hi,

Please see simple project which shows the issue CarouselDemo

I didn't add big email html to make demo smaller, but you can follow steps below to see the issue:

  1. Set breakpoint in Android's CustomWebViewRenderer.cs line 41

  2. Run Android project

  3. When MainPage is loaded carousel_CurrentItemChanged will be triggered in MainPage.xaml.cs and LoadMore in MainPageViewModel.cs is called

  4. Breakpoint will be triggered, note the value of view.ContentHeight (always correct for 1st and 2nd pages)

  5. Scroll to second page

  6. Breakpoint will be triggered again, this time for second page as it's being displayed (height will be correct again)

  7. Once you scroll to the middle carousel_CurrentItemChanged will be triggered as well and 3rd page will be loaded

  8. This is where problem happens - breakpoint will be triggered for 3rd page even if it's not being presented yet. You will notice than in the renderer view.Width is 0, so height will be incorrect.

  9. If you keep scrolling same happens with the rest of pages

Another scenario:

  1. Disable code in carousel_CurrentItemChanged

  2. Run Android project

  3. First page will be created

  4. Click 'Add' in toolbar, it will create second page

  5. Scroll to second page, breakpoint will be triggered as second page is about to be presented (height is correct)

  6. Click 'Add' again to create third page

  7. Scroll to third page and so on - all pages will be created with correct heights


So to me looks like some issue in Xamarin CarouselView when adding new pages while scrolling. By the way same thing happens if using Threshold property. I've tried 3rd party CarouselView and it calculates height correctly when scrolling, but it has it's own issues so don't want to use it.

I really hope you can find a solution as I wasted so many days trying to make this work :(((

· 4
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

I reproduced the issue with your sample .
I suggest you not add new page while scrolling , it will cause expected behavior.
It seems a potential issue , you can open a new issue on github for better support : https://github.com/xamarin/Xamarin.Forms/issues .

0 Votes 0 ·

Your original question is related to iOS side , is problem solved on iOS or still persists ?

0 Votes 0 ·

It happens on both iOS and Android. If you can't add during scrolling, then when can you add? I don't want users to press a button to get to next email. Even official CarouselView documentation mentions that you can add to ItemsSource when Threshold is reached.

0 Votes 0 ·
Show more comments