안녕하세요, 오랜만에 포스팅을 하는 마늘맨입니다.
오늘 포스팅할 내용은 엄청 큰건 아니지만 의외로 좀 헤매실 수 있는 내용이라 정리해보았습니다.
애플의 HIG에 딱히 부합하는 뷰는 아니에요..
그렇지만 이런 뷰 자주 만드시죠..?
저도 요런 상단에 탭이 있는 뷰들을 자주 만들게 되는데요 ~
오늘은 TCA로 이 탭뷰 만드는 방법을 알아보도록 하겠습니다.
탭을 누르면 인디케이터가 움직여주면 되구요!
스와이프 해서 페이징이 가능하고
상단을 탭해도 이동이 되면 되겠죠 !
상단탭은 사실 대강 만들어도 됩니다. 오늘의 핵심 주제는 TCA + TabView의 케이스 스터디 이기 때문에...
import SwiftUI
import ComposableArchitecture
struct TopTabView: View {
@Bindable
var store: StoreOf<RandomProfileListReducer>
var body: some View {
VStack {
HStack {
ForEach(self.store.tabList.map { $0.rawValue }, id: \.self) { title in
VStack {
Text(title)
.frame(maxWidth: .infinity, minHeight: 50)
.foregroundStyle(.gray)
}
.onTapGesture {
Task {
withAnimation {
if let index = store.tabList.firstIndex(where: { $0.rawValue == title }) {
store.send(.changeTabIndex(index))
} else {
store.send(.changeTabIndex(0))
}
}
}
}
}
}
GeometryReader(content: { geometry in
HStack {
let capsuleWidth = geometry.size.width / CGFloat(store.tabList.count)
Capsule()
.frame(width: capsuleWidth, height: 3)
.position(x: geometry.size.width / CGFloat(store.tabList.count) * CGFloat(store.state.selectedIndex) + (capsuleWidth / 2) )
}
})
}
.animation(.easeIn)
}
}
이제 아래에 탭뷰를 추가해줍니다.
이때 상위 리듀서를 공유하도록 작성해야 탭을 눌러서 페이징을 하든, 스와이프를 해서 페이징을 하든 싱크가 맞겠죠~
코드 보시면 아시겠지만! RandomProfileListReducer.State의 내부에 selectedIndex, Action으로 changeTabIndex를 준비해두셔야 되겠죠!
저는 그냥 저 표현 $store.selectedIndex.sending(\.changeTabIndex) 를 바로 못찾아서 조금 해맸습니다~
import SwiftUI
import ComposableArchitecture
enum GenderType: String, CaseIterable {
case male = "남성"
case female = "여성"
case text = "test1"
case test1 = "test2"
}
struct RandomProfileView: View {
@Bindable var store: StoreOf<RandomProfileListReducer>
var body: some View {
VStack {
// 위에서 만든 상단의 탭뷰
TopTabView(store: self.store)
// 페이징이 되는 진짜(?) 탭뷰
TabView(selection: $store.selectedIndex.sending(\.changeTabIndex)) {
ForEach(GenderType.allCases.indices) { index in
ProfileListView(store: self.store)
.tag(index)
}
}
.tabViewStyle(.page(indexDisplayMode: .never))
}
}
}
[iOS] CoreTelephony 를 활용하여 Cellular data 사용 가능 여부 알기 (0) | 2023.10.26 |
---|---|
[Swift] Decimal, Double의 소수점을 round, ceil, floor하기 (1) | 2023.06.26 |
[Swift Concurrency] Async/Await 진짜 쉽게 이해하기 (3) - 흔히 하는 실수 (1) | 2023.06.13 |
[Swift Concurrency] Async/Await 진짜 쉽게 이해하기 (2) - 작성법 배우기 (0) | 2023.06.13 |
[Swift Concurrency] Async/Await 진짜 쉽게 이해하기 (1) - Do,Try,Catch 알기 (5) | 2023.06.12 |