Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Label.Measure() in Android returns very different results from native Android.Text.StaticLayout() measurement method, causing abnormal Label clipping and wrapping behavior #18328

Open
jonmdev opened this issue Oct 25, 2023 · 2 comments
Labels
area-controls-label Label, Span area-drawing Shapes, Borders, Shadows, Graphics, BoxView, custom drawing area-layout StackLayout, GridLayout, ContentView, AbsoluteLayout, FlexLayout, ContentPresenter platform/android 🤖 t/bug Something isn't working
Milestone

Comments

@jonmdev
Copy link

jonmdev commented Oct 25, 2023

Description

Labels in Android do not layout correctly currently causing abnormal wrapping and clipping of letters/words: #17884

This is likely because using Label.Measure() to get the size of a given Label in Maui returns very different results from the native Android.Text.StaticLayout() method. If Maui and Android are discordant in what size Labels should be, this will cause the problematic behavior.

ANDROID GIVES WRONG RESULTS

A Label's expected size may be found in Android by using a StaticLayout object, as Maui does in PlatformStringSizeService. There are two methods to do this allowed by Android and both return the same results, which differ considerably from Label.Measure() with the same data.

My test project lays out a Label and then gets its size based on the label.Measure() (ie. real world size) and also based on the attempted prediction of its size.

The relevant output code is:

                Size labelMeasureSize = label.Measure(1000, 1000, MeasureFlags.None); //constraints are set in Label.MaxWidth already
                Size nativeMeasuredSize = NativeLabelMeasurer.Instance.getMeasurement(labelParams);
                Debug.WriteLine("label.Measure(): " + labelMeasureSize + " || NativeMeasurement: " + nativeMeasuredSize);

Expected behavior is that Label.Measure() should return the same as the NativeLabelMeasurer output.

In Windows this returns perfectly:

label.Measure(): { Width = 30 Height = 581} || NativeMeasurement: { Width = 30 Height = 581} //measuring perfectly`

In iOS this returns close but not exactly:

label.Measure(): { Width = 29.333333333333332 Height = 580.3333333333334} || NativeMeasurement: { Width = 29.232 Height = 580.2439999999997} //close enough?

In Android this returns completely wrong:

label.Measure(): { Width=30.181818181818183 Height=583.2727272727273} || NativeMeasurement: { Width=30 Height=612} // very wrong

IMPLICATIONS

I wonder if this is why we are seeing these wrapping/clipping glitches in Android: #17884

If Maui is somehow not allocating the correct amount of space for the Android objects or there is some miscommunication on their sizes, things may clip or wrap abnormally as shown in that other bug report.

SOLUTION FOR WINDOWS:

I also see this thread here where someone was requesting a method for Windows in PlatformStringSizeService: #12476

My method can be used for this purpose as it returns exactly correct results every time.

MINOR IOS ISSUES

Here is the iOS version in Maui:

https://github.com/dotnet/maui/blob/783db2459c6e3ec6437f9939a0ea2681fd634a3d/src/Graphics/src/Graphics/Platforms/iOS/PlatformStringSizeService.cs

There are two problems with it FYI:

  • using uiFont.Dispose(); as written there triggers an error Cannot access a disposed object. Object name: 'UIKit.UIFont'. (System.ObjectDisposedException) - I presume this is disposing the underlying font as well in the process
  • new method listed only as size = nsString.StringSize(uiFont, CGSize.Empty); does not apply any constraints - my method gives a more complete version of this

I just mention these iOS issues in passing if it is helpful.

Steps to Reproduce

  1. Open bug project and play in Windows/iOS/Android.
  2. See the measured sizes in Windows are perfect, they are close to perfect in iOS, and they are very wrong in Android.
  3. Try to comment in my new suggested Android method of getting the StaticLayout object and see the enum error.
  4. See this perhaps related bug report: [Android] Entire words omitted & letters truncated from Label display #17884

All code can be seen here:

https://github.com/jonmdev/Label-Measurement-Bug/blob/main/Label%20Measurement%20Bug/App.xaml.cs

Link to public reproduction project repository

https://github.com/jonmdev/Label-Measurement-Bug

Version with bug

7.0.96

Is this a regression from previous behavior?

No, this is something new

Affected platforms

iOS, Android

Did you find any workaround?

None. Needs fixing likely to get reliable Layout/Label behaviors. Not sure why it is happening.

@jonmdev jonmdev added the t/bug Something isn't working label Oct 25, 2023
@jsuarezruiz jsuarezruiz added area-layout StackLayout, GridLayout, ContentView, AbsoluteLayout, FlexLayout, ContentPresenter area-controls-label Label, Span labels Oct 25, 2023
@ghost ghost added the legacy-area-controls Label, Button, CheckBox, Slider, Stepper, Switch, Picker, Entry, Editor label Oct 25, 2023
@jonmdev jonmdev changed the title Method to measure expected Label sizes for Android is obsolete & returns very wrong results compared to real Layout size - possibly reason for Android Label layout glitches previously reported (minor error with iOS measurement also) Method to measure expected Label sizes for Android is deprecated & returns very wrong results compared to real Layout size - possibly reason for Android Label layout glitches previously reported (minor error with iOS measurement also) Oct 25, 2023
@mattleibow mattleibow added area-drawing Shapes, Borders, Shadows, Graphics, BoxView, custom drawing area-layout StackLayout, GridLayout, ContentView, AbsoluteLayout, FlexLayout, ContentPresenter legacy-area-controls Label, Button, CheckBox, Slider, Stepper, Switch, Picker, Entry, Editor area-controls-label Label, Span and removed area-layout StackLayout, GridLayout, ContentView, AbsoluteLayout, FlexLayout, ContentPresenter legacy-area-controls Label, Button, CheckBox, Slider, Stepper, Switch, Picker, Entry, Editor area-controls-label Label, Span labels Oct 25, 2023
@mattleibow mattleibow added this to the Backlog milestone Oct 25, 2023
@ghost
Copy link

ghost commented Oct 25, 2023

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.

@mattleibow mattleibow changed the title Method to measure expected Label sizes for Android is deprecated & returns very wrong results compared to real Layout size - possibly reason for Android Label layout glitches previously reported (minor error with iOS measurement also) Method to measure expected Label sizes for Android is deprecated & returns very wrong results compared to real Layout size Oct 25, 2023
@jonmdev jonmdev changed the title Method to measure expected Label sizes for Android is deprecated & returns very wrong results compared to real Layout size Label.Measure() in Android returns very different results from native Android.Text.StaticLayout() measurement method, causing abnormal Label clipping and wrapping behavior Mar 14, 2024
@jonmdev
Copy link
Author

jonmdev commented Mar 14, 2024

I have done some more work on this bug. I was now able to get both the old (API 21+ I believe) and new (API 33+) Android native label measurement methods working in the bug project, but again, both return completely wrong results compared to Label.Measure().

I updated my bug project code accordingly and some notes as well. All code is contained here:

https://github.com/jonmdev/Label-Measurement-Bug/blob/main/Label%20Measurement%20Bug/App.xaml.cs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-controls-label Label, Span area-drawing Shapes, Borders, Shadows, Graphics, BoxView, custom drawing area-layout StackLayout, GridLayout, ContentView, AbsoluteLayout, FlexLayout, ContentPresenter platform/android 🤖 t/bug Something isn't working
Projects
None yet
Development

No branches or pull requests

5 participants