2

In Xamarin Forms, when I put a label inside a grid with many columns, the label takes extra height just as if the text is longer and overflows below on a new line.
If I put the label inside the stack layout, before or after the grid, it displays correctly, but it doesn't when inside the grid.
Also, the issue seems bigger if the grid has many columns.

If I delete the scroll view it doesn't fix the issue.
The issue seems to be related with the Margin of 20 set for the stack layout. Bigger margin makes things worse, however, even if I delete the scroll view and stack layout and I keep just the grid, the issue still appears.

I am using latest Xamarin Forms (5.0.0.2291) and Xamarin Essentials (1.7.0). I tried older versions, e.g. XF 4.7.1239 - issue still appears.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="App1.MainPage"
             NavigationPage.HasNavigationBar="False"
             xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
             ios:Page.UseSafeArea="true">
    <ContentPage.Content> <!-- totally not good... -->
        <ScrollView Orientation="Vertical">
            <StackLayout  Orientation="Vertical"
                          Margin="20"
                          HorizontalOptions="FillAndExpand"
                          BackgroundColor="LightGreen">
                <Grid Margin="0" Padding="0" BackgroundColor="LightCyan">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="1*" />
                        <ColumnDefinition Width="1*" />
                        <ColumnDefinition Width="1*" />
                        <ColumnDefinition Width="1*" />
                        <ColumnDefinition Width="1*" />
                        <ColumnDefinition Width="1*" />
                        <ColumnDefinition Width="1*" />
                        <ColumnDefinition Width="1*" />
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                    </Grid.RowDefinitions>
                    <Label Text="Contact wire height low and high alert limits
                           contact wire 123456"
                           FontSize="18"
                           Padding="0"
                           Margin="0"
                           HorizontalOptions="FillAndExpand"
                           Grid.Row="0"
                           Grid.Column="0"
                           Grid.ColumnSpan="8"
                           BackgroundColor="LightBlue"/>
                </Grid>
            </StackLayout>
        </ScrollView>
    </ContentPage.Content>
</ContentPage>

UPDATE

explanation in image explanation in image explanation in image explanation in image

ToolmakerSteve
  • 18,547
  • 14
  • 94
  • 196
Marius Rusu
  • 93
  • 1
  • 6

2 Answers2

2

That sounds like a bug in Grid's layout logic, related to the label spanning multiple columns.

You might be able to control it, by explicitly telling it to only use a single line:

<Label ... MaxLines="1" ... />

OR you may have to set an explicit row height. E.g.

<RowDefinition Height="30"/>

WORKAROUND: The bug does not occur if Grid has

<Grid ...  ColumnSpacing="0" ...>

You can approximate what ColumnSpacing did, using Padding on elements of the Grid. Not as convenient, but possible.

I discovered this when using a custom Label class. The first time its OnMeasure was called, widthRequest apparently did not include ColumnSpacing; it was not the full width of the grid!

After that, OnMeasure was called again with the correct width - but I infer that Grid had already determined Row Height based on that first call.

ToolmakerSteve
  • 18,547
  • 14
  • 94
  • 196
  • Yes, was thinking of this, however, I don't know how much height the Label will require. This varies with the number of characters that the Label will display and also with the phone resolution and pixel density, etc. If I put such constraints I think the code will probably fail in some situations. – Marius Rusu Jan 18 '22 at 11:35
  • @MariusRusu - I see. I posted this answer before you added the images; I was assuming the text fit in a single line. Its possible to fix by adapting [code in this answer](https://stackoverflow.com/a/70475809/199364). You'd define a custom Grid instead of AbsoluteLayout. But its a fair amount of code - Grid is challenging to customize. So here's the situation: You've uncovered a Xamarin bug, but there is no easy workaround. Do you still want to proceed, or now that you know it isn't simple, why not move the Label outside of the Grid? – ToolmakerSteve Jan 19 '22 at 01:45
  • Actually, I just had an idea. Might be easy to make a custom Label, whose Measure method sets MaxLines as a side-effect and/or somehow works around the Grid multi-column bug. Investigating. – ToolmakerSteve Jan 19 '22 at 01:49
  • 1
    @MariusRusu - Found a workaround - ColumnSpacing=0. Added to answer. – ToolmakerSteve Jan 19 '22 at 02:42
  • Great, the workaround does work and seems to be "risk free" as in I expect it to work well on various screen sizes and/or OS. Many thanks! – Marius Rusu Jan 19 '22 at 11:09
-1
  1. According to your description, Lable takes up extra height. In your definition, you use <RowDefinition Height="Auto"/>, so the view will expand downwards automatically. Defining a fixed height can make him in height. show normaly.
  2. You have used Grid.ColumnSpan="8", using this code is to combine the space of 8 columns into one, that is to use the space of a whole row, you can see that this Lable occupies a whole row on the display.
  3. For your column definitions, you used eight 1*, which is equivalent to dividing a row into 8 parts, each taking 1/8 of the space.
Wen xu Li
  • 1,698
  • 1
  • 4
  • 7
  • 1. Yes, I use Auto because I don't know how much height the text will require. Auto means that it should take up as much space as it needs, but it is taking up more than what it needs... 2. Yes, I have to display 8 columns, and on top of the 8 columns I need to show some text; I think I am using grid correctly... 3. Yes, the columns will all have little amount of text, my intention is that they are equal in width... – Marius Rusu Jan 18 '22 at 11:29
  • @WenxuLi-MSFT - Yes you can. `ColumnSpan` is number of columns covered. In this case, columns 0 through 7 = span of 8. – ToolmakerSteve Jan 19 '22 at 01:29
  • I usually don't downvote answers to questions that I have also answered - but how is this answer helpful? The problem is that the label expands vertically **more than it needs to**, to hold the text. Clearly a Xamarin bug. Point 1 I already discussed in my earlier answer - plus I showed two code snippets that might fix it. Points 2 and 3 simply explain details of the question's code. Details which are deliberate, so why discuss them? They can't possibly cause the problem being discussed. – ToolmakerSteve Jan 19 '22 at 01:35