今回はList
の機能の一つである、セルの選択方法について説明します。
環境
- Xcode12.5.1
- iOS14.6
- スクショはiPhone12Pro Maxで撮影
初めに
条件は前回の記事【SwiftUI】Listの機能 – 行の並べ替え、削除 と同じです。
List
の基本的な実装方法は本記事では説明しません。とは言えコードは記載しますし、List
自体は非常に簡単に実装できると思います。
また、List
とForEach
で一覧表示を実装していること、ForEach
では更新可能な配列を使用しておりidを用いて識別されることが前提となります。
今回説明に使用するコードはこちらです。Person
は必ずHashable
に準拠するようにしてください。理由については今度詳しく説明します。
struct Person: Hashable{
var name: String
var age: Int
}
struct ContentView: View {
@State private var people = [Person(name: "John", age: 18),
Person(name: "Bob", age: 20),
Person(name: "Tony", age: 35),
Person(name: "Andy", age: 31)]
var body: some View {
VStack {
List {
ForEach(people, id: \.self) { person in
Text("\(person.name) : \(person.age)")
}
}
}
}
}
selectionを使う前に
selection
を使う前に、List
を編集可能な状態にするための準備が必要です。方法は2つあります。
1つは環境値.environment
を使って編集状態にする方法。
もう1つはEditButton()
を設置する方法です。
.environment
を使った方法
struct Person: Hashable{
var name: String
var age: Int
}
struct ContentView: View {
@State private var people = [Person(name: "John", age: 18),
Person(name: "Bob", age: 20),
Person(name: "Tony", age: 35),
Person(name: "Andy", age: 31)]
var body: some View {
VStack {
List {
ForEach(people, id: \.self) { person in
Text("\(person.name) : \(person.age)")
}
}
.environment(\.editMode, .constant(.active))
}
}
}
List
のモディファイアとして.environment(.editMode, .constant(.active))
をつけてあげるだけです。こうするとList
は常に編集可能な状態になります。
EditButton()
を設置する方法
struct Person: Hashable{
var name: String
var age: Int
}
struct ContentView: View {
@State private var people = [Person(name: "John", age: 18),
Person(name: "Bob", age: 20),
Person(name: "Tony", age: 35),
Person(name: "Andy", age: 31)]
var body: some View {
VStack {
EditButton()
List {
ForEach(people, id: \.self) { person in
Text("\(person.name) : \(person.age)")
}
}
}
}
}
レイアウトのどこかにEditButton()を置くだけです。こうするとボタンが表示され、そのボタンをタップするとList
を編集可能な状態になります。
selectionを使った単体選択
まずは、選択したセルの情報を保持する変数selectedValue
を用意します。今回はPerson型のデータをForEachで回して表示しているので、保持する変数もPerson型にします。このForEachで回すデータの型と選択したデータを保持する変数の型が一致していないと正しく動作しないので気をつけてください。
struct Person: Hashable{
var name: String
var age: Int
}
struct ContentView: View {
@State private var people = [Person(name: "John", age: 18),
Person(name: "Bob", age: 20),
Person(name: "Tony", age: 35),
Person(name: "Andy", age: 31)]
@State private var selectedValue: Person?
var body: some View {
VStack {
List {
ForEach(people, id: \.self) { person in
Text("\(person.name) : \(person.age)")
}
}
.environment(\.editMode, .constant(.active))
}
}
}
次に、List
のイニシャライザでselection
を指定します。引数には上で用意した変数selectedValue
を設定します。
struct Person: Hashable{
var name: String
var age: Int
}
struct ContentView: View {
@State private var people = [Person(name: "John", age: 18),
Person(name: "Bob", age: 20),
Person(name: "Tony", age: 35),
Person(name: "Andy", age: 31)]
@State private var selectedValue: Person?
var body: some View {
VStack {
List(selection: $selectedValue) {
ForEach(people, id: \.self) { person in
Text("\(person.name) : \(person.age)")
}
}
.environment(\.editMode, .constant(.active))
}
}
}
こうするだけでリストの左側に選択マークが表示され、セルの選択が可能になります。
これで選択したデータはselectedValue
に渡されるので、selectedValue
を使って色々と処理ができます。例として、選択中のデータのnameを表示するようにしてみましょう。VStack
の中に Text("選択:\(selectedValue?.name ?? "")")を追加します。
struct Person: Hashable{
var name: String
var age: Int
}
struct ContentView: View {
@State private var people = [Person(name: "John", age: 18),
Person(name: "Bob", age: 20),
Person(name: "Tony", age: 35),
Person(name: "Andy", age: 31)]
@State private var selectedValue: Person?
var body: some View {
VStack {
Text("選択:\(selectedValue?.name ?? "")")
List(selection: $selectedValue) {
ForEach(people, id: \.self) { person in
Text("\(person.name) : \(person.age)")
}
}
.environment(\.editMode, .constant(.active))
}
}
}
選択したデータのnameが表示されるようになりました。
複数選択する方法
複数選択する場合は、selectedValue
をSet<>
型にする必要があります。
Set<>型とは配列のようなもので、ユニークなデータしか保持しないため、同じデータを追加しようとしても追加されない特徴があります。また、データの順番という概念もありません。
struct Person: Hashable{
var name: String
var age: Int
}
struct ContentView: View {
@State private var people = [Person(name: "John", age: 18),
Person(name: "Bob", age: 20),
Person(name: "Tony", age: 35),
Person(name: "Andy", age: 31)]
@State private var selectedValue: Set<Person> = []
var body: some View {
VStack {
Text("\(selectedValue.count)")
List(selection: $selectedValue) {
ForEach(people, id: \.self) { person in
Text("\(person.name) : \(person.age)")
}
}
.environment(\.editMode, .constant(.active))
}
}
}
このようにselectedValue
をSet<Person>
という型にすることで、複数選択が可能になります。
今回は以上です。UIKitのUITableViewに比べて非常にシンプルな実装になりましたよね。
コメント