Tip TabBar 와 ToolBar는 모두 화면 하단에 나타나지만, 서로 다른 목적을 갖는다 탭 바는 한 화면에서 탭에따라 다른 뷰를 표시해 주지만, ToolBar의 경우 항목 생성, 필터링, 콘텐츠 표시등을 위한 버튼 등이 포함된다 TabBar와 ToolBar는 동시에 표시할 수 없다.
지켜야 할점
어떠한 기능을 수행하기 위해 사용하지 말고, 오직 탭을 전환하는 용도로만 사용할것
View의 요소에 어떠한 기능을 제공해야 하는 경우Toolbar를 사용할것.
적당한 수의 탭을 사용할것, iPhone의 경우 3~5개 , iPad의 경우 조금더 많이 사용할것
⇒ 너무 많거나, 너무 적으면 오히려 디자인적 요소가 깨짐
iPadOS 앱에서는 TabBar대신SideBar를 사용하도록 권장
Modal View를 제외한 다른 View에서 언제 어디서나 유저가 바로 이동할수 있도록 TabBar를 숨기지 말것
해당 탭의 컨텐츠를 이용할수 없는 경우에도 Tab을 숨기지 말고 이용할 수 없는 설명을 보여줄것
현재 선택된 탭에서 다른 탭의 View에 영향을 끼치지 말아야 함
→ 예를 들어, 분할된 view의 왼쪽에 부분에 있는 tab을 선택했다면, 분할된 view의 오른쪽에 갑자기 변경되지 않아야 하고 Popover에서 tab을 선택했다면 popup 뒤의 뷰가 변경되지 않아야 한다
소통을 위해서 badge를 사용할것 ( 알림이 있다면 뱃지를 사용하여 표시 ) ex) 카카오톡 채팅 탭
본 내용은 스윗한 SwiftUI 책에 있는 예제를 공부한 내용입니다. 해당 예제들에 대한 저작권은 BJpublic 에 있습니다.
이미지에 frame 속성을 사용해도 이미지 자체의 크기를 변경해 주진 않음
Resizable 속성을 사용하여 이미지 크기를 변경할 수 있음
HStack {
Image("imgFile") // 이미지 크기는 변하지 않고, 이미지를 포함함 뷰의 크기가 변함
.frame(width: 50, height: 50)
Image("imgFile").resizable() // resizable() 을 사용하여 이미지 크기 자체가 변함
.frame(width: 200, height: 50)
}
frame 은 View의 속성이기 때문에 resizable 과 순서가 중요함!
resizable() 을 사용하여 특정 영역만 늘려주는 것도 가능함
단, UIKit 처럼 ResizingMode 를 생략하면tile이 아니라stretch가 기본값이 됨
HStack(spacing: 30){
// 기본값
Image("swift").resizable().frame(width: 100, height: 150)
// UIKit의 Aspect Fit 적용
Image("swift").resizable()
.scaledToFit()
.frame(width: 100, height: 150)
// UIKit의 Aspect Fill 적용
Image("swift").resizable()
.scaledToFill()
.frame(width: 100, height: 150)
}
AspectRatio
이미지 비율을 좀더 세부적으로 조정하기 위해 사용하는 수식어
모든 콘텐츠가 적용된 상황에서 추가적으로 비율조정을 하기위해 사용
// CGFloat : 너비 / 높이 를 계산한 비율을 전달
func aspectRatio(_ aspectRatio: CGFloat? = nil, contentMode: ContentMode) -> some View
// CGSize : 너비 와 높이를 각각 설정
func aspectRatio(_ aspectRatio: CGFloat? = nil, contentMode: ContentMode) -> some View
AspectRatio 적용한 예제
HStack(spacing: 30) {
//scaledToFit 콘텐츠 모드를 적용한 뒤, 너비가 높이보다 1.6배 비율을 가지도록 조정
Image("swift").resizable()
.aspectRatio(CGSize(width: 1.6, height: 1), contentMode: .fit)
.frame(width: 150, height: 150)
// scaledToFill 콘텐츠 모드를 적용한뒤, 너비가 높이보다 0.7배의 비율을 가지도록 조정
Image("swift").resizable()
.aspectRatio(0.7, contentMode: .fill)
.frame(width: 150, height: 150)
.clipped()
}
ClipShape
이미지를 원하는 모양으로 조정
크기 또한 조정 가능
HStack(spacing: 30) {
// 원 모양
Image("swift").clipShape(Circle())
// 이미지 크기보다 사방으로 10씩 크기를 조정한 사각형
Image("swift").clipShape(Rectangle().inset(by: 10))
// 크기와 위치를 직접 지정한 타원
Image("swift").clipShape(Ellipse().path(in: CGRect(x: 10, y: 10, width: 80, height: 110)))
}
RanderingMode
template : 이미지의 불투명 영역이 가진 본래의 색을 무시하고 원하는 색으로 변경
original : 항상 이미지의 본래 색을 유지
렌더링 모드를 생략하면 시스템이 알아서 조정을 하므로, 원치않은 결과가 나오면 렌더링 모드를 지정해야함
HStack(spacing: 30) {
// 렌더링 모드 생략 -> 시스템이 스스로 결정
Image("swift")
// 원본 이미지 색상 유지
Image("swift").renderingMode(.original)
// template 모드 적용
Image("swift").renderingMode(.template)
}
.foregroundColor(.blue) // 자식 뷰 모두에게 일괄 적용
본 내용은 스윗한 SwiftUI 책에 있는 예제를 공부한 내용입니다. 해당 예제들에 대한 저작권은 BJpublic 에 있습니다.
전체적으로 훑어보기
VStack(spacing: 30) { // 세로 방향으로 뷰를 배열하는 컨테이너 뷰
Text("폰트와 굵기 설정")
.font(.title) // 폰트 설정
.fontWeight(.black) // 폰트 굵기
Text("글자색은 foreground, 배경은 background")
.foregroundColor(.white)
.padding() // 텍스트 주변 여백 설정
.background(Color.blue)
Text("커스텀 폰트, 볼드체, 이탤릭체, 밑줄, 취소선")
.font(.custom("Menlo", size: 16))
.bold()
.italic()
.underline()
.strikethrough()
Text("라인 수 제한과 \\n 텍스트 정렬 기능입니다. \\n 이건 안 보입니다.")
.lineLimit(2)
.multilineTextAlignment(.trailing) // 다중행 문자열의 정렬 방식 지정
.fixedSize() // 주어진 공간의 크기가 작아도 텍스트를 새략하지 않고 표현하도록 설정
// 2개 이상의 텍스트를 하나로 묶어서 동시에 적용
(Text("자간과 기준선").kerning(8) //자간
+ Text(" 조정도 쉽게 가능합니다.").baselineOffset(8)) // 기준선
.font(.system(size: 16))
Text 수식어 적용의 순서의 중요성
Text 와 View 의 font, foregroundColor 의 정의
extention Text {
// Text와 View 모두 있는 수식어
public func font(_ font: Font?) -> Text
public func foregroundColor(_ color: Color?) -> Text
// Text에만 있는 수식어
public func bold() -> Text
public func italic() -> Text
}
extention View {
// Text와 View 모두 있는 수식어
public func font(_ font: Font?) -> some View
public func foregroundColor(_ color: Color?) -> some View
// View 에만 있는 수식어
public func padding(
_ edges: Edge.Set = .all,
_ length: CGFloat? = nil
) -> some View
}
Text에도, View에도 font 와 foregrountColor 가 정의되어 있다
단, 반환 타입이 다름을 주시하자
View 에만 있거나, Text에만 있는 경우 순서가 중요하다
잘못된 순서로인한 변화 예제
Text("SwiftUi")
.font(.title) // Text - 호출자의 타입이 Text
.bold() // Text
.padding() // View - padding 수식어 호출 이후로는 Text가 아닌 View 반환
Text("SwiftUi")
.bold() // Text
.padding() // View
.font(.title) // View - 동일한 font 수식어를 호출해도 호출자에 따라 반환타입 다름
Text("SwiftUi")
.padding() // View
.bold() // 컴파일 오류 - View에는 bold 가 정의되어 있지 않기 때문
.font(.title)
Text("SwiftUi")
.font(.title) // View
.padding() // View
.bold() // 컴파일 오류 - View에는 bold 가 정의되어 있지 않기 때문
잘못된 순서로 인한 변화 예제2
// 1번
Text("🐶🐱🐭🐹🐼").font(.largeTitle)
.background(Color.yellow) // 배경 색상지정이 Text 크기에 따라 우선 적용
.padding() // 배경 색상이 적용된 Text에 padding 적용
// 2번
Text("🐶🐱🐭🐹🐼").font(.largeTitle)
.padding() // Text에 Padding 을 우선 적용!
.background(Color.yellow) // padding 이 적용된 부분에 배경색상 지정
1번
2번
보이는 것과 같이 순서에 따라 View 자체가 어떻게 그려질지 보여준다
이처럼, SwiftUI에서는 수식어의 순서에 따라 오류가 날수도, 보여지는 뷰가 다를수도 있음을 유의하자