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

Add NeedsExactMeasure check for Editor on Android #10876

Merged
merged 2 commits into from
Nov 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 1 addition & 47 deletions src/Core/src/Handlers/Button/ButtonHandler.Android.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,58 +124,12 @@ void OnSetImageSource(Drawable? obj)
PlatformView.Icon = obj;
}

bool NeedsExactMeasure()
{
if (VirtualView.VerticalLayoutAlignment != Primitives.LayoutAlignment.Fill
&& VirtualView.HorizontalLayoutAlignment != Primitives.LayoutAlignment.Fill)
{
// Layout Alignments of Start, Center, and End will be laying out the TextView at its measured size,
// so we won't need another pass with MeasureSpecMode.Exactly
return false;
}

if (VirtualView.Width >= 0 && VirtualView.Height >= 0)
{
// If the Width and Height are both explicit, then we've already done MeasureSpecMode.Exactly in
// both dimensions; no need to do it again
return false;
}

// We're going to need a second measurement pass so TextView can properly handle alignments
return true;
}

public override void PlatformArrange(Rect frame)
{
var platformView = this.ToPlatform();

if (platformView == null || Context == null)
{
return;
}

if (frame.Width < 0 || frame.Height < 0)
{
return;
}

// Depending on our layout situation, the TextView may need an additional measurement pass at the final size
// in order to properly handle any TextAlignment properties.
if (NeedsExactMeasure())
{
platformView.Measure(MakeMeasureSpecExact(frame.Width), MakeMeasureSpecExact(frame.Height));
}

this.PrepareForTextViewArrange(frame);
Comment on lines -168 to +129
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously, the could would exit out if something was null or -1 and base wouldnot run, but now because that code is extracted, base always runs.

Is this going to cause any issues?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The base method also does those checks. And the NeedsExactMeasure logic shouldn't really have been making the "don't run base at all decision" anyway, it should have just been answering the question "do we need an additional exact measure?".

base.PlatformArrange(frame);
}

int MakeMeasureSpecExact(double size)
{
// Convert to a platform size to create the spec for measuring
var deviceSize = (int)Context!.ToPixels(size);
return MeasureSpecMode.Exactly.MakeMeasureSpec(deviceSize);
}

bool OnTouch(IButton? button, AView? v, MotionEvent? e)
{
switch (e?.ActionMasked)
Expand Down
11 changes: 9 additions & 2 deletions src/Core/src/Handlers/Editor/EditorHandler.Android.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Android.Views;
using Android.Views.InputMethods;
using AndroidX.AppCompat.Widget;
using Microsoft.Maui.Graphics;
using static Android.Views.View;

namespace Microsoft.Maui.Handlers
Expand Down Expand Up @@ -80,7 +81,7 @@ public static void MapPlaceholderColor(IEditorHandler handler, IEditor editor)
public static void MapCharacterSpacing(IEditorHandler handler, IEditor editor) =>
handler.PlatformView?.UpdateCharacterSpacing(editor);

public static void MapMaxLength(IEditorHandler handler, IEditor editor) =>
public static void MapMaxLength(IEditorHandler handler, IEditor editor) =>
handler.PlatformView?.UpdateMaxLength(editor);

public static void MapIsReadOnly(IEditorHandler handler, IEditor editor) =>
Expand All @@ -92,7 +93,7 @@ public static void MapIsTextPredictionEnabled(IEditorHandler handler, IEditor ed
public static void MapFont(IEditorHandler handler, IEditor editor) =>
handler.PlatformView?.UpdateFont(editor, handler.GetRequiredService<IFontManager>());

public static void MapHorizontalTextAlignment(IEditorHandler handler, IEditor editor) =>
public static void MapHorizontalTextAlignment(IEditorHandler handler, IEditor editor) =>
handler.PlatformView?.UpdateHorizontalTextAlignment(editor);

public static void MapVerticalTextAlignment(IEditorHandler handler, IEditor editor) =>
Expand Down Expand Up @@ -131,5 +132,11 @@ private void OnSelectionChanged(object? sender, EventArgs e)
if (VirtualView.SelectionLength != selectedTextLength)
VirtualView.SelectionLength = selectedTextLength;
}

public override void PlatformArrange(Rect frame)
{
this.PrepareForTextViewArrange(frame);
base.PlatformArrange(frame);
}
}
}
48 changes: 1 addition & 47 deletions src/Core/src/Handlers/Label/LabelHandler.Android.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,7 @@ protected override AppCompatTextView CreatePlatformView()

public override void PlatformArrange(Rect frame)
{
var platformView = this.ToPlatform();

if (platformView == null || Context == null)
{
return;
}

if (frame.Width < 0 || frame.Height < 0)
{
return;
}

// Depending on our layout situation, the TextView may need an additional measurement pass at the final size
// in order to properly handle any TextAlignment properties.
if (NeedsExactMeasure())
{
platformView.Measure(MakeMeasureSpecExact(frame.Width), MakeMeasureSpecExact(frame.Height));
}

this.PrepareForTextViewArrange(frame);
base.PlatformArrange(frame);
}

Expand Down Expand Up @@ -84,33 +66,5 @@ public static void MapLineHeight(ILabelHandler handler, ILabel label)
{
handler.PlatformView?.UpdateLineHeight(label);
}

bool NeedsExactMeasure()
{
if (VirtualView.VerticalLayoutAlignment != Primitives.LayoutAlignment.Fill
&& VirtualView.HorizontalLayoutAlignment != Primitives.LayoutAlignment.Fill)
{
// Layout Alignments of Start, Center, and End will be laying out the TextView at its measured size,
// so we won't need another pass with MeasureSpecMode.Exactly
return false;
}

if (VirtualView.Width >= 0 && VirtualView.Height >= 0)
{
// If the Width and Height are both explicit, then we've already done MeasureSpecMode.Exactly in
// both dimensions; no need to do it again
return false;
}

// We're going to need a second measurement pass so TextView can properly handle alignments
return true;
}

int MakeMeasureSpecExact(double size)
{
// Convert to a native size to create the spec for measuring
var deviceSize = (int)Context!.ToPixels(size);
return MeasureSpecMode.Exactly.MakeMeasureSpec(deviceSize);
}
}
}
59 changes: 59 additions & 0 deletions src/Core/src/Handlers/ViewHandlerExtensions.Android.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System;
using System.Runtime.CompilerServices;
using Android.Content;
using Android.Views;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Platform;
Expand Down Expand Up @@ -132,5 +134,62 @@ internal static void PlatformArrangeHandler(this IViewHandler viewHandler, Rect

viewHandler.Invoke(nameof(IView.Frame), frame);
}

internal static void PrepareForTextViewArrange(this IViewHandler handler, Rect frame)
{
if (frame.Width < 0 || frame.Height < 0)
{
return;
}

var platformView = handler.ToPlatform();
var context = platformView?.Context;

if (platformView == null || context == null)
{
return;
}

var virtualView = handler.VirtualView;
if (virtualView == null)
{
return;
}

// Depending on our layout situation, the TextView may need an additional measurement pass at the final size
// in order to properly handle any TextAlignment properties and some internal bookkeeping
if (virtualView.NeedsExactMeasure())
{
platformView.Measure(context.MakeMeasureSpecExact(frame.Width), context.MakeMeasureSpecExact(frame.Height));
}
}

internal static bool NeedsExactMeasure(this IView virtualView)
{
if (virtualView.VerticalLayoutAlignment != Primitives.LayoutAlignment.Fill
&& virtualView.HorizontalLayoutAlignment != Primitives.LayoutAlignment.Fill)
{
// Layout Alignments of Start, Center, and End will be laying out the TextView at its measured size,
// so we won't need another pass with MeasureSpecMode.Exactly
return false;
}

if (virtualView.Width >= 0 && virtualView.Height >= 0)
{
// If the Width and Height are both explicit, then we've already done MeasureSpecMode.Exactly in
// both dimensions; no need to do it again
return false;
}

// We're going to need a second measurement pass so TextView can properly handle alignments
return true;
}

internal static int MakeMeasureSpecExact(this Context context, double size)
{
// Convert to a native size to create the spec for measuring
var deviceSize = (int)context!.ToPixels(size);
return MeasureSpecMode.Exactly.MakeMeasureSpec(deviceSize);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ Microsoft.Maui.IWindow.MinimumHeight.get -> double
Microsoft.Maui.IWindow.MinimumWidth.get -> double
Microsoft.Maui.IWindow.X.get -> double
Microsoft.Maui.IWindow.Y.get -> double
override Microsoft.Maui.Handlers.EditorHandler.PlatformArrange(Microsoft.Maui.Graphics.Rect frame) -> void
override Microsoft.Maui.Handlers.MenuFlyoutHandler.CreatePlatformElement() -> object!
override Microsoft.Maui.Handlers.MenuFlyoutSeparatorHandler.CreatePlatformElement() -> object!
override Microsoft.Maui.Handlers.EditorHandler.SetVirtualView(Microsoft.Maui.IView! view) -> void
Expand Down