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

SwiftUI : HStack / Spacer / minLength / Frame

서근
QUOTE THE DAY

-
Written by SeogunSEOGUN

반응형

 

HStack

앞에 Stack은 뷰 컨테이너이자 하나의 뷰라고 했습니다. 따라서 스택에도 뷰 프로토콜이 가진 수식어를 적용할 수 있습니다.

 

우선 HStack 주위로 테두리를 그려봅시다.

 

참고로 여기서padding을 먼저 적용하지 않으면 텍스트 주위로 바짝 붙어서 여백이 없어지니 순서에 유의해주세요.

HStack {
            Text("HStack")
            .font(.title)  //이미 폰트크기를 정해줬기때문에 밖에있는 largeTitle은 영향X
            .foregroundColor(.blue)
           
           Text("은 뷰를 가로로 배열합니다")
            Text("!")    
    }
        .padding()
        .border(Color.black)   //border은 테두리를 뜻한다.
        .font(.largeTitle)

이처럼 largeTitle 폰트를 HStack에 적용하게 되면, 그 내부의 모든 자식 뷰에 영향을 주게 됩니다.

 

단, HStack 이라는 문자열을 가진 텍스트는 title 폰트가 이미 정해져 있기 때문에, 그 뷰 자신에 적용된 설정이 우선시되어 largeTitle이 적용 되지 않습니다.

Frame( )

SwiftUI에서 FrameUIKit에서 프레임을 설정했던 것과는 다릅니다. SwiftUI의 수식어는 뷰를 직접 변경하는 것이 아니라 원래의 뷰를 수식하는 새로운 뷰를 반환합니다.

 

SwiftUI의 뷰는 필요한 만큼만 공간을 차지하지만 변경하려는 경우 frame()수정자를 사용하여 SwiftUI에 원하는 크기 범위를 알릴 수 있습니다.

Text("Frame") //Text타입
Text("Frame").frame(width: 100, height: 100) //ModifiedContent<Text, _FrameLayout>

위 코드에서 Textframe수식어를 적용하니 Text타입이 아닌 ModifiedContent타입으로 바뀐 것을 볼 수 있는데, 이처럼 SwiftUI에서 프레임은 제약 조건을 설정하는 것이 아니라, 액자처럼 콘텐츠를 담고 있는 하나의 뷰라는 점을 인식해야 합니다.

프레임의 역할

SwiftUI에서 프레임은 자식 뷰가 사용 가능한 키기를 제안하기 위해 사용됩니다. 동시에 뷰의 정렬 위치를 결정하는 역할도 하죠. 이제 어느 위치에 그림을 배치할 것인지도 정할 수 있습니다. Frame 수식어에는 Alignment 타입을 가진 alignment 매개 변수가 있어 위치를 지정해 줄 수 있습니다.

VStack(spacing: 20) {
    Text("서근개발블로그").background(Color.yellow)
        .frame(width:200, height: 200, alignment: .leading)
        .border(Color.blue)
    Text("서근개발블로그").background(Color.yellow)
        .frame(width:200, height: 200, alignment: .center)
        .border(Color.blue)
    
    Text("서근개발블로그").background(Color.yellow)
        .frame(width:200, height: 200, alignment: .trailing)
        .border(Color.blue)   
}

Button {
    print("Button tapped")
} label: {
    Text("Welcome")
        .foregroundColor(.black)
        .frame(minWidth: 0, maxWidth: 200, minHeight: 0, maxHeight: 200)
        .font(.largeTitle)
        .background(Color.blue)
        .clipShape(Circle())
}

배경화면을 꽉 채우는 방법

.frame(maxWidth: .infinity, maxHeight: .infinity)

        Text("서근개발노트")
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .font(.largeTitle)
            .foregroundColor(.black)
            .background(Color.yellow)

 

SafeArea까지 채우는 방법

ignoresSafeArea() 또는 .edgesIgnoringSafeArea(.all)

        Text("서근개발노트")
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .font(.largeTitle)
            .foregroundColor(.black)
            .background(Color.yellow)
            .ignoresSafeArea()

Spacer( )

Spacer()은 뷰 사이의 간격을 설정하거나 뷰의 크기를 확장할 용도로 사용되는 레이아웃을 위한 뷰입니다. 

 

SwiftUI에서는 기본적으로 view를 중앙에 배치합니다. 즉, 세 개의 text view VStack모두 내부에 배치하면 화면의 수직 중앙에 배치됩니다. 이를 변경하려면 (화면의 상단, 하단, 왼쪽 또는 오른쪽으로 보기를 강제하려는 경우) Spacer() 를 사용해야 합니다

 

스택 외부에서 사용할 때와 스택 내부에서 사용될 때 그 특성이 각각 달라지게 됩니다.

 

스택 외부에서 단독으로 사용

  • 부모 뷰가 제공하는 공간 내에서 가능한 최대 크기로 확장.
  • 시작적 요소를 적용할 수 있는 하나의 뷰로 사용됨.

HStack / VStack 내부에서 사용

  • 시각적 요소가 제외되고 단지 공간을 차지하기 위한 역할로만 가능하며,
  • 만약 콘텐츠가 없이 단독으로 사용되었을 경우는 아예 뷰가 없는 것처럼 취급됩니다.

 

다음 두 가지 경우를 나누어 실행해 보고 결과를 알아봅시다.

//스택 내부에서 
  HStack {
    Spacer()
    .background(Color.blue)  //출력되는 내용 없음
}
//스택 외부에서 
struct ContentView: View {
    var body: some View {
         
        Spacer().background(Color.blue)  //공간 최대 확장. 시각적 요소 표현 가능
    }
}

 

만약 텍스트를 view의 3분의 1 아래에 배치하고 싶다면 앞에 Spacer()를 두고 텍스트 뒤에 두 번 배치하면 됩니다.

        VStack {
            Spacer()
            Text("Hello World")
            Spacer()
            Spacer()
        }

이번엔 스택에 다른 콘텐츠가 함께 포함되어있을 때 어떤 모습이 될지 확인해 봅시다.

HStackSpacer()와 함께 텍스트를 하나 추가해주세요.

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

가로축에 대해 최대 크기 확장

Spacer를 이용한 배치 방법

 VStack {
            Text("제목")
                .font(.largeTitle)
            Text("부제목")
                .foregroundColor(.gray)
            Spacer()
            Spacer()
            Text("본문내용")
            Spacer()
            Text("각주")
            
        }
        .font(.title)
        .frame(width: 300, height: 500)
        .padding()
        .border(Color.black, width: 2) //width 두께
    }
}

Spacer().frame()

만약 Spacer()의 길이를 제한하고 싶다면 frame() 수식어를 사용합니다.

HStack {
            Spacer().frame(width: 100)
            Text("Spacer").font(.title).background(Color.yellow)
            
            
        }.background(Color.blue)

정확한 크기의 Spacer()를 만들려면 frame()을 사용하여 원하는 정확한 크기의 수정자를 사용할 수 있습니다.

 

예제 1

VStack {
    Text("First Label")
    Spacer()
        .frame(height: 50)
    Text("Second Label")
}

왼: Spacer() 만 적용  /  오 : Spacer().frame 적용

예제 2

struct ContentView: View {

    var body: some View {
        HStack {
            Image(systemName: "message.fill")
            Text("Inbox")
            Spacer()
            Image(systemName: "chevron.right")
        }
        .padding(.horizontal)
    }
}

Spacer() 적용
Spacer() 미적용

struct ContentView: View {

    var body: some View {
        HStack {
            Image(systemName: "message.fill")
            Text("Inbox")
            Spacer().frame(height: 10).background(Color.blue)
            Image(systemName: "chevron.right")
        }
        .padding(.horizontal)
    }
}

Spacer()가 차지하는 공간을 보려면 background를 추가해보면 됩니다.

minLength

예제 1

Spacer()은 사용 가능한 공간과 뷰의 크기에 따라 간격을 알아서 조절하는데, minLength(길이 제한)의 값을 설정하면 최소 간격을 지정할 수도 있습니다. (더 작아지지는 않는다)

HStack {
            Text("Spacer MinLength")
                .font(.title)
                .foregroundColor(.white)
            
            Spacer(minLength: 150)
            
            Text("Spacer").font(.title).background(Color.yellow)
        }
        .background(Color.blue)
    }
}

minLength 미지정
minLength: 150

예제 2

struct ContentView: View {

    var body: some View {

        HStack {
            Image(systemName: "message.fill")
            Spacer(minLength: 10)
            Text("사용 가능한 공간과 뷰의 크기에 따라 간격을 알아서 조절하는데, minLength(길이제한) 의 값을 설정하면 최소 간격을 지정할 수도 있습니다").lineLimit(1)
        }
    }
}

minLength : 0
minLength : 10
minLength : 50

 

 

읽어주셔서 감사합니다🤟


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


서근


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