モバイルアプリには、リストはよくある画面構成だと思います。
表示するだけならさほど難しくないのかなと思いますが、表示されている内容を編集し、さらに編集後のデータをリストに反映されるには少しハードルが上がります。
実際リストを使う時は、内容の更新も普通にあると思いますので、例としてここに書き残します。
ソース
全体のソースは以下です。
//
// TestListView.swift
// UkiCalendar
//
// Created by ukiLab on 2024/05/02.
//
import SwiftUI
// 行のレイアウト
struct RowView: View {
let row: Row
var body: some View {
HStack {
Text(row.name)
Text(row.description)
}
}
}
// 行ごとのデータ構造
struct Row: Identifiable {
let id = UUID()
var name: String
var description: String
}
// 編集画面
struct EditSheet: View {
@Binding var rowBeingEdited: Row
var body: some View {
VStack {
TextField("Name", text: $rowBeingEdited.name) // ③
TextField("Description", text: $rowBeingEdited.description) // ③
}
}
}
// リスト画面
struct TestListView: View {
@State var rows: [Row] = [Row(name: "Name1", description: "Description1"),
Row(name: "Name2", description: "Description2"),
Row(name: "Name3", description: "Description3"),
Row(name: "Name4", description: "Description4"),
Row(name: "Name5", description: "Description5"),
Row(name: "Name6", description: "Description6")]
@State var rowID: UUID?
var body: some View {
NavigationView {
List {
ForEach($rows) { $row in
RowView(row: row)
// セルにスワイプすると編集ボタンが表示されます
.swipeActions(edge: .trailing, allowsFullSwipe: false) {
Button(action: {
rowID = row.id
}) {
Label("Edit", systemImage: "rectangle.and.pencil.and.ellipsis")
}
}
.sheet(isPresented: Binding<bool>( // ①
get: { row.id == rowID },
set: { _ in
rowID = nil
})
) {
EditSheet(rowBeingEdited: $row) // ②
}
}
}
.navigationBarTitle("サンプルリスト", displayMode: .inline)
}
}
}
#Preview {
TestListView()
}
上記を実行すると、まず最初の画面(つまりTestListView
)は次のように表示されます。
例として、3番目のセルを左へスワイプすると、次のように編集ボタンが表示されます。
編集ボタンを押すと、次のように編集画面(EditSheet
)が表示されます。
ここは例として、nameを”hello”に変更し、descriptionを”world”に変更します。
編集画面を下にスワイプすると、編集画面が消えて元のリスト画面が表示されます。
次のように、3番目のセルは”Hello World”に変わっていることを確認できます。
解説
元ネタは参考サイトほぼそのままですが、ここは少し整理しただけです。
実装うまいなと思った点を簡単に説明します。
- どのセルが押されたかを判定するために、変数として
rowID
を持ってます。
そして、①のようにBinding<bool>のgetとsetをカスタマイズして判定するようにしています。 - リスト画面から編集画面は②の
$row
のように参照渡ししています。
編集画面はその参照でもらったデータの属性をそのままTextFieldに渡してます。
そうすると、TextFieldの値を変更すると、元のリスト画面にあるrows
配列をそのまま変えられてしまう仕組みです。
リスト実装の参考になると嬉しいです。
コメントを残す