List の編集
並べ替え可能にする
swift
List {
ForEach ... {
...
}
.onMove { src, dst in
}
}
編集モードにするボタンを配置
swift
EditButton()
編集モード固定する
swift
List {
}
.environment(\.editMode, .constant(EditMode.active))
編集モードをコードから参照
swift
@Environment(\.editMode) var editMode
..
var isEditing: Bool {
editMode?.wrappedValue.isEditing ?? false
}
onMove
つけてると並べ替え出来てしまう(並べ替え用のボタンは出ないが)
↓
swift
@State var editActive: Bool = false
..
Button(editActive ? "Done" : "Edit") {
editActive.toggle()
}
..
List {
ForEach {
}
.onDelete { indexes in
appData.routePoints.remove(atOffsets: indexes)
}
.onMove { src, dst in
appData.books.move(fromOffsets: src, toOffset: dst)
}
.moveDisabled(!editActive)
// .deleteDisabled(true)
}
.environment(\.editMode, .constant(editActive ? EditMode.active : EditMode.inactive))
複数選択の行を削除
配列から IndexSet
に変換してい る
swift
Button("Delete Selected Rows", role: .destructive) {
let indexes = IndexSet(selectedRoutePoints.compactMap({ appData.routePoints.firstIndex(of: $0) }))
appData.routePoints.remove(atOffsets: indexes)
}
見た目系で、各行の要素に設定する
swift
List {
ForEach {
Xxxx
.listRowBackground(Color.clear) // タップのときに背景色がつけないようにする
.listRowSeparator(.hidden) // 行間の線を消す
}
}
ボタンにだけ反応したいが行全体にイベントが持っていかれて、同じ行の他のボタンにまで反応してしまう
→ buttonStyle
を設定すれば良い
swift
Button {
..
}
.buttonStyle(.plain)
// .buttonStyle(.borderless)
SwiftData 使用時の並べ替え
swift
@Query(sort: \EventLocation.order) private var eventLocations: [EventLocation]
...
List {
ForEach(eventLocations) { eventLocation in
}
.onMove { src, dst in
moveItems(src, dst)
}
.onDelete { idxs in
deleteItems(idxs)
}
}
.environment(\.editMode, .constant(EditMode.active))
...
func moveItems(_ src: IndexSet, _ dst: Int) {
var items = eventLocations // copy
items.move(fromOffsets: src, toOffset: dst)
for (i, item) in items.enumerated() {
item.order = i
}
try? modelContext.save()
}
func deleteItems(_ idxs: IndexSet) {
}
削除ボタンについて
onDelete
や、swipeAction
の role: .destructive
だと表示上、即時消えてしまうので
swipeAction
で .tint(.red)
する
ただ、swipeAction
だと EditMode.active
設定すると反応しない
swift
@State private var isDeleteConfirmationDialogPresented: Bool = false
...
List {
ForEach(eventLocations) { eventLocation in
HStack {
...
}
}
.swipeActions(edge: .trailing, allowsFullSwipe: true) {
Button("Delete", role: .destructive) {
isDeleteConfirmationDialogPresented = true
}
}
}