Height of Stack Layout is always assigning 0

Steve1000Steve1000 Member ✭✭
edited March 2018 in Xamarin.Forms

Hi,

I have a Vertical stack layout which i am adding elements to. I want to get the height of the stack layout but it is alway assigning the value of 0.

When I inspect in Visual Studio, the height is definitly showing as non-zero but it doesn't get assigned to my variable.

double chats_Height = view_Chat.Height;

chats_Height is always 0, but view_Chat.Height has a non-zero value.

very strangee as i've never seen this in C# before,

I have the stacklayout inside a scrollview. i want the height of the stacklayout so i can scroll to the end of the scroll view programmatically.

Best Answer

Answers

  • JohnHardmanJohnHardman GBUniversity mod

    @Steve1000 - Where is that line of code? The Height property is populated as part of the layout process, so if you create your UI in the constructor of a ContentPage and query Height in the constructor it will be zero as the layout processing has not yet been done.

    However, if you want to scroll the ScrollView to the end of the StackLayout, you can simply use the ScrollToPosition.End parameter when calling the ScrollToAsync method, without needing the Height at all.

  • Steve1000Steve1000 Member ✭✭
    edited March 2018

    @JohnHardman - yes that is exactly what I want to do - do you you have an example of how to call ScrollToPosition.End? Currently I have the following which doesn't scroll to the end of the screen.

      await view_main.ScrollToAsync(view_main, ScrollToPosition.End, true);
    

    The line of code is in a separate method that is called after the page has been created. It retrieves some messages from the server then adds messages to a stack layout which is in side the scroll layout:

    private async void LoadChats()
    {

        try 
            {
                var results = await api.GetMessages();
    
                foreach (Chat c in results)
                {
                    var cBubble = new ChatBubbleView() { message = c.Message };
                    view_Chat.Children.Add(cBubble);
                }
    
                double chats_height = view_Chat.Height;
    
                await view_main.ScrollToAsync(view_main, ScrollToPosition.End, true);
    
            }
    
        catch (Exception e)
        {
            // todo;
    
        }
    
    }
    

    The stack layout and scroll layout is created in XAML:

    <ScrollView  BackgroundColor="White" x:Name="view_main" IsVisible ="false">
          <StackLayout BackgroundColor="White">
                 <StackLayout x:Name="view_Chat" VerticalOptions="Fill">
    
                  </StackLayout>
    
          </StackLayout>
    
    </ScrollView>
    
  • JohnHardmanJohnHardman GBUniversity mod
    edited March 2018

    @Steve1000 - you need to allow the layout processing to complete between adding the last bubble and doing the scroll. You probably also need to check the first argument of ScrollToAsync.

    There are various ways of allowing the layout processing to complete. One is being included in a forthcoming change to ScrollToAsync so you may not need to explicitly do this yourself in future. The code for that change can be seen at https://github.com/xamarin/Xamarin.Forms/pull/988/files

    If you want to put that fix in your code now (hopefully to remove it later on), you can do the following (largely copied from the fix mentioned above). Note that this does use a method marked as for Xamarin internal use though, but as a temporary tweak you're probably safe.

                        var lastBubble = results[results.Count - 1]; // tweak this as required
    
                        int cycle = 0;
                        while ((!lastBubble.IsInNativeLayout) && (++cycle <= 10))
                        {
                            await Task.Delay(TimeSpan.FromMilliseconds(1));
                        }
                        await view_main.ScrollToAsync(lastBubble, ScrollToPosition.End, false);
    

    I haven't tested that code (or even compiled it), but give it a go.

  • JohnHardmanJohnHardman GBUniversity mod

    @DavidOrtinau @SamanthaHouts - Is there any chance of getting the IsInNativeLayout property made for normal use please? At the moment it is marked as for Xamarin internal use only.

  • Steve1000Steve1000 Member ✭✭

    @JohnHardman said:
    @Steve1000 - I've just created a little helper method using that internal method.

        public static class ScrollHelper
        {
            // Based on https://github.com/xamarin/Xamarin.Forms/pull/988
            public static async Task ScrollOnceInLayoutAsync(
                ScrollView scrollView,
                View view,
                bool animated = false,
                ScrollToPosition scrollToPosition = ScrollToPosition.End,
                int millisecondDelay = 1,
                int maxCycles = 10)
            {
                if ((scrollView != null) && (view != null))
                {
                    // Note that IsInNativeLayout is currently marked for Xamarin internal use only
                    int cycle = 0;
                    while ((!view.IsInNativeLayout)  && (++cycle <= maxCycles))
                    {
                        await Task.Delay(TimeSpan.FromMilliseconds(millisecondDelay));
                    }
                    await scrollView.ScrollToAsync(view, scrollToPosition, animated);
                }
            }
        }
    

    It's only had a very preliminary test, but you might find it useful.

    Excellent - thanks, this works!

Sign In or Register to comment.