.NET MAUI - XAML StackLayout 의 View(Control) 정렬

2022. 7. 12. 00:00MAUI

반응형

StackLayout은 자식 보기를 왼쪽에서 오른쪽 또는 위에서 아래로 구성하는 레이아웃 컨테이너이다. 

방향은 Orientation 속성을 기반으로 하며 기본값은 위에서 아래로이다. 

다음 그림은 수직방향의 StackLayout의 개념적 보기를 보여준다.

 

 

VerticalStackLayout 및 HorizontalStackLayout은 성능에 최적화되어 있으며

방향이 변경되지 않는다는 것을 알고 있을 때 사용하는 기본 레이아웃이다.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MauiApp1.Xaml.StackLayout.MainPage"
             >
    <StackLayout x:Name="stack" Orientation="Vertical">
        <BoxView Color="Silver" HeightRequest="40" />
        <BoxView Color="Blue" HeightRequest="40"/>
        <BoxView Color="Gray" HeightRequest="40"/>
    </StackLayout>
</ContentPage>

 

 

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MauiApp1.Xaml.StackLayout.MainPage"
             >
    <StackLayout x:Name="stack" Orientation="Horizontal">
        <BoxView Color="Silver" WidthRequest="40"/>
        <BoxView Color="Blue" WidthRequest="40"/>
        <BoxView Color="Gray" WidthRequest="40"/>
    </StackLayout>
</ContentPage>

 

 

 

프리뷰 버전이라 그런지 아니면 초기 버전이라 그런지 버그가 상당히 많다.

c# code 로 xaml 의 내용을 구현해 보면 동작하지 않는다. 이부분은 참고하자

 

아래와 같은 형태로 수직, 수평 stacklayout 을 최적화하여 표현할 수 있다.

<VerticalStackLayout>
    <BoxView Color ="Silver" HeightRequest="40"/>
    <BoxView Color="Blue"  HeightRequest="40"/>
    <BoxView Color="Gray"  HeightRequest="40"/>
</VerticalStackLayout>
<HorizontalStackLayout>
    <BoxView Color="Silver" WidthRequest="40"/>
    <BoxView Color="Blue" WidthRequest="40"/>
    <BoxView Color="Gray" WidthRequest="40"/>
</HorizontalStackLayout>

 

예제

StackLayout/Exercise.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MauiApp1.Xaml.StackLayout.Exercise"
             Title="Exercise">
    <VerticalStackLayout>
        <Label Text="Bill" />
        <Entry x:Name="billInput" Placeholder="Enter Amount" Keyboard="Numeric" />

        <Label Text="Tip"   />
        <Label x:Name="tipOutput" Text="0.00" />

        <Label Text="Total" />
        <Label x:Name="totalOutput" Text="0.00" />

        <Label Text="Tip Percentage" />
        <Label x:Name="tipPercent" Text="15%" />
        <Slider x:Name="tipPercentSlider" Minimum="0" Maximum="100" Value="15" />

        <Button Text="15%" Clicked="OnNormalTip" />
        <Button Text="20%" Clicked="OnGenerousTip" />

        <Button x:Name="roundDown" Text="Round Down" />
        <Button x:Name="roundUp"   Text="Round Up" />
    </VerticalStackLayout>
</ContentPage>

StackLayout/Exercise.xaml.cs

namespace MauiApp1.Xaml.StackLayout;

public partial class Exercise : ContentPage
{
	public Exercise()
	{
		InitializeComponent();

        billInput.TextChanged += (s, e) => CalculateTip(false, false);
        roundDown.Clicked += (s, e) => CalculateTip(false, true);
        roundUp.Clicked += (s, e) => CalculateTip(true, false);

        tipPercentSlider.ValueChanged += (s, e) =>
        {
            double pct = Math.Round(e.NewValue);
            tipPercent.Text = pct + "%";
            CalculateTip(false, false);
        };
    }

    void CalculateTip(bool roundUp, bool roundDown)
    {
        double t;
        if (Double.TryParse(billInput.Text, out t) && t > 0)
        {
            double pct = Math.Round(tipPercentSlider.Value);
            double tip = Math.Round(t * (pct / 100.0), 2);

            double final = t + tip;

            if (roundUp)
            {
                final = Math.Ceiling(final);
                tip = final - t;
            }
            else if (roundDown)
            {
                final = Math.Floor(final);
                tip = final - t;
            }

            tipOutput.Text = tip.ToString("C");
            totalOutput.Text = final.ToString("C");
        }
    }

    void OnNormalTip(object sender, EventArgs e) { tipPercentSlider.Value = 15; }
    void OnGenerousTip(object sender, EventArgs e) { tipPercentSlider.Value = 20; }
}

실행 및 Test

Layout 이 공간이 없고 크기도 맞지 않으므로 우리가 앞에서 배운 방식을 통해 정렬 및 resizing 해보자

 

Exercise.xaml 을 열고 VerticalStackLayout 에  padding 40 과 spacing 10 을 주자

<VerticalStackLayout Padding="40" Spacing="10">

Bill 과 12.4 를 그룹화 하기 위해 HorizontalStackLayout  에 Label 과 Entry 를 넣자

그리고 HorizontalStackLayout  의 Spacing 에 10 을 주자.

Bill 에 해당하는 Label 에 WidthRequest 를 100 을 주고 VerticalOptions 는 Center 를 주자

<HorizontalStackLayout Spacing="10">
    <Label Text="Bill" WidthRequest="100" VerticalOptions="Center"/>
    <Entry ... />
</HorizontalStackLayout>

 

Tip 에도 HorizontalStackLayout 을 이용하여 감싸고 Margin 0,20,0,0 을 주자.

Spacing 은 10 을 주자

Label 인 Tip 에 WidthRequest 를 100 주자

<HorizontalStackLayout Margin="0,20,0,0" Spacing="10">
    <Label Text="Tip" WidthRequest="100" />
    <Label .../>
</HorizontalStackLayout>

 

Total 에 대해서는 아래와 같이 수정하자

<HorizontalStackLayout Spacing="10">
    <Label Text="Total" WidthRequest="100"  />
    <Label .../>
</HorizontalStackLayout>

 

Tip Percentage

<HorizontalStackLayout VerticalOptions="EndAndExpand" Spacing="10">
    <Label Text="Tip Percentage" WidthRequest="100"/>
    <Label ... />
</HorizontalStackLayout>

 

Button (15%, 20%)

<HorizontalStackLayout  Margin="0,20,0,0" Spacing="10">
    <Button Text="15%" ... />
    <Button Text="20%" ... />
</HorizontalStackLayout>

 

Button (Round Down, Round Up)

<HorizontalStackLayout Margin="0,20,0,0" Spacing="10">
        <Button ... Text="Round Down" />
        <Button ... Text="Round Up" />
</HorizontalStackLayout>

 

그리고 모든 button 에 다음을 추가

<Button ... WidthRequest="150" HorizontalOptions="CenterAndExpand" ... />

전체 xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MauiApp1.Xaml.StackLayout.Exercise"
             Title="Exercise">
    <VerticalStackLayout Padding="40" Spacing="10">
        <HorizontalStackLayout Spacing="10">
            <Label Text="Bill"  WidthRequest="100" VerticalOptions="Center"/>
            <Entry x:Name="billInput" Placeholder="Enter Amount" Keyboard="Numeric" />
        </HorizontalStackLayout>

        <HorizontalStackLayout  Margin="0,20,0,0" Spacing="10">
            <Label Text="Tip" WidthRequest="100" />
            <Label x:Name="tipOutput" Text="0.00" />
        </HorizontalStackLayout>

        <HorizontalStackLayout Spacing="10">
            <Label Text="Total" WidthRequest="100"/>
            <Label x:Name="totalOutput" Text="0.00" />
        </HorizontalStackLayout>

        <HorizontalStackLayout VerticalOptions="EndAndExpand" Spacing="10">
            <Label Text="Tip Percentage"  WidthRequest="100"/>
            <Label x:Name="tipPercent" Text="15%" />
        </HorizontalStackLayout>
        
        <Slider x:Name="tipPercentSlider" Minimum="0" Maximum="100" Value="15" />

        <HorizontalStackLayout  Margin="0,20,0,0" Spacing="10">
            <Button Text="15%" Clicked="OnNormalTip" WidthRequest="150" HorizontalOptions="CenterAndExpand"/>
            <Button Text="20%" Clicked="OnGenerousTip" WidthRequest="150" HorizontalOptions="CenterAndExpand"/>
        </HorizontalStackLayout>
        <HorizontalStackLayout Margin="0,20,0,0" Spacing="10">
            <Button x:Name="roundDown" Text="Round Down" WidthRequest="150" HorizontalOptions="CenterAndExpand"/>
            <Button x:Name="roundUp"   Text="Round Up" WidthRequest="150" HorizontalOptions="CenterAndExpand"/>
        </HorizontalStackLayout>
    </VerticalStackLayout>
</ContentPage>

 

실행

 

 

관련영상

https://youtu.be/-0rImqg0Lck

반응형