dotnet / maui

.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.
https://dot.net/maui
MIT License
22.21k stars 1.75k forks source link

Line height does not work as expected #17741

Open hansmbakker opened 1 year ago

hansmbakker commented 1 year ago

Description

The LineHeight property of Label is documented as the multiplier to apply to the default line height when displaying text

While it is counter-intuitive (I expected it to be an absolute value like the FontSize), it is possible to follow the documentation. However, this raises the next questions:

With an absolute line height of 20, I would expect that 3 lines of text have a height of 60, so that text would not be clipped if I put it in a container that has a height of 60.

With a font size of 14, I would expect that the required LineHeight multiplier is 20/14 = 1.42857.

When I use those settings for a label, a Label item of 3 lines

When I use font size 14 and set the LineHeight multiplier to 1.25, a Label item of 3 lines

Steps to Reproduce

  1. New Maui project
  2. Add Label styling to the MainPage:
    <ContentPage.Resources>
    <Style TargetType="Label">
        <Setter Property="FontFamily"
                Value="PoppinsRegular" />
        <Setter Property="FontSize"
                Value="14" />
        <Setter Property="LineHeight"
                Value="1.42857" />
        <Setter Property="CharacterSpacing"
                Value="-0.28" />
        <Setter Property="LineBreakMode"
                Value="WordWrap" />
        <Setter Property="TextColor"
                Value="Black" />
    </Style>
    </ContentPage.Resources>
  3. Add 2 Labels with a Text property that will span 3 lines (no need to insert line feeds or enters, it should flow automatically), like

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

  4. Set one Label's Background to some color, to visualize the element size
  5. Set the colored Label's HeightRequest to 60 (3 lines with an absolute line height of 20).
  6. See that the text in the colored Label is clipped.
  7. Use XAML Live Preview to see that the Label not having HeightRequest set is actually higher than the expected value of 60

Link to public reproduction project repository

https://github.com/hansmbakker/bugrepro-lineheight

Version with bug

8.0.0-rc.1.9171

Is this a regression from previous behavior?

Not sure, did not test other versions

Last version that worked well

Unknown/Other

Affected platforms

Android

Affected platform versions

No response

Did you find any workaround?

Manually fiddling with the LineHeight, property which is a bad developer experience.

Relevant log output

No response

hansmbakker commented 1 year ago
lineheight-too-large
ghost commented 1 year ago

We've added this issue to our backlog, and we will work to address it as time and resources allow. If you have any additional information or questions about this issue, please leave a comment. For additional info about issue management, please read our Triage Process.

hansmbakker commented 1 year ago

@jsuarezruiz please note that while I reproduced it on Android, the root of the issue is across platforms - on other platforms the calculation is also not clear from the documentation.

hansmbakker commented 9 months ago

Note: empirically we found that the default line height seems to be 16 (at least on Android), but it is unclear what that depends on. This assumption unfortunately does not work in all places in our app 🤦🏼‍♂️ and it is unclear what it depends on. So if we apply the formula required lineheight in maui = lineheight in px / 16 then in some places we get deviations and we would need inline overrides.

Please also note, that the Android font scaling (users able to drag a slider in the Android Settings app, changing the default font size) seems to add another variable to the mix.

hansmbakker commented 9 months ago

As a workaround I'm investigating a few Label control handlers to tame this control. They

I would have appreciated more feedback from Microsoft here though - having to implement a design with unpredictable behavior is energy consuming, to put it mildly.

pierrebelin commented 3 months ago

I just had the following issue: the first line as a greater height than this others.

Capture d'écran 2024-08-05 083728

So I found that using FormattedString just fixed it. I hope it can help someone:

<Label>
    <Label.FormattedText>
        <FormattedString>
            <Span Text="TEXT HERE........." LineHeight="3"/>
        </FormattedString>
    </Label.FormattedText>
</Label>
hansmbakker commented 3 months ago

@pierrebelin while I'm glad for you that it solves your problem, I believe it is not related to the original issue (how to determine the correct value for LineHeight and how to use LineHeight in a predictable way across platforms).

What you're seeing is uneven spacing between lines, which is a different thing. Without seeing your original code, the line height should be expected to be distributed evenly and using FormattedString this way should not be required to achieve that. Your issue might be the issue discussed in https://github.com/dotnet/maui/issues/24171.

jaosnz-rep commented 1 month ago

I can repro this issue at Android platform on the latest 17.12.0 Preview 1.0(8.0.82 & 8.0.80).

colincwilliams commented 2 weeks ago

First of all, I completely agree with the confusing nature of the LineHeight property. It being a multiplier is unexpected, and then determining how that is calculated is nigh impossible and would love to see either the implementation and/or documentation improved.

For others reading this, I did figure out what's happening for Windows (WinUI) specifically by digging into the MAUI source code. At this time the application I'm working on is exclusively for Windows so I have not investigated other platforms.

The underlying TextBlock has a LineHeight property that is an absolute value in pixels. The value assigned by Maui to the TextBlock's LineHeight is label.LineHeight * platformControl.FontSize

The source for that is: Microsoft.Maui.Platform.TextBlockExtensions.UpdateLineHeight.

So if your design indicates a font size of 28 and a line height of 36, the multiplier used in MAUI styles (at least for Windows) is: 36/28 = 1.2857.

Hope that helps someone out!