궁금한 내용을 검색해보세요!
이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
서근 개발노트
티스토리에 팔로잉
SWIFTUI/View layout

SwiftUI : ZStack ( Spacer / offset / zIndex )

서근
QUOTE THE DAY

-
Written by SeogunSEOGUN

반응형

ZStack

Stack에는 가로방향 HStack, 세로방향 VStack, 겹겹히 쌓아있는 ZStack 총 세 가지 종류가 있습니다.

 

각 스택이 어떻게 사용되는지 알아보기 위해 2개의 사각형을 만들어 결과를 확인해 보겠습니다.

HStack {    //이 부분만 HStack, VStack, ZStack으로 수정해 봅니다.
 Rectangle()
    .fill(Color.green)
    .frame(width: 150, height: 150)
  Rectangle()
    .fill(Color.yellow)
    .frame(width: 150, height: 150)     
 }

ZStack 에서 offset

ZStack과 함께 offset을 사용하면 한 뷰를 다른 뷰 안에 배치 할 수 있습니다. 이 기능은 ZStack의 정렬을 제어 할 때 특히 유용합니다.

 

예를 들어, ZStack에 이름과 함께 사진을 보여주는 경우 .topTrailing정렬을 사용하여 이미지가 사용 가능한 모든 공간을 차지하도록하고, credit 라인은 오른쪽 상단에 .offset(x: -10, y: 15)를 넣어주어 카드 이름을 나타나게 해주겠습니다.

        ZStack(alignment: .topTrailing) {
            Image("card")
                .resizable()
                .scaledToFit()
            Text("Photo credit: 서근")
                .padding(4)
                .background(Color.black)
                .foregroundColor(.white)
                .offset(x: -10, y: 15)
        }

ZStack이 정말 초록색 사각형이 노란색 사각형에 가려진 것이 맞는것인지 확인하고자, 노란색 사각형에 위치를 이동시키는 offset수식어를 적용해봅니다.

ZStack {
 ...
 Rectangle()
    .fill(Color.green)
    .frame(width: 150, height: 150)
    .offset(x: 40, y:40)  //각각 x축과 y축으로 40씩 이동
 }

다시 정리해보면, H / V / Z 스택의 레이아웃은 다음 그림과 같은 모습으로 나타납니다.

Spacer()

VStack {
            Spacer()
            Text("Spacer").font(.title).background(Color.yellow)
        }
        .background(Color.blue)
        
    }
ZStack {
            Spacer()
            Text("Spacer").font(.title).background(Color.yellow)
        }
        .background(Color.blue)
        
    }

왼쪽 : VStack    /     오른쪽 : ZStack

왼쪽의 VStackHStack과 같은 특성을 가지므로 축을 따라 늘어났다는 것은 쉽게 알겠지만, ZStack에선 왜 보이지 않는 걸까요? ZStackSpacer은 최대 크기로 확장 된다고 그랬었는데 말이죠.

 

그 이유는 ZStack에서 Spacer은 다른 형제 뷰의 최대 크기만큼만 확장 되기 때문입니다.

 

현재 Spacer의 형제 뷰는 Spacer라는 문자열을 가진 텍스트밖에 없기에 Spacer도 이 크기를 가지게 되어 가려지게 된 것입니다.뷰 계층 구조를 확인해 보면 텍스트 뒤로 Spacer가 그려져 있는 것을 알 수 있습니다.

그래서 ZStack에서는 Color.clearRectangle처럼 부모 뷰의 크기만큼 커지려는 확장성을 지닌 뷰를 Spacer 대신 사용할 수 있습니다.

      ZStack {
            Color.clear
            Text("Spacer").font(.title).background(Color.yellow)
        }
        .background(Color.blue)
    }
}

뷰 레이어링의 순서 변경

기본적으로 ZStack은 뷰의 깊이를 결정하기 위해 painter의 알고리즘을 사용하여 ZStack뷰를 계층화합니다. 첫 번째에 입력 한 내용이 먼저 그려진 다음 후속 뷰가 그 위에 계층화됩니다.

 

이 구조를 원하는 경우가 많지만 때로는 더 많은 제어가 필요합니다. 예를 들어 앱이 실행되는 동안 어떠한 뷰를 다른뷰 뒤로 밀거나 탭할 때 특정 뷰를 앞으로 가져오고 싶을때가 있습니다.

 

이렇게하려면 .zIndex()수정자를 사용해야합니다.

 

뷰의 기본 Z index0이지만 다른 뷰의 위 또는 아래에 각각 배치하는 양수 또는 음수 값을 제공 할 수 있습니다.

        ZStack {
            Rectangle()
                .fill(Color.green)
                .frame(width: 50, height: 50)

            Rectangle()
                .fill(Color.red)
                .frame(width: 100, height: 100)
        }

이렇게 코드를 작성해보면 맨위에 올라오는 상자는 red 입니다. 만약 green 박스를 위로 올려주고 싶다면 zIndex() 수정자를 사용하여 순서를 변경 할 수 있습니다.

ZStack {
    Rectangle()
        .fill(Color.green)
        .frame(width: 50, height: 50)
        .zIndex(1)

    Rectangle()
        .fill(Color.red)
        .frame(width: 100, height: 100)
}

TIP
 
 

zIndex()수정자는 현재 ZStack 내부의 그리기 순서에만 영향을줍니다. 즉, 두 개의 겹치는 스택이있는 경우 스택의 ZIndex()와 스택 내부의 뷰에 대해 생각해야합니다.

 

 

읽어주셔서 감사합니다🤟

 


잘못된 내용이 있으면 언제든 피드백 부탁드립니다.


서근


위처럼 이미지 와 함께 댓글을 작성할 수 있습니다.