CommunityToolkit/Maui.Markup

[Proposal] Absolute layout LayoutBounds and LayoutFlag extension

danielftz opened this issue ยท 6 comments

Absolute layout LayoutBounds and LayoutFlag markup extension

  • Proposed
  • Prototype
  • Implementation
  • Unit Tests
  • Documentation
  • Sample

Link to Discussion

#22

Summary

I propose a ViewInAbsoluteLayoutExtensions static class, where LayoutBounds and LayoutFlag static methods (and their overloads) are implemented.

In most cases when using AbsoluteLayout, every child view will need to define two attached properties, LayoutBounds and LayoutFlag, where LayoutBounds is a Rectangle struct and LayoutFlag is an AbsoluteLayoutFlags Enum. Thus, the ViewInAbsoluteLayoutExtensions will offer the child View the ability to define these two attached properties declaratively.

Example:

BoxView box= new BoxView
{
   Color = Colors.Red,
}.LayoutBounds(0.5, 0.5, 100, 100)
.LayoutFlags(AbsoluteLayoutFlags.PositionProportional);

Motivation

Currently In MCT Markup, there are no declarative way to define LayoutBounds and LayoutFlag (like Row and Column for child Views in Grid)

Detailed Design

The ViewInAbsoluteLayoutEx tensions static class should at the very least include 4 extension methods to cover the 4 basic use cases,

  • setting AbsoluteLayoutFlags
public static TView LayoutFlags<TView>(this TView view, AbsoluteLayoutFlags flag) where TView : View
{
    view.SetValue(AbsoluteLayout.LayoutFlagsProperty, flag);
    return view;
}
  • setting position only LayoutBounds value (Not sure if this implementation is correct)
public static TView LayoutBounds<TView>(this TView view, Point point) where TView : View
{
    view.SetValue(AbsoluteLayout.LayoutBoundsProperty, point);
    return view;
}
  • setting position and size LayoutBounds value
public static TView LayoutBounds<TView>(this TView view, Rectangle rectangle) where TView : View
{
    view.SetValue(AbsoluteLayout.LayoutBoundsProperty, rectangle);
    return view;
}

Additionally, LayoutBounds method should have overloads mostly for the purpose of ease of use. Allowing the user to input in x,y,width,height directly, instead of encapsulating these values in a Rectangle struct.

public static TView LayoutBounds<TView>(this TView view, int x, int y) where TView : View
public static TView LayoutBounds<TView,TCoord>(this TView view, TCoord x, TCoord y) where TView : View where TCoord : Enum
public static TView LayoutBounds<TView>(this TView view, int x, int y, int width , int height) where TView : View
public static TView LayoutBounds<TView, TCoord>(this TView view, TCoord x, TCoord y, TCoord width, TCoord height) where TView : View where TCoord : Enum
public static TView LayoutBounds<TView>(this TView view, Point point, Size size) where TView : View

There also needs to be a private ToDouble helper method in this class, as double is expected input type for Rectangle struct

static double ToDouble(this Enum enumValue) => Convert.ToDouble(enumValue, CultureInfo.InvariantCulture);

Drawbacks

None that i can think of.

Alternatives

None that i can think of.

Unresolved Questions

  • For child View objects that need to use AbsoluteValue.AutoSize, the implementation still needs more testing.
  • Sometimes if the user only wants to change the position or the size of the child View, should they be given the option to do that with one of the overloads?

Thanks @danielftz! I'll champion this proposal and add it to our next standup for a vote/approaval ๐Ÿ™Œ

I approve this Proposal โœ…

Approve

I approve too

Congrats @danielftz! This Proposal has officially been approved and can be implemented!

Would you like to also do the implementation and open a Pull Request?

Thank you guys. Yes, I will open a pull request.