Iris Classon
Iris Classon - In Love with Code

Wrapping Text in Maui With Grids, StackLayouts, and More

Wrapping Text in Maui With Grids Stacklayouts and More

Today’s challenge in migrating from Xamarin to MAUI consisted of making a text label wrap a text into multiple lines. Sounds easy? Well, some things are different in Maui. When you have a stack layout and its orientation set to horizontal, or you use a horizontal stack layout, it will continue to add items horizontally even beyond the boundaries of its parent. In other words, if you for some reason cannot make the text wrap, double check its parent and the parent properties. The behavior is not considered a bug but intended behavior, although you’ll find several issues on GitHub regarding text wrapping. I don’t really have an opinion whether or not this should be considered a bug, as long as there is a solution.Solutions:

Set the WidthRequest of the parent or label
Use Grid with * or specific sizes
Use a FlexLayout

When you use a Grid Auto for size won’t work.“The fact that the text does not wrap in the second Label is not a bug, it’s as designed. The Label is in column with a Width of Auto; this means that each item in the column is measured as if it had infinite width available. Given infinite width, the Label has no reason to wrap its text, and simply lays it out in a single line that runs off the edge of the Grid.”   If you look at the code you can see that the first label spans across and beyond, and therefor the yellow label isn’t even visible. In the grid the same thing happens since the width is set to auto. We can see the first label, orange, but again just one line instead of three. The pink label isn’t visible for the same reasons as the StackLayout earlier.   The FlexLayout shows both, but even though we’ve se the direction to Column it shows them stacked as the first label spans the entire screen without a width restriction.   In the last Grid we see both labels, as multilines, which is due to the * width, which in this case evenly splits the available space based on the parent container.   In the last example I’ve used an extension method on the label to measure the width of the text and set the column to the width of that label knowing that that label has precedence and will always be shorter. This is to illustrate a different way to go about this.

    <VerticalStackLayout>
        <StackLayout Orientation="Horizontal">
            <Label Text="Very very very very very long text, and even longer etx more text more text more text, and even longer etx more text more text more text."
                   LineBreakMode="WordWrap"
                   MaxLines="3"
                   BackgroundColor="Grey">
            </Label>
            <Label Text="Very very very very very long text, and even longer etx more text more text more text, and even longer etx more text more text more text."
                   LineBreakMode="WordWrap"
                   MaxLines="3"
                   BackgroundColor="Yellow">
            </Label>
        </StackLayout>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"></ColumnDefinition>
                <ColumnDefinition Width="Auto"></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <Label Text="Very very very very very long text, and even longer etx more text more text more text, and even longer etx more text more text more text."
                   LineBreakMode="WordWrap"
                   MaxLines="3"
                   BackgroundColor="Orange">
            </Label>
            <Label Grid.Column="1" Text="Very very very very very long text, and even longer etx more text more text more text, and even longer etx more text more text more text."
                   LineBreakMode="WordWrap"
                   MaxLines="3"
                   BackgroundColor="HotPink">
            </Label>
        </Grid>
      <FlexLayout Direction="Column" >
          <Label Text="Very very very very very long text, and even longer etx more text more text more text, and even longer etx more text more text more text."
                 LineBreakMode="WordWrap"
                 MaxLines="3"
                 BackgroundColor="Red">
          </Label>
          <Label Grid.Column="1" Text="Very very very very very long text, and even longer etx more text more text more text, and even longer etx more text more text more text."
                 LineBreakMode="WordWrap"
                 MaxLines="3"
                 BackgroundColor="Brown">
          </Label>
      </FlexLayout>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"></ColumnDefinition>
                <ColumnDefinition Width="*"></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <Label Text="Very very very very very long text, and even longer etx more text more text more text, and even longer etx more text more text more text."
                   LineBreakMode="WordWrap"
                   MaxLines="3"
                   BackgroundColor="BlueViolet">
            </Label>
            <Label Grid.Column="1" Text="Very very very very very long text, and even longer etx more text more text more text, and even longer etx more text more text more text."
                   LineBreakMode="WordWrap"
                   MaxLines="3"
                   BackgroundColor="Blue">
            </Label>
        </Grid>
        <Grid x:Name="grid2">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"></ColumnDefinition>
                <ColumnDefinition Width="*"></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <Label Text="Very very very very very long text, and even longer etx more text more text more text, and even longer etx more text more text more text."
                   LineBreakMode="WordWrap"
                   MaxLines="3"
                   BackgroundColor="GreenYellow">
            </Label>
            <Label x:Name="label" Grid.Column="1" Text="I need this much."
                   LineBreakMode="WordWrap"
                   MaxLines="3"
                   BackgroundColor="Green">
            </Label>
        </Grid>
    </VerticalStackLayout>
</ContentPage>
namespace MauiApp7;
#if ANDROID
using Android.Graphics;
#elif IOS
using UIKit;
using Foundation;
using CoreGraphics;
#endif

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
        grid2.ColumnDefinitions[1].Width = label.MeasureTextWidth();
    }


}

public static class LabelExtensions
{
    public static double MeasureTextWidth(this Label label)
    {
        double width = 0;

#if ANDROID
        var paint = new Paint();
        paint.TextSize = (float)label.FontSize;
        width = paint.MeasureText(label.Text);
#elif IOS
        var nsText = new NSString(label.Text);
        var attributes = new UIStringAttributes
        {
            Font = UIFont.FromName(label.FontFamily, (float)label.FontSize)
        };
        width = nsText.GetSizeUsingAttributes(attributes).Width;
#endif

        return width;
    }
}

Comments

Leave a comment (via email)

Last modified on 2023-10-05