SwiftUI において、リスト に登録した リストアイテム を 移動 する View を実装したかったのですが、 toolbar の EditButton を用いる実装では都度 Edit ボタン を クリック する必要があり、その手間を省けないかと思いました。 実装してみれば簡単なのですが、あまり サンプル も見つからなかったた事もあり、本記事で整理してみます。
Xcode: 12.4 Swift: 5
はじめに SwiftUI で リスト を実装
まずは、単純なリストを実装するところから始めます。
import SwiftUI struct ContentView: View { var body: some View { SampleList() } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
ContentView.swift
単純に5つの アイテム を生成し、 リスト に表示する シンプル な リスト です。
SampleList.swift
struct SampleList: View { struct Item: Identifiable { let id = UUID() let title: String } @State private var items: [Item] = (0..<5).map { Item(title: "Item #\($0)") } var body: some View { NavigationView { List { ForEach(items) { item in Text(item.title) } } } } }
EditButton を用いて、 リストアイテム を 移動 する
まずは、EditButton を用いた実装を紹介します。 なお、ここで NavigationView を追加していますが、追加せずとも動作するはずです。
以下の サイト を参考に、下記を追記しています。
- move function を定義
- リストアイテム の onMove の Perform アクション の Closure として指定
- リストの Modifier に toolbar を追加し、要素として EditButton を追加
SampleList.swift
struct SampleList: View { struct Item: Identifiable { let id = UUID() let title: String } @State private var items: [Item] = (0..<5).map { Item(title: "Item #\($0)") } var body: some View { NavigationView { List { ForEach(items) { item in Text(item.title) } .onMove(perform: move) } .navigationTitle("Navigation Title") .toolbar { EditButton() } } } private func move(source: IndexSet, destination: Int) { items.move(fromOffsets: source, toOffset: destination) } }
Editボタン を クリック することで、編集 モード になり、 リスト が移動できるようになります。
リストアイテム を常に 移動 できるようにする
UI によっては、都度 Edit ボタン を クリック するのが煩雑な場合もあるかと思います。
次に紹介するのは、 リスト の アイテム が常に移動できるようになる サンプル です。
以下の サイト を参考に、以下を実装します。
- リスト の environment Modifier の中で、 EditMode.active を指定
https://developer.apple.com/documentation/swiftui/environmentvalues
https://developer.apple.com/documentation/swiftui/editmode
SampleList.swift
struct SampleList: View { struct Item: Identifiable { let id = UUID() let title: String } @State private var items: [Item] = (0..<5).map { Item(title: "Item #\($0)") } var body: some View { NavigationView { List { ForEach(items) { item in Text(item.title) } .onMove(perform: move) } .navigationTitle("Navigation Title") .environment(\.editMode, .constant(EditMode.active)) } } private func move(source: IndexSet, destination: Int) { items.move(fromOffsets: source, toOffset: destination) } }
このように、 Edit ボタン を クリック することなく、 リスト の アイテム が常に移動可能となります。
まとめ
- List の onMove モディファイア で move 部分を実装
- Navigation View の environment モディファイア で \.editMode を指定することで 常に リスト を編集状態にすることが可能