ListView inside StackLayout: a height problem

HalvardHagestherHalvardHagesther NOMember ✭✭
edited July 2014 in Xamarin.Forms

In a ContentPage I have a ListView inside a StackLayout inside a ScrollView. The ListView is populated (ItemSource is set) in the ContentPage when OnAppearing gets called and I can see that the list is populated in the emulator. The StackLayouts orientation is Vertical and below the ListView I have a Button.

My problem is that no matter how many elements the ListView has, it gets the height of 53.33. I would like the height of the ListView to match the total height of the items in it. By setting HeightRequest I can set the height of the ListView to anything I want, but since I do not know the height of the items inside the ListView the result is most often that the distance to the button below it is incorrect and therefore looks ugly. I have tried to set VerticalOptions on both the ListView and the StackLayout to Start, but this does not change the height from 53.33 (and if I try to combine using HeightRequest and Start it turns out that HeightRequest wins out).

(please excuse the cross posting on Stackoverflow)

«1

Posts

  • ddotmunchddotmunch DEMember ✭✭
    edited July 2014

    Running into same sort of layout problems with a ListView inside a StackLayout, bound to a viewmodels ItemSource. In my case the ListView doesn't appear (has Height=0) unless I specify a hard coded HeightRequest. Any updates on this?

    (Running Xamarin.Forms 1.2.2)

  • HalvardHagestherHalvardHagesther NOMember ✭✭

    @ddotmunch‌ Unfortunately I have not been able to solve this. I have not received any suggestions either.

  • CraigDunnCraigDunn USXamarin Team Xamurai

    ListView is not intended to always size itself to just fit its contents.

    Consider the common use-case: a ListView is added to a Page but the data in the list will be downloaded from a web service, so initially it is empty (the data comes later after an async web call). What size should the ListView be? It is intended to be a scrolling container that will be able to display all its cells, by scrolling, not by initially sizing itself. The number of cells will never affect its height.

    This gets further complicated if you nest scrolling controls inside each other (such as a ListView inside of a ScrollView. In theory the size that the scrolling contents can use is unbound (ie. because they're intended to scroll) so the contained controls really need to be told what size they should be. Nesting scrolling controls inside other scrolling controls is going to create issues unless you are very careful with your layouts.

    in short... a ListView should be sized either with specific width and height requests or in combination with other controls (using LayoutOptions). Refer to the views & layouts section of the intro doc for more info on the types of layouts and how they compare:

    Controls themselves are hosted inside of a layout. Xamarin.Forms has two different categories of layouts that arrange the controls in very different ways:

    >

    • Managed Layouts - these are layouts that will take care of positioning and sizing child controls on the screen and follow the CSS box model. Applications should not attempt to directly set the size or position of child controls. One common example of a managed Xamarin.Forms layout is the StackLayout.
    • Unmanaged Layouts - as opposed to managed layouts, unmanaged layouts will not arrange or position their children on the screen. Typically, the user will specify the size and location of the child control as it is being added to the layout. The AbsoluteLayout is an example of an unmanaged layout control.

    Please post if you have further questions about this stuff works.

  • ChrisgozdChrisgozd USMember ✭✭

    @HalvardHagesther‌ Is it possible for you to post the code you just described above to illustrate it better?

  • @HalvardHagesther‌, I have the same problem, i used your method but dont work for me !

  • PaulFrostPaulFrost USMember

    @kameloulebsir.7777, Are you using XAML or C# for your layout?

  • DquaglioDquaglio ITMember
    edited January 2015

    I used the same code here but it doesn't work for me either, I have a personalized DataTemplate, could be that the problem? I'm using C# for the layout..

  • I'm having the same problem and Halvard's approach does not work for me. In my case the ListView is filling about 2/3 of the screen. I too am using a personalized DataTemplate and am also wondering if that is part of the problem.

  • mramra USMember ✭✭

    Hello,

    I've used the same code as @HalvardHagesther and it worked. But with the new Xamarin Version 1.4.0 the height of the ListView doesn't match the height of the items in it anymore.
    I have a ScrollView with 3 ListViews on it and they all have more than the double size than they need.

  • AlecTucker.2208AlecTucker.2208 AUInsider, University, Developer Group Leader mod

    You can put the list in a grid with a single row, and then set the height of the row based on the calculated height of the cells.
    Calculate the height in your custom cell renderer in OnBindingContextChanged. Keep a cumulative total of cell heights and set grid row height accordingly.

  • UddhaoPachrneUddhaoPachrne INMember ✭✭
    edited April 2015

    Hi,
    @AlecTucker.1318 I've used your solution with some little changes as per my requirement and it's work for me with new xamarin version. But i don't think it is right solution for that but there is no other option. Anyhow it's working for me.

    thank you

  • rsplrspl USMember ✭✭

    @AlecTucker.1318 I have the same issue, But in my case I am having Listview inside relative layout, and it doesnt allow me to scroll the listview, Can you help me here ?

  • FredyWengerFredyWenger CHInsider ✭✭✭✭✭

    @kameloulebsir.7777, @NeilMcKechnie, @mra, @AlecTucker.1318, @UddhaoPachrne, @rspl:
    I work with the newest .forms version (1.4.3-pre2) and also have this (more than) strange problem on one page (all c# without XAML).
    I show a ListView bound to a List with a custom data-template (ViewCell).
    The ListView is added to the main StackLayout with some more labels and an editor.
    The ListView takes to much space, so that there is a lot of free space showed after the ListView.
    I use the same ViewCell on various other pages (with ListViews) and also have the same page architecture on other pages, where I don't have such problems.
    If I have a look with the debugger at runtime, anything seems to be O.K.
    To add the LV in an additional StackLayout and set VerticalOptions = LayoutOptions.FillAndExpand don't help.
    If I remove the ListView from the page, the spacing between the controls is correct.
    I think, it may have something to do with the data-template (ViewCell).

    Do you have further information's to the problem?
    Thanks

  • NinineaNininea USUniversity ✭✭✭

    listView.HasUnevenRows = true; works for android, but for IOS still has problems :( :( anyone ???

  • FredyWengerFredyWenger CHInsider ✭✭✭✭✭

    @Nininea: Works also for iOS (since a longer time now) :smile:

  • NinineaNininea USUniversity ✭✭✭
    edited July 2015

    hm, it doesn't work here :( but in android looks fine

  • NinineaNininea USUniversity ✭✭✭

    here is my listview

    listView.ItemTemplate = new DataTemplate (typeof(ListItemCell)); listView.HasUnevenRows = true;

    and ListItemCell:

    `public ListItemCell ()
    {
    var nameLabel = new Label {
    HorizontalOptions = LayoutOptions.FillAndExpand
    };
    nameLabel.SetBinding (Label.TextProperty, "Product.Name");

            var viewLayout = new StackLayout () {
                Orientation = StackOrientation.Vertical,
                VerticalOptions = LayoutOptions.FillAndExpand,
                Padding = 4,
                Children = { nameLabel, CreateDetailsLayout () }
            };
            View = viewLayout;
    
        }
    
        static StackLayout CreateDetailsLayout ()
        {
            var quantityName = new Label {
                HorizontalOptions = LayoutOptions.FillAndExpand,
                Text = "Quantity:"
            };
            var quantity = new Label {
                HorizontalOptions = LayoutOptions.FillAndExpand
            };
            quantity.SetBinding (Label.TextProperty, "Quantity");
    
            var priceName = new Label {
                HorizontalOptions = LayoutOptions.FillAndExpand,
                Text = "Price:"
            };
            var price = new Label {
                HorizontalOptions = LayoutOptions.FillAndExpand
            };
            price.SetBinding (Label.TextProperty, "Product.Price");
            var priceSymbol = new Label {
                HorizontalOptions = LayoutOptions.FillAndExpand,
                Text = "$"
            };
            var nameLayout = new StackLayout () {
                HorizontalOptions = LayoutOptions.StartAndExpand,
                Orientation = StackOrientation.Horizontal,
                VerticalOptions = LayoutOptions.FillAndExpand,
                Children = { quantityName, quantity, priceName, price, priceSymbol }
            };
            return nameLayout;
        }`
    
  • NinineaNininea USUniversity ✭✭✭

    should I use ViewCellRenderer ?

  • FredyWengerFredyWenger CHInsider ✭✭✭✭✭

    If you don't set the height explicitly in your code (out of the posted code), I think, you have another problem with your layout...
    Sometimes the combination of options can give problems
    Not sure, but I would try to remove the vertical options to your SL (VerticalOptions = LayoutOptions.FillAndExpand) first..

  • HenryTranHenryTran USMember

    Put listview in stacklayout then set stack layout propery "Spacing = 0". Done

  • I am facing a similar problem but I was not able to use the solutions posted here. I am using a custom DataTemplate with a ListView in my Xamarin.Forms app. The content within the template however is bleeding over to the next row (attached the image). Similar to another post, my layout does not work for iOS but works on Android:

    An alternative is to hard-code the 'RowHeight' for the ListView but I want the row's height to be updated according to its contents so was hoping for a more generic solution.

    My markup is so:

    <ContentPage.Content>
        <StackLayout VerticalOptions="FillAndExpand">
            <ListView
                x:Name="busesListView"
                HasUnevenRows="true">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <StackLayout
                                Orientation="Horizontal">
                                <Image Source="{Binding Icon}" />
                                <StackLayout
                                    VerticalOptions="FillAndExpand">
                                    <Label Text="{Binding Name}" />
                                    <Label Text="{Binding Capacity}" />
                                    <Label Text="{Binding Location}" />
                                </StackLayout>
                            </StackLayout>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackLayout>
    </ContentPage.Content>
    

    Any insights on how to fix this problem?

  • Hello all,

    I am using Relative Layout using xaml and I have 1 label at the top and 2 buttons at the bottom. I want to show listview at the middle position. ListView contains label and button. My ListView is acquiring all the space of the page. What should I do? I am using relative layout to give constraints so that it can work on all the iOS and Android devices.
    please help

  • ThibaultDThibaultD SEMember ✭✭✭

    Defining RowHeight seems to be important for this to work.

  • Specifying a single RowDefinition with RowHeight="Auto" makes a difference.. strange.

  • EeshaEesha USMember ✭✭

    RowHeight does not work me in iOS.
    How to overcome this issue?
    Please share ur ideas.

    Thanks

  • Was anyone able to figure this out? I'm having this same issue. Thanks!

  • PranavSharmaPranavSharma AUMember

    Not the best solution but I implemented a workaround, maybe some one can improve it

    scrollView.SizeChanged += (s, e) =>
      {
          foreach (var child in stackLayout.Children)
          {  
              stackLayout.HeightRequest = stackLayout.Height + child.Height;
          }
      };
    

    What this does is adds extra height so that ListView's scroll does not get stuck.

  • TomCoombs.4595TomCoombs.4595 USMember

    listView.HasUnevenRows = true; worked for me in the context of a listView with a DataTemplate with stack layout inside and variable element displayed.

  • TomCoombs.4595TomCoombs.4595 USMember

    Checked on iOS and the issue is still there.

    @Nininea: did you find any solution?

    We also have a bunch of stack layout options.
    Seems to maybe have to do with the context displayed when mixed with horizontal layout for some lines in the listview element content

    <StackLayout Orientation="Vertical" Padding="5"> <controls:LabelEx Text="{Binding EventType}" FontAttributes="Bold" FontSize="16" /> <StackLayout Orientation="Horizontal"> <controls:LabelEx Text="Occured on" FontSize="16"/> <controls:LabelEx Text="{Binding EventDate, StringFormat='{}{0:MMMM, d yyyy}'}" FontSize="16" /> </StackLayout> <StackLayout Orientation="Horizontal" IsVisible="{Binding ValidUntilDate, Converter={StaticResource ValidityVisibilityConverter}}"> <controls:LabelEx Text="Valid until" FontSize="16"/> <controls:LabelEx Text="{Binding ValidUntilDate, StringFormat='{}{0:MMMM, d yyyy}'}" FontSize="16" /> </StackLayout> </StackLayout>

  • samuraxsamurax BRMember
    edited May 2016

    Forget StackLayout. Use Grid with RowDefinition Height="Auto"

  • WojciechBoczarskiWojciechBoczarski USUniversity ✭✭

    Putting ListView in StackLayout and setting it's attribute of Spacing=0 worked for me. Thank you

  • MattButlerMattButler USUniversity ✭✭

    The only way I've been able to overcome this issue, is to explicitly set the height of the StackLayout containing the Listview. My challenge now, is that I have uneven rows so explicit heights will be problematic. I am also building building a custom rendered ExpandableListView -> Android BaseExpandableListView haven't gotten to iOS yet. There are some examples out there of solutions for that, but they do not handle item.clicked events well, so most digging to do. Out of a year long build on our project, this is the most difficult UI issues we have faced...

  • LuisMatosLuisMatos USMember ✭✭

    The solution for me was to calculate the total height of my rows by the amount of items from the source and binding this property. Example:

    string heightList;
    int heightRowsList = 90;
    
    public string HeightList 
    { 
        get 
        { 
            heightList = (Items.Count * heightRowsList).ToString(); 
            return heightList; 
        } 
    }
    

    And in my xaml looks like this:

        <ListView x:Name="ItemsList"  HasUnevenRows="True" 
                ItemsSource="{Binding Items}" 
                HeightRequest="{Binding HeightList}"></ListView>
    
  • batmacibatmaci DEMember ✭✭✭✭✭

    @LuisMatos said:
    The solution for me was to calculate the total height of my rows by the amount of items from the source and binding this property. Example:

    string heightList;
    int heightRowsList = 90;
    
    public string HeightList 
    { 
      get 
      { 
          heightList = (Items.Count * heightRowsList).ToString(); 
          return heightList; 
      } 
    }
    

    And in my xaml looks like this:

        <ListView x:Name="ItemsList"  HasUnevenRows="True" 
              ItemsSource="{Binding Items}" 
              HeightRequest="{Binding HeightList}"></ListView>
    

    your solution has conflict. you use hasunevenrows true and you define even number for each row, 90 in your case.

  • LuisMatosLuisMatos USMember ✭✭

    @batmaci

    This solution work for my, for now...

  • batmacibatmaci DEMember ✭✭✭✭✭

    @LuisMatos said:
    @batmaci

    This solution work for my, for now...

    for sure it works for one device but when you actually try your solution on a bigger screen or smaller screen, you may get not expected view because you hardcode the size. This post is made for dynamic sizing. So it can adapt based on screen size of the device.

Sign In or Register to comment.