프로그래밍/xamarin

xamarin 강좌 010. Layout (3) - StackLayout의 모든 것

panpro 2018. 9. 18. 23:27

 

 

 

xamarin은 마이크로소프트에서 Visual Studio와 함께 무료로 배포하고 있는 스마트폰 앱 개발 툴입니다.

 

xamarin은 크로스 플랫폼(cross platform) 기술로 한번 코드를 작성해 놓으면 안드로이드, 아이폰, 윈도우에서 실행되는 스마트폰 앱을 한꺼번에 만들 수 있는 강력한 도구입니다.

 

 

 

 

Xamarin 강의 목록

 

2018/09/17 - [프로그래밍/xamarin] - xamarin 강좌 009. Layout(2) - ScrollView

2018/09/16 - [프로그래밍/xamarin] - xamarin 강좌 008. Layout(1) - Frame Layout

2018/09/15 - [프로그래밍/xamarin] - xamarin 강좌 007. Page, Layout, View

2018/09/13 - [프로그래밍/xamarin] - xamarin 강좌 006. Custom Renderer를 만들며 배우는 자마린의 구조

2018/09/13 - [프로그래밍/xamarin] - xamarin 강좌 005. 데스크탑, 스마트폰 등 디바이스 타입마다 다른 UI 만들기

2018/09/12 - [프로그래밍/xamarin] - xamarin 강좌 004. 안드로이드, 아이폰, 윈도우, 플랫폼마다 다르게 실행되는 코드 만들기

2018/09/12 - [프로그래밍/xamarin] - xamarin 강좌 003. iOS 빌드를 위한 맥북 설정 - 아이폰 실행화면 보기

2018/09/11 - [프로그래밍/xamarin] - xamarin 강좌 002. xamarin 기본생성 프로젝트의 구조 - 버튼 추가

2018/09/10 - [프로그래밍/xamarin] - xamarin 강좌 001. xamarin의 시작


 

Stack Layout은 Xamarin 프로젝트를 만들면 기본으로 포함되어 있을 정도로 가장 많이 쓰이는 layout 입니다.

 

stackLayout은 Frame이나 ScrollView와 달리 여러 개의 요소들을 받을 수 있는 layout 입니다.

 

StackLayout안에는 view나 다른 layout 들이 들어올 수 있습니다.

 

 

<StackLayout>

  <Label … />

  <Label …>

  <Button …>

  <StackLayout>

    <Label... />

  </StackLayout>

</StackLayout>

 

 

이런 식이죠.

 

 

 

StackLayout의 중요한 속성 2가지

 

 

StackLayout에서 중요한 속성 2가지는

Orientation Spacing 입니다.

 

Orientation은 방향입니다.

 

StackLayout 에서는 그 방향대로 하나씩의 엘리먼트들만 놓으면서 쌓아가는 식으로 내부 엘리먼트들의 위치와 크기를 조정해 나가는데, 그 방향을 정해주는 속성입니다.

 

방향은 vertical 세로 방향과,

horizontal 가로 방향

 

이렇게 2가지가 있습니다.

 

<StackLayout Orientation="Vertical">
        <Label Text="Hello 1" BackgroundColor="Green"/>
        <Label Text="Hello 2" BackgroundColor="Green"/>
        <Label Text="Hello 3" BackgroundColor="Green"/>
        <Label Text="Hello 4" BackgroundColor="Green"/>
</StackLayout>

 

 

 

Orientation 의 기본값은 vertical 이라 따로 써주지 않아도 vertical이 됩니다.

 

위 코드에 Orientation만 Horizontal로 바꿔주면 ,

 

 

<StackLayout Orientation="Horizontal">
        <Label Text="Hello 1" BackgroundColor="Green"/>
        <Label Text="Hello 2" BackgroundColor="Green"/>
        <Label Text="Hello 3" BackgroundColor="Green"/>
        <Label Text="Hello 4" BackgroundColor="Green"/>
</StackLayout>

 

 

 

 

 

 

Vertical, Horizontal 모두 여기서 중요한 특징이 보이는데,

그건 해당 방향으로는 한줄, 혹은 한칸에 하나의 엘리먼트들만 놓는다는 점입니다.

 

Orientation = Vertical 일때는 세로방향으로 내려가니까 각 줄에 하나씩만 Label을 놓았습니다.

Orientation = Horizontal 일때는 가로방향으로 옆으로 가니까 각 칸에 하나씩만 Label을 놓았습니다.

 

이게 무지 중요한 속성이에요. 이걸 이해해야 StackLayout에 대해 정확하게 이해할 수 있어요.

 

 

Spacing

 

이렇게 한쪽 방향으로 쌓아가다 보니 그 요소들 간의 간격 설정도 할 수 있어야겠죠.

그래서 Spacing 이라는 속성도 제공합니다.

 

Spacing의 기본값은 6 이에요.

그러니까 위 예제 2개 모두, Spacing 속성을 설정하지 않았으니 기본값인 6을 가져요.

Spacing = 6 인 상태의 모습인거죠.

 

 

<StackLayout Orientation="Vertical" Spacing="20">
        <Label Text="Hello 1" BackgroundColor="Green"/>
        <Label Text="Hello 2" BackgroundColor="Green"/>
        <Label Text="Hello 3" BackgroundColor="Green"/>
        <Label Text="Hello 4" BackgroundColor="Green"/>
</StackLayout>

 

 

이렇게 Spacing 속성값을 크게 주면,

 

 

간격이 더 많이 벌어집니다.

 

Spacing 값을 음수로 줄 수도 있어요.

 

 

    <StackLayout Orientation="Vertical" Spacing="-10">
        <Label Text="Hello 1" BackgroundColor="Green"/>
        <Label Text="Hello 2" BackgroundColor="Green"/>
        <Label Text="Hello 3" BackgroundColor="Green"/>
        <Label Text="Hello 4" BackgroundColor="Green"/>
    </StackLayout>

 

 

 

바짝 붙었죠.

 

 

여기까지만 보면 StackLayout은 굉장히 쉬운 layout인데, 이제 좀더 복잡한 걸 해보겠습니다.

 

 

 

 

Layout 관련 옵션들

 

모든 View들은 Layout 관련된 옵션을 가지고 있습니다.

 

View는 대체로 자기 스스로의 위치를 정하기 보다는(스스로 정하기도 함) Layout에게 자기가 원하는 위치를 말하고 그 위치로 옮겨 달라고 요청합니다.

 

view : 나를 가로 방향에서는 가운데에 놓아주고, 세로 방향으로 봤을 때는 맨 위에 놓아줘.

layout : 알았어. 최대한 가운데, 위에 놓아 줄께.

 

이런 식이에요.

 

 

이 때 사용하는 게

HorizontalOptions와 VerticalOptions 에요.

 

layout에게 이 view가 놓여질 위치를, 놓여졌으면 하는 위치를 알려주는 거지요.

 

HorizontalOptions는 가로 위치를,

VerticalOptions는 세로 위치를 요청해요.

 

 

두 옵션 모두 똑같이 4개의 값을 가질 수 있어요.

 

Start, End, Center, Fill

 

Start와 End는 Orientation 설정값에 따라 뜻이 바뀌는데,

 

Vertical에서, Start는 위, End는 아래 를 뜻해요.

Horizontal에서는, Start는 왼쪽, End는 오른쪽을 뜻해요.

 

[왼쪽 소스]

    <StackLayout>
        <Label Text="Vertical" FontSize="20" HorizontalOptions="CenterAndExpand" />
        <StackLayout Orientation="Vertical">
            <Label Text="Start" BackgroundColor="Yellow" HorizontalOptions="Start"/>
            <Label Text="Center" BackgroundColor="Yellow" HorizontalOptions="Center"/>
            <Label Text="End" BackgroundColor="Yellow" HorizontalOptions="End"/>
        </StackLayout>
    </StackLayout>

 

 

 

[오른쪽 소스]

    <StackLayout>
        <Label Text="Horizontal" FontSize="20" HorizontalOptions="CenterAndExpand" />
        <StackLayout Orientation="Horizontal">
            <Label Text="Start" BackgroundColor="Yellow" VerticalOptions="Start"/>
            <Label Text="Center" BackgroundColor="Yellow" VerticalOptions="Center"/>
            <Label Text="End" BackgroundColor="Yellow" VerticalOptions="End"/>
        </StackLayout>
    </StackLayout>

 

 

[결과]

 

   


Vertical의 Start, Center, End는 상당히 이해가 가요.

 

Vertical은 한줄에 하나씩 들어가는데,

수평 방향으로 봤을 때 빈 공간이 많으니 Left, Center Right의 위치에 자리잡았습니다.

 

 

Label이 이렇게 해달라고 layout에 요청하고, layout은 그걸 들어준거죠.

 

 

왜 Orientation이 Vertical일 때 HorizontalOptions만 요청했을까요?

 

세로방향으로 내려오면서 세로방향의 위치는 이미 layout이 Spacing 설정값에 따라 정했기 때문에 가로 방향의 위치(Left, Center, Right)만 요청하는 거에요.

 

그럼 Vertical일 때는 대부분 다 이해된 거 같네요.

 

 

그런데 horizontal에서는 왜 저렇게 나왔을까요.

이걸 이해하셔야 StackLayout을 제대로 이해하시는 거에요.

 

 

 

 

이 그림을 보시면 쌓이는 방향이 Horizontal이라 왼쪽에서 오른쪽으로 쌓여가게 되지요.

그러니 HorizontalOptions은 아무리 줘 봐야 소용없습니다.

 

이미 StackLayout이 Spacing 값에 의해 다음 "Start"라고 쓰인 label 다음에 "Center" 라고 쓰인 label이 놓일 위치를 정해 놓았기 때문이죠.

 

그래서 VerticalOptions을 주었습니다.

그런데 VerticalOptions을 준 것도 소용이 없네요.

 

이유는 모든 label 들의 높이가 다 똑같게 계산되어 위로 올려도 가운데 올려도 다 그 자리가 그 자리기 때문이에요.

 

이걸 이해하기 위해 다음 예제를 보세요.

 

    <StackLayout>
        <Label Text="Horizontal" FontSize="20" HorizontalOptions="CenterAndExpand" />
        <StackLayout Orientation="Horizontal">
            <Label Text="큰글씨" BackgroundColor="Yellow" FontSize="50"/>
            <Label Text="Start" BackgroundColor="Yellow" VerticalOptions="Start"/>
            <Label Text="Center" BackgroundColor="Yellow" VerticalOptions="Center"/>
            <Label Text="End" BackgroundColor="Yellow" VerticalOptions="End"/>
        </StackLayout>
    </StackLayout>

 

 

 

"큰글씨" label 때문에 StackLayout의 한 칸의 높이가 굉장히 커졌습니다.

 

그 높이는 그 옆에 계속 쌓이는 view 들에게도 영향을 미쳐 그 view들이 놓일 수 있는 공간이 위 아래로 넓어졌습니다.

그래서 Start, Center, End 가 차이나게 보이게 되었습니다.

 

 

 

Layout의 역할

 

layout은 자기가 관리하는 엘리먼트들(View나 다른 layout들)의 위치와 크기를 결정하는 역할을 합니다.

 

StackLayout은 자기가 관리하는 엘리먼트들이 어느 한방향으로 쌓이도록 "위치를 결정하는" 역할을 하지요.

여태까지는 StackLayout이 Label의 위치를 결정하는 역할에 대해서만 말씀드렸는데요,

 

StackLayout은 크기도 결정해 줍니다. view가 이 layout의 공간에 꽉 차게 크기를 키워줄지 아니면 그냥 원래 자기 크기대로만 할지 결정해 줍니다.

 

이렇게 할 수 있게 해주는 Layout option이 Fill 입니다.

 

    <StackLayout>
        <Label Text="Horizontal" FontSize="20" HorizontalOptions="CenterAndExpand" />
        <StackLayout Orientation="Horizontal">
            <Label Text="큰" BackgroundColor="Yellow" FontSize="50"/>
            <Label Text="Start" BackgroundColor="Yellow" VerticalOptions="Start"/>
            <Label Text="Center" BackgroundColor="Yellow" VerticalOptions="Center"/>
            <Label Text="End" BackgroundColor="Yellow" VerticalOptions="End"/>
            <Label Text="Fill" BackgroundColor="Yellow" VerticalOptions="Fill"/>
        </StackLayout>
    </StackLayout>

 

 

 

 

 

    <StackLayout>
        <Label Text="Vertical" FontSize="20" HorizontalOptions="CenterAndExpand" />
        <StackLayout Orientation="Vertical">
            <Label Text="큰" BackgroundColor="Yellow" FontSize="50"/>
            <Label Text="Start" BackgroundColor="Yellow" HorizontalOptions="Start"/>
            <Label Text="Center" BackgroundColor="Yellow" HorizontalOptions="Center"/>
            <Label Text="End" BackgroundColor="Yellow" HorizontalOptions="End"/>
            <Label Text="Fill" BackgroundColor="Yellow" HorizontalOptions="Fill"/>
        </StackLayout>
    </StackLayout>

 

 

 

 

 

이렇게 Fill 옵션은 Layout에게 요청해서 크기를 조정하게 합니다.

 

그런데, 이거 어디서 많이 본 거 아닌가요?

 

아래는 맨 처음 보여드렸던 소스인데요,

 

 

<StackLayout Orientation="Vertical">
        <Label Text="Hello 1" BackgroundColor="Green"/>
        <Label Text="Hello 2" BackgroundColor="Green"/>
        <Label Text="Hello 3" BackgroundColor="Green"/>
        <Label Text="Hello 4" BackgroundColor="Green"/>
</StackLayout>

 

 

 

아무런 옵션을 주지 않았더니 Fill 로 처리되어 있네요.

한줄 꽉 채우고 있죠.

 

Label 자체의 크기를 저렇게 꽉 채우도록 변경시킨 겁니다.

 

이걸 보고 알 수 있듯이 layout option을 따로 주지 않으면 Fill 이 적용됩니다.

Fill 이 기본값인 거죠.

 

 

 

 

 

Orientation과 Expand

 

StackLayout에서만 제공해주는 Layout 옵션이 있는데, 바로 Expand 옵션입니다.

 

여태까지는

Orientation 이 Vertical 이면 Horizontal 방향의 옵션에 대해서만,

Orientation 이 Horizontal 이면 Vertical 방향의 옵션에 대해서만 얘기했는데,

 

Expand 옵션은

 

Orientation 이 Vertical 이면 Vertical 방향에 대해서만,

Orientation 이 Horizontal 이면 Horizontal 방향에 대해서만 설정해야 효과를 발휘합니다.

 

 

    <StackLayout>
        <!-- Place new controls here -->
        <Label Text="Welcome to Xamarin.Forms!"
           HorizontalOptions="Center"
           VerticalOptions="CenterAndExpand" />
    </StackLayout>

 

프로젝트를 맨 처음 시작하면 위와 같이 되어 있죠.

이걸 실행하면,

 

 

 

이렇게 나옵니다.

 

문구가 제일 가운데에 나오는군요.

Label이 화면의 정 가운데에 위치하고 있다는 뜻이에요.

 

여기서는 Orientation을 정해주지 않아서 기본값인 Vertical을 쓰고 있습니다.

같은 방향인 VerticalOptions에 Expand 옵션을 사용했네요.

 

VerticalOptions="CenterAndExpand"

 

 

우리가 배운 Center 뒤에 AndExpand 가 붙은 형태의 옵션인데요,

4개의 옵션

 

Start

Center

End

Fill

 

모두 AndExpand 가 붙은

 

StartAndExpand

CenterAndExpand

EndAndExpand

FillAndExpand

 

옵션을 가지고 있습니다.

 

 

Expand 옵션은,

 

Vertical 방향일 때,

세로 방향, 즉 밑으로 쌓아가게 되는데,

 

이 경우처럼 하나만 쌓으면 밑에 공간에 많이 남게 되죠.

 

이럴 떄 AndExpand 옵션을 붙이면,

 

"남는 공간은 다 나한테 줘" 라는 뜻이 됩니다.

 

그래서 이 경우처럼

 

VerticalOptions="CenterAndExpand"

 

와 같이 하면

 

"남는 공간은 다 나한테 주고 나는 세로의 가운데에 놓아줘"

 

라고 요청하는 거에요.

 

여기서는 layout 안에 엘리먼트가 하나 밖에 없으니 혼자 모든 세로 공간을 다 차지하게 되는 거지요.

 

 

만약 EndAndExpand라고 한다면

 

먼저 남는 모든 공간을 다 차지하고 자기는 바닥에 붙게 됩니다.

 

 

    <StackLayout>
        <!-- Place new controls here -->
        <Label Text="Welcome to Xamarin.Forms!"
           HorizontalOptions="Center"
           VerticalOptions="EndAndExpand" />
    </StackLayout>

 

 

 

 

 

그런데 만약 2개 이상의 view가 AndExpand를 하면 어떻게 될까요?

 

    <StackLayout BackgroundColor="Green">
        <!-- Place new controls here -->
        <Label Text="Welcome to Xamarin.Forms 1"
           HorizontalOptions="Center"
           VerticalOptions="CenterAndExpand" BackgroundColor="Red"/>
        <Label Text="Welcome to Xamarin.Forms 2"
           HorizontalOptions="Center"
           VerticalOptions="CenterAndExpand" BackgroundColor="Red"/>
    </StackLayout>

 

 

 

이렇게 둘이 똑같이 공간을 나눠 가지게 됩니다.

 

더 자세히 보기 위해,

Label 자체의 크기도 변경시키는 옵션인 Fill을 이용해

FillAndExpand를 사용하면,

 

    <StackLayout BackgroundColor="Green">
        <!-- Place new controls here -->
        <Label Text="Welcome to Xamarin.Forms 1"
           HorizontalOptions="Fill"
           VerticalOptions="FillAndExpand" BackgroundColor="Red"/>
        <Label Text="Welcome to Xamarin.Forms 2"
           HorizontalOptions="Fill"
           VerticalOptions="FillAndExpand" BackgroundColor="Yellow"/>
    </StackLayout>

 

 

 

 

이렇게 됩니다.

 

 

 

 

글자를 가운데로

 

바로 위 예제에서 글자를 가운데 놓고 싶으시죠?

그런데 그건 Layout이 할 일이 아닙니다.

 

Layout은 그 안에 속한 label의 크기나 위치를 결정해 주는 녀석이지 글씨의 위치를 결정해 주는 게 아니에요.

 

Label의 크기가 커지면서 글씨도 Label의 정가운데로 오게 하고 싶으면

Layout Option이 아니라 Label 자체의 속성을 바꿔줘야 합니다.

 

그 속성은

 

VerticalTextAlignment 와

HorizontalTextAlignment 입니다.

 

VerticalTextAlignment 은 세로방향의 글자 정렬

HorizontalTextAlignment 은 가로방향의 글자 정렬입니다.

 

 

    <StackLayout BackgroundColor="Green">
        <!-- Place new controls here -->
        <Label Text="Welcome to Xamarin.Forms 1"
           HorizontalOptions="Fill"
           VerticalOptions="FillAndExpand" BackgroundColor="Red"
           VerticalTextAlignment="Center"
           HorizontalTextAlignment="Center"
/>
        <Label Text="Welcome to Xamarin.Forms 2"
           HorizontalOptions="Fill"
           VerticalOptions="FillAndExpand" BackgroundColor="Yellow"/>
    </StackLayout>

 

 

 

 

 

 

동영상 강의

 

Xamarin 동영상 강의로 더 자세히 배워 보세요.

 

 

 

 

 

소스코드


[공용코드(xa008) 프로젝트]


MainPage.xaml

 

 

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:xa010"
             x:Class="xa010.MainPage">

    <StackLayout Orientation="Vertical" Spacing="20" BackgroundColor="Green">
        <!-- Place new controls here -->
        <Label Text="Welcome"
           HorizontalOptions="CenterAndExpand"                
               VerticalOptions="CenterAndExpand"
               BackgroundColor="Red"/>

        <Label Text="Welcome2"     
               HorizontalOptions="Fill"
               VerticalOptions="FillAndExpand"
               HorizontalTextAlignment="Center"
               VerticalTextAlignment="Center"
               BackgroundColor="Red"/>
    </StackLayout>

</ContentPage>