SwiftUI Tutorials - Composing Complex Interfaces
上部にランドマークを強調表示しながら、下部の方ではカテゴリー分けして表示できるようにします。
新しいSwiftUIファイルCategoryHome.swiftを作り構造体CategoryHome.を作ります。
var body: some View {
NavigationView {
Text("Hello, World!")
.navigationTitle("Featured")
}
}
NavigationViewを設置しタイトルを表示させます。
Create a Category List
landmarkData.json のファイルにはすでにカテゴリが記入されているので、
Landmark.swiftにプロパティを追加します。
var category: Category
enum Category: String, CaseIterable, Codable {
case lakes = "Lakes"
case rivers = "Rivers"
case mountains = "Mountains"
次にModelData.swiftのクラスModelDataを編集していきます。
@Published var landmarks: [Landmark] = load("landmarkData.json")
としてすでに定義されているので 変数categoriesは変数landmarksを読み込んで使います。
var categories: [String: [Landmark]] {
Dictionary(
grouping: landmarks,
by: { $0.category.rawValue }
)
}
landmarksのデータを変数categoryで定義したenum Categoryの要素である3つのcaseのデータでカテゴリー分けをします。
grouping: landmarks,
by: { $0.category.rawValue }
次に、CategoryHome.swiftを編集していきます。
modelData を@EnvironmentObjectとして読み込みます。これで他のデータのアクセスができるようになります。
@EnvironmentObject var modelData: ModelData
そして
NavigationView {
List {
ForEach(modelData.categories.keys.sorted(), id: \.self) { key in
Text(key)
}
}
.navigationTitle("Featured")
}
でリスト表示させます。
Create a Category Row
カテゴリーは水平方向のスクロールビューを設定していきます。
新しいファイルCategoryRow.swiftを作り構造体CategoryRowを定義します。
変数を定義します。こちらがテンプレートになります。
var categoryName: String
var items: [Landmark]
Viewの部分を作ります。
var body: some View {
VStack(alignment: .leading) {
Text(categoryName)
.font(.headline)
.padding(.leading, 15)
.padding(.top, 5)
ScrollView(.horizontal, showsIndicators: false) {
HStack(alignment: .top, spacing: 0) {
ForEach(items) { landmark in
Text(landmark.name)
}
}
}
.frame(height: 185)
}
}
次に新しいCategoryItem.swiftファイルを作り、構造体 CategoryItemを作ります。こちらで実際のデータを入れるものを作ります。
var landmark: Landmark
var body: some View {
VStack(alignment: .leading) {
landmark.image
.resizable()
.frame(width: 155, height: 155)
.cornerRadius(5)
Text(landmark.name)
.font(.caption)
}
.padding(.leading, 15)
}
これをCategoryRow.swiftのScrollView()に適応します。
ScrollView(.horizontal, showsIndicators: false) {
HStack(alignment: .top, spacing: 0) {
ForEach(items) { landmark in
CategoryItem(landmark: landmark)
}
}
ForEach(items) { landmark in
CategoryItem(landmark: landmark)
}
Complete the Category View
カテゴリーViewの仕上げをしていきます。
CategoryHome.swiftを編集していきます。CategoryRow()を入れ込んでいきます。
List {
ForEach(modelData.categories.keys.sorted(), id: \.self) { key in
CategoryRow(categoryName: key, items: modelData.categories[key]!)
}
}
CategoryRow(categoryName: key, items: modelData.categories[key]!)
Landmark.swiftの構造体Landmarkにプロパティを追加します。
var isFeatured: Bool
そしてModelData.swiftのクラスModelDataに追加します。
var features: [Landmark] {
landmarks.filter { $0.isFeatured }
}
再度CategoryHome.swiftの構造体CategoryHomeを編集します。
NavigationView {
List {
modelData.features[0].image
.resizable()
.scaledToFill()
.frame(height: 200)
.clipped()
.listRowInsets(EdgeInsets())
ForEach(modelData.categories.keys.sorted(), id: \.self) { key in
CategoryRow(categoryName: key, items: modelData.categories[key]!)
}
.listRowInsets(EdgeInsets())
}
.navigationTitle("Featured")
}
modelData.features[0].image
リストの一番上に注目のものを表示します。
.listRowInsets(EdgeInsets())
.listRowInsets(EdgeInsets())
そして、幅いっぱいに表示できるようにします。
Add Navigation Between Sections
カテゴリ分けされたデータにアクセスする方法を整理していきます。
CategoryRow.swiftから編集していきます。
ScrollView(.horizontal, showsIndicators: false) {
HStack(alignment: .top, spacing: 0) {
ForEach(items) { landmark in
NavigationLink(destination: LandmarkDetail(landmark: landmark)) {
CategoryItem(landmark: landmark)
}
}
}
}
NavigationLink(destination: LandmarkDetail(landmark: landmark)) {
CategoryItem(landmark: landmark)
}
詳細画面LandmarkDetailへのリンクをNavigationLinkを使って遷移させます。
次にCategoryItem.swiftを編集します。
VStack(alignment: .leading) {
landmark.image
.renderingMode(.original)
.resizable()
.frame(width: 155, height: 155)
.cornerRadius(5)
Text(landmark.name)
.foregroundColor(.primary)
.font(.caption)
}
以下を追加しています。見た目の変更です。
.renderingMode(.original)
.foregroundColor(.primary)
最後にContentView.swiftを編集します。
タブで画面をTabView()を使って管 理するようにします。
struct ContentView: View {
@State private var selection: Tab = .featured
enum Tab {
case featured
case list
}
var body: some View {
TabView(selection: $selection) {
CategoryHome()
.tabItem {
Label("Featured", systemImage: "star")
}
.tag(Tab.featured)
LandmarkList()
.tabItem {
Label("List", systemImage: "list.bullet")
}
.tag(Tab.list)
}
}
}
この記事が気に入ったらサポートをしてみませんか?