Develop Apps for iOSをやってみる 〜その4〜
はじめに
DX推進室の野上です。
前回 の続きです
どこから?
だんだん長くなってきましたが、今回はここから続けます。
最初に
今回も用意されたプロジェクトファイルがあります。
が、前回と同じように無視します(ホントはダメ)
画面の遷移を作成する
NavigationViewを作る
NavigationView を使うことで階層的な画面遷移を実装することができます。
ルートViewをNavigationViewで囲ってみましょう。
ScrumdingerApp.swiftに修正を行います。
import SwiftUI
@main
struct ScrumdingerApp: App {
var body: some Scene {
WindowGroup {
NavigationView {
ScrumsView(scrums: DailyScrum.data)
}
}
}
}
次に、Listの各要素をタップした際の遷移をScrumsViewに実装していきましょう。
NavigationLinkを使って画面遷移を実装できます。
仮でscrum.titleをTextで表示する遷移を実装します。
Previewの方にNavigationViewも追加しておきます。
Previewが階層構造を理解して、自動的に戻る遷移実装してくれます。
import SwiftUI
struct ScrumsView: View {
let scrums: [DailyScrum]
var body: some View {
List {
ForEach(scrums) { scrum in
NavigationLink(destination: Text(scrum.title)) {
CardView(scrum: scrum)
.listRowBackground(scrum.color)
}
}
}
}
}
struct ScrumsView_Previews: PreviewProvider {
static var previews: some View {
NavigationView {
ScrumsView(scrums: DailyScrum.data)
}
}
}
CardViewに設定されているlistRowBackgroundをNavigationLinkの方に移動させます。
(ただしプロジェクトファイルをダウンロードして使っていないと意味がないです)
navigationTitleを使って、タイトルもつけておきましょう。
また、navigationBarItemsを使って、右上に今後要素を追加する際の+ボタンを表示しておきましょう。
この時点では、タップしても空のアクションが動作するだけです。
import SwiftUI
struct ScrumsView: View {
let scrums: [DailyScrum]
var body: some View {
List {
ForEach(scrums) { scrum in
NavigationLink(destination: Text(scrum.title)) {
CardView(scrum: scrum)
}
.listRowBackground(scrum.color)
}
}
.navigationTitle("Daily Scrums")
.navigationBarItems(trailing: Button(action: {}) {
Image(systemName: "plus")
})
}
}
struct ScrumsView_Previews: PreviewProvider {
static var previews: some View {
NavigationView {
ScrumsView(scrums: DailyScrum.data)
}
}
}
ここまでで画面は以下のようになっているはずです。
XCode上でPreviewを実行して、動作を確認してみてください。
各要素をタップすると、スクラムタイトルを表示する画面に遷移でき、元の画面に戻ることができるようになっているはずです。
Detail Viewを作る
新しくScrumの詳細を表示するViewを作成します。
DetailView.swiftを新しく作成して、以下の内容を記述します。
import SwiftUI
struct DetailView: View {
let scrum: DailyScrum
var body: some View {
Text("Hello, World!")
}
}
struct DetailView_Previews: PreviewProvider {
static var previews: some View {
NavigationView {
DetailView(scrum: DailyScrum.data[0])
}
}
}
DetailViewの仮実装ができたので、ScrumsViewのNavigationLinkのdestinationをDetailViewに変更しましょう。
import SwiftUI
struct ScrumsView: View {
let scrums: [DailyScrum]
var body: some View {
List {
ForEach(scrums) { scrum in
NavigationLink(destination: DetailView(scrum: scrum)) {
CardView(scrum: scrum)
}
.listRowBackground(scrum.color)
}
}
.navigationTitle("Daily Scrums")
.navigationBarItems(trailing: Button(action: {}) {
Image(systemName: "plus")
})
}
}
struct ScrumsView_Previews: PreviewProvider {
static var previews: some View {
NavigationView {
ScrumsView(scrums: DailyScrum.data)
}
}
}
これでListの要素をタップした際にDetailViewに遷移するようになりました。
次に、DetailViewの中身を実装していきましょう。
まずはMetting Infoから。
body部分のTextを変更して以下のようにします。
import SwiftUI
struct DetailView: View {
let scrum: DailyScrum
var body: some View {
List {
Section(header: Text("Meeting Info")) {
Label("Start Meeting", systemImage: "timer")
.font(.headline)
.foregroundColor(.accentColor)
.accessibilityLabel(Text("Start meeting"))
HStack {
Label("Length", systemImage: "clock")
.accessibilityLabel(Text("Meeting length"))
Spacer()
Text("\(scrum.lengthInMinutes) minutes")
}
HStack {
Label("Color", systemImage: "paintpalette")
Spacer()
Image(systemName: "checkmark.circle.fill")
}
.accessibilityElement(children: .ignore)
}
}
.listStyle(InsetGroupedListStyle())
}
}
struct DetailView_Previews: PreviewProvider {
static var previews: some View {
NavigationView {
DetailView(scrum: DailyScrum.data[0])
}
}
}
ここまででDetailViewは以下のような画面になっているはずです。
次にMeetingの参加者を表示します。
MEETING INFOと同じようにSectionを追加して、DailyScrumのattendeesを表示しましょう。
import SwiftUI
struct DetailView: View {
let scrum: DailyScrum
var body: some View {
List {
Section(header: Text("Meeting Info")) {
Label("Start Meeting", systemImage: "timer")
.font(.headline)
.foregroundColor(.accentColor)
.accessibilityLabel(Text("Start meeting"))
HStack {
Label("Length", systemImage: "clock")
.accessibilityLabel(Text("Meeting length"))
Spacer()
Text("\(scrum.lengthInMinutes) minutes")
}
HStack {
Label("Color", systemImage: "paintpalette")
Spacer()
Image(systemName: "checkmark.circle.fill")
.foregroundColor(scrum.color)
}
.accessibilityElement(children: .ignore)
}
Section(header: Text("Attendees")) {
ForEach(scrum.attendees, id: \.self) { attendee in
Label(attendee, systemImage: "person")
.accessibilityLabel(Text("Person"))
.accessibilityValue(Text(attendee))
}
}
}
.listStyle(InsetGroupedListStyle())
}
}
struct DetailView_Previews: PreviewProvider {
static var previews: some View {
NavigationView {
DetailView(scrum: DailyScrum.data[0])
}
}
}
これでDetailViewは以下のような画面になっているはずです。
最後に、Start MeetingをタップしたらMeetingViewに遷移するようにしましょう。
Start MeetingにNavigationLinkを設定します。
また、この画面のタイトルを設定します。
import SwiftUI
struct DetailView: View {
let scrum: DailyScrum
var body: some View {
List {
Section(header: Text("Meeting Info")) {
NavigationLink(destination: MeetingView()) {
Label("Start Meeting", systemImage: "timer")
.font(.headline)
.foregroundColor(.accentColor)
.accessibilityLabel(Text("Start meeting"))
}
HStack {
Label("Length", systemImage: "clock")
.accessibilityLabel(Text("Meeting length"))
Spacer()
Text("\(scrum.lengthInMinutes) minutes")
}
HStack {
Label("Color", systemImage: "paintpalette")
Spacer()
Image(systemName: "checkmark.circle.fill")
.foregroundColor(scrum.color)
}
.accessibilityElement(children: .ignore)
}
Section(header: Text("Attendees")) {
ForEach(scrum.attendees, id: \.self) { attendee in
Label(attendee, systemImage: "person")
.accessibilityLabel(Text("Person"))
.accessibilityValue(Text(attendee))
}
}
}
.listStyle(InsetGroupedListStyle())
.navigationTitle(scrum.title)
}
}
struct DetailView_Previews: PreviewProvider {
static var previews: some View {
NavigationView {
DetailView(scrum: DailyScrum.data[0])
}
}
}
これでScrumsView->DetailView->MeetingViewと遷移できるようになりました。
アプリをbuildして確認してみましょう。
ここまでのまとめ
- NavigationViewを使うと勝手に階層構造にしてくれる
- NavigationLinkで遷移先を指定できる
次回はDetailViewから内容を編集できるようにします。
(やっと中盤です・・・)