관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - SwiftUI] 튜토리얼 - 9. 수평 스크롤 뷰 구현 (TabView, VStack, HStack, ScrollView, NavigationLink) 본문

iOS 튜토리얼 (SwiftUI)

[iOS - SwiftUI] 튜토리얼 - 9. 수평 스크롤 뷰 구현 (TabView, VStack, HStack, ScrollView, NavigationLink)

jake-kim 2022. 7. 11. 23:22

구현된 뷰

* 전체 소스 코드는 튜토리얼에 있는 프로젝트 참고

TabView

TabView (Home과 List 아이템이 존재)

  • TabView와 .tabItem 속성을 이용하여 구현
    • 먼저 Tab의 케이스를 정의하고, 이 케이스를 상태로 갖고있는 프로퍼티도 선언
import SwiftUI

struct ExampleView: View {
  @State private var selection = Tab.home
  
  enum Tab {
    case home
    case setting
  }
}
  • body를 선언하여 내부에서 TabView(selection:)으로 selection 상태를 정의하고 클로저 내부에서 TabView안에 들어갈 뷰들을 구현
  var body: some View {
    TabView(selection: $selection) {
    	// 여기서 뷰 구현
    }
  }
  • 첫 번째 뷰 - 0~20까지의 값을 갖는 뷰
      List {
        ForEach([Int](0...20), id: \.self) {
          Text("\($0)")
        }
      }
  • 여기다가 tabItem과 tag를 이용하여 아이템을 등록
    • tabItem의 클로저에서 Label()을 통해 이름과 이미지 입력
      .tabItem { // <-
        Label("Home", systemImage: "house")
      }
      .tag(Tab.home)
  • 완성된 첫 번째 뷰
  // in ExampleView
  
  var body: some View {
    TabView(selection: $selection) {
      List {
        ForEach([Int](0...20), id: \.self) {
          Text("\($0)")
        }
      }
      .tabItem {
        Label("Home", systemImage: "house")
      }
      .tag(Tab.home)
      
   // TODO: 두 번째 탭에 들어갈 뷰 구현
  • 두 번째 뷰도 완성하여 2개의 tabItem이 존재하는 뷰 구현 완료
struct ExampleView: View {
  @State private var selection = Tab.home
  
  enum Tab {
    case home
    case setting
  }
  
  var body: some View {
    TabView(selection: $selection) {
      List {
        ForEach([Int](0...20), id: \.self) {
          Text("\($0)")
        }
      }
      .tabItem {
        Label("Home", systemImage: "house")
      }
      .tag(Tab.home)
      
      Text("Tab page 2")
        .tabItem {
          Label("List", systemImage: "list.bullet")
        }
        .tag(Tab.setting)
    }
  }
}

수평 스크롤 뷰 구현

https://developer.apple.com/tutorials/swiftui/composing-complex-interfaces

  • 아이디어
    • 수평 스크롤 뷰 = ScrollView안에 HStack을 넣고 이 안에 아이템을 넣어서 구현
    • ScrollView 안에 HStack을 넣는 이유: HStack을 넣으면 자동으로 height의 min값과 max값이 정해지므로 내부 크기가 정해져서 구현되므로 사용
  • 먼저 수평 스크롤 뷰 안에 들어갈 하나의 아이템 정의

스크롤 뷰에 들어갈 아이템

  • CategoryItem 구현
    • Vstack안에 Image와 Text가 존재하도록 구현
struct CategoryItem: View {
    var landmark: Landmark

    var body: some View {
        VStack(alignment: .leading) {
            landmark.image
                .renderingMode(.original)
                .resizable()
                .frame(width: 155, height: 155)
                .cornerRadius(5)
            Text(landmark.name)
                .foregroundColor(.primary)
                .font(.caption)
        }
        .padding(.leading, 15)
    }
}
  • 수평 스크롤 뷰 구현

수평 스크롤 뷰

import SwiftUI

struct CategoryRow: View {
  var categoryName: String
  var items: [Landmark]

}
  • VStack안에 하나의 Text와, ScrollView 구현
  var body: some View {
    VStack(alignment: .leading) {
      Text(categoryName)
        .font(.headline)
        .padding(.leading, 15)
        .padding(.top, 5)
      
      // TODO: ScrollView
  • ScrollView 구현
    • frame에 height값을 지정
ScrollView(.horizontal, showsIndicators: false) {

}
.frame(height: 185)
  • ScrollView 안에 HStack을 이용하여 리스트 구현
    • NavigationLink에는 다음 화면이 올 Detail로 정의하고, 보여지는 화면은 위에서 정의한 CategoryItem으로 선언
ScrollView(.horizontal, showsIndicators: false) {
  HStack(alignment: .top, spacing: 0) { // <-
    ForEach(items) { landmark in
      NavigationLink {
        LandmarkDetail(landmark: landmark)
      } label: {
        CategoryItem(landmark: landmark)
      }
    }
  }
}
.frame(height: 185)

* 만약 ScrollView안에 HStack을 쓰지 않으면 아래처럼 보여짐

HStack을 사용하지 않은 경우 - 세로로 배치되는 현상

* 참고

https://developer.apple.com/tutorials/swiftui/composing-complex-interfaces

 

Comments