Zum Inhalt
Kuonen.UI

MAUI-Layouts

FlexLayout wie CSS Flexbox (Richtung, Umbruch, Verteilung), AbsoluteLayout mit festen und proportionalen Lagen und die Stack-Layouts.

Vorführung: MAUI-LayoutsVorführung: MAUI-Layouts

KXAML

MauiLayoutsSeite.kxaml
<StackPanel xmlns="https://ui.kuonen.org/kxaml"
            xmlns:x="https://ui.kuonen.org/kxaml/x"
            x:Class="Kuonen.UI.Galerie.Seiten.MauiLayoutsVorfuehrung"
            Spacing="8">
  <!-- Gefüllt von MauiLayoutsSeite.Fuelle, derselben Methode wie die C#-Fassung. -->
  <StackPanel x:Name="Flaeche" Spacing="8" />
</StackPanel>
MauiLayoutsSeite.kxaml.cs
using Kuonen.UI;

namespace Kuonen.UI.Galerie.Seiten;

public sealed partial class MauiLayoutsSeite
{
    protected override Func<UIElement>? KxamlFabrik => () => new MauiLayoutsVorfuehrung();
}

/// <summary>KXAML-Fassung der Seite: das Gerüst steht in MauiLayoutsSeite.kxaml, das Innere füllt MauiLayoutsSeite.Fuelle.</summary>
public sealed partial class MauiLayoutsVorfuehrung
{
    public MauiLayoutsVorfuehrung()
    {
        InitializeComponent();
        MauiLayoutsSeite.Fuelle(Flaeche);
    }
}

C#

MauiLayoutsSeite.cs
using Kuonen.UI;
using Kuonen.UI.Controls;
using Kuonen.UI.Layout;
using Kuonen.UI.Media;

namespace Kuonen.UI.Galerie.Seiten;

/// <summary>Galerie-Seite: FlexLayout, AbsoluteLayout und die Stack-Layouts wie MAUI (Plan 6n).</summary>
public sealed partial class MauiLayoutsSeite : GalerieSeite
{
    public override string Titel => "MAUI-Layouts";

    public override string Beschreibung => "FlexLayout wie CSS Flexbox (Richtung, Umbruch, Verteilung), AbsoluteLayout mit festen und proportionalen Lagen und die Stack-Layouts.";

    public override string Stichworte => "MAUI Xamarin FlexLayout Flexbox JustifyContent Wrap AbsoluteLayout LayoutBounds proportional VerticalStackLayout HorizontalStackLayout";

    public override string Datei => nameof(MauiLayoutsSeite);

    public override UIElement Baue()
    {
        // Wie die KXAML-Fassung: eine Wurzel mit der Fläche darin.
        var flaeche = new StackPanel { Spacing = 8 };
        Fuelle(flaeche);
        return new StackPanel { Spacing = 8, Children = { flaeche } };
    }

    private static readonly Color[] Farben =
    [
        Color.FromRgb(0xE5, 0x39, 0x35), Color.FromRgb(0xFB, 0x8C, 0x00), Color.FromRgb(0xFD, 0xD8, 0x35), Color.FromRgb(0x43, 0xA0, 0x47),
        Color.FromRgb(0x1E, 0x88, 0xE5), Color.FromRgb(0x5E, 0x35, 0xB1), Color.FromRgb(0x6D, 0x4C, 0x41), Color.FromRgb(0x54, 0x6E, 0x7A),
    ];

    private static BoxView Kasten(int i, double breite = 60) => new() { Color = new SolidColorBrush(Farben[i % Farben.Length]), Width = breite, Height = 30 };

    /// <summary>Inhalt der Seite (auch von der KXAML-Fassung benutzt).</summary>
    public static void Fuelle(StackPanel flaeche)
    {
        var flex = new FlexLayout { Wrap = FlexWrap.Wrap, Width = 320, HorizontalAlignment = HorizontalAlignment.Left };
        for (int i = 0; i < 8; i++) flex.Children.Add(Kasten(i));
        var verteilung = new ComboBox { Width = 160 };
        foreach (var art in Enum.GetValues<FlexJustify>()) verteilung.Items.Add(art);
        verteilung.SelectedIndex = 0;
        verteilung.SelectionChanged += (_, _) => flex.JustifyContent = verteilung.SelectedItem is FlexJustify j ? j : FlexJustify.Start;
        var umgekehrt = new CheckBox { Content = "Umgekehrt" };
        umgekehrt.Click += (_, _) => flex.Direction = umgekehrt.IsChecked == true ? FlexDirection.RowReverse : FlexDirection.Row;
        flaeche.Children.Add(new TextBlock { Text = "FlexLayout" });
        flaeche.Children.Add(new HorizontalStackLayout { Spacing = 8, Children = { verteilung, umgekehrt } });
        flaeche.Children.Add(new Border { BorderThickness = new Thickness(1), HorizontalAlignment = HorizontalAlignment.Left, Child = flex });

        var absolut = new AbsoluteLayout { Width = 320, Height = 120, HorizontalAlignment = HorizontalAlignment.Left };
        var fest = Kasten(0, 80);
        AbsoluteLayout.SetLayoutBounds(fest, new Rect(10, 10, 80, 30));
        var mitte = Kasten(4, 80);
        AbsoluteLayout.SetLayoutBounds(mitte, new Rect(0.5, 0.5, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize));
        AbsoluteLayout.SetLayoutFlags(mitte, AbsoluteLayoutFlags.PositionProportional);
        var unten = new BoxView { Color = new SolidColorBrush(Farben[3]) };
        AbsoluteLayout.SetLayoutBounds(unten, new Rect(0, 1, 1, 0.15));
        AbsoluteLayout.SetLayoutFlags(unten, AbsoluteLayoutFlags.All);
        absolut.Children.Add(fest);
        absolut.Children.Add(mitte);
        absolut.Children.Add(unten);
        flaeche.Children.Add(new TextBlock { Text = "AbsoluteLayout: fest, mittig, unten über die ganze Breite" });
        flaeche.Children.Add(new Border { BorderThickness = new Thickness(1), HorizontalAlignment = HorizontalAlignment.Left, Child = absolut });

        flaeche.Children.Add(new TextBlock { Text = "VerticalStackLayout in HorizontalStackLayout" });
        flaeche.Children.Add(new HorizontalStackLayout
        {
            Spacing = 12,
            Children =
            {
                new VerticalStackLayout { Spacing = 4, Children = { Kasten(5), Kasten(6), Kasten(7) } },
                new VerticalStackLayout { Spacing = 4, Children = { Kasten(1), Kasten(2) } },
            },
        });
    }
}