Jakub Jenis
Jakub Jenis

Reputation: 75

How to make FlexLayout's height adjust to its content?

In my Xamarin Forms application, I have a list of strings (minimum 1, maximum 4) that I want to display evenly in a column layout. Each column needs to have the same width and the content should expand so that the whole text is wrapped and visible. I know how I can do it using the Grid control using Width="*" on its columns.

I want to achieve the same result using FlexLayout, so I can bind the list of strings to BindableLayout and easily add and remove columns (I will not be displaying strings but a more complex layout in each column).

Using FlexLayout.Grow and FlexLayout.Basis I can get the FlexLayout to display evenly sized columns. The problem is making the FlexLayout's height fit all the displayed labels. Only the first row of text is displayed.

Both the Grid and FlexLayout are wrapped in a StackLayout:

<StackLayout>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>

        <Label  Text="First label" Grid.Column="0" BackgroundColor="Aqua"
                LineBreakMode="WordWrap" />

        <Label Text="Second label" Grid.Column="1"  BackgroundColor="Red"
               LineBreakMode="WordWrap" />

        <Label Text="Third label but with longer text" Grid.Column="2" BackgroundColor="Aqua"
               LineBreakMode="WordWrap"/>

        <Label Text="Fourth label" BackgroundColor="Red"
               Grid.Column="3"   LineBreakMode="WordWrap" />

    </Grid>
    <BoxView BackgroundColor="Blue"></BoxView>

    <FlexLayout AlignItems="Stretch">
        <Label  Text="First label" 
                FlexLayout.Grow="1" 
                FlexLayout.Basis="0" 
                BackgroundColor="Aqua"
                LineBreakMode="WordWrap" />

        <Label  Text="Second label" 
                FlexLayout.Grow="1" 
                FlexLayout.Basis="0" 
                BackgroundColor="Red"
                LineBreakMode="WordWrap" />

        <Label  Text="Third label but with longer text" 
                FlexLayout.Grow="1" 
                FlexLayout.Basis="0" 
                BackgroundColor="Aqua"
                VerticalOptions="FillAndExpand"
                LineBreakMode="WordWrap" />

        <Label  Text="Fourth label" 
                FlexLayout.Grow="1" 
                FlexLayout.Basis="0" 
                BackgroundColor="Red"
                LineBreakMode="WordWrap" />

    </FlexLayout>
    <BoxView BackgroundColor="Blue"></BoxView>
</StackLayout>

Grid and FlexLayout displayed

I figured out that when setting the HeightRequest of the FlexLayout to a specific number (e.g. 150), everything works as expected - the row has a height of 150 and all the labels stretch out to fit that. So what I need is somehow specify HeightRequest="Auto" so that the row fits all the column's content without being set to a specific value

Is there a way to achieve this?

Upvotes: 6

Views: 2487

Answers (1)

Lucas Zhang
Lucas Zhang

Reputation: 18861

FlexLayout will cut its child Elements . So in your case use Grid is the best solution .

so I can bind the list of strings to BindableLayout and easily add and remove columns

If you want to display a collection of data I suggest that you could use ListView or CollectionView(if you want to let the collection scroll in Horizontal or display multi Columns in the same row) .

 <ContentPage.Resources>
        <ResourceDictionary>
            <local:WidthConverter x:Key="WidthConverter" />
        </ResourceDictionary>
    </ContentPage.Resources>

    <StackLayout x:Name="stack">
        <CollectionView x:Name="list"  >

            <CollectionView.ItemsLayout>
                <LinearItemsLayout Orientation="Horizontal" />
            </CollectionView.ItemsLayout>

            <CollectionView.ItemTemplate>
                <DataTemplate>
                    

                        <Grid WidthRequest="{Binding Source={x:Reference stack},Path=Width,Converter={StaticResource WidthConverter}}">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto"/>
                            </Grid.RowDefinitions>

                            <Label Text="111111" BackgroundColor="LightBlue"  />

                           

                        </Grid>

                    
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
    </StackLayout>

in code behind

public class WidthConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var width = (double)value;

            if(width>0)
            {
                return width * 0.25;
            }

            return 100;

        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return 0;
        }
    }

For more details you could check https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/collectionview/layout#horizontal-list

Upvotes: 1

Related Questions