一个纯 SwiftUI 结构组件,可以轻松实现拖放重新排序操作。它支持基于 DragGesture
的与其元素进行快速交互,而不是像 .onDrag
/.draggable
那样基于“长按”的交互。这是它在即将推出的 Vis iOS 应用中的实际应用示例。
此软件包包含 ReorderableVStack
和 ReorderableHStack
。
.dragHandle()
修饰符指定您自己的拖动手柄.dragDisabled(_ dragDisabled: Bool)
修饰符禁用/启用拖动,该修饰符与动画配合良好(而不是添加/删除 .onDrag()
修饰符)content
视图构建器的 isDragged
参数,轻松自定义您的拖动状态。此框架以 Swift 包 的形式分发。要使用,请将以下 URL 添加到您的软件包列表
https://github.com/visfitness/reorderable
要将此包添加到您的 XCode 项目,请按照这些说明。
该软件包的文档可以在这里找到
注意
以下所有示例都使用以下 struct
作为其数据
private struct Sample: Identifiable {
var color: UIColor
var id: UUID = UUID()
var height: CGFloat
init(_ color: UIColor, _ height: CGFloat) {
self.color = color
self.height = height
}
}
struct SimpleExample: View {
@State var data = [
Sample(UIColor.systemBlue, 200),
Sample(UIColor.systemGreen, 100),
Sample(UIColor.systemGray, 300)
]
var body: some View {
ReorderableVStack($data) { $sample in
RoundedRectangle(cornerRadius: 32, style: .continuous)
.fill(Color(sample.color))
.frame(height: sample.height)
.padding()
}
.padding()
}
}
struct SimpleExample: View {
@State var data = [
Sample(UIColor.systemBlue, 200),
Sample(UIColor.systemGreen, 100),
Sample(UIColor.systemGray, 300)
]
var body: some View {
ReorderableVStack(data, onMove: { from, to in
withAnimation {
data.move(fromOffsets: IndexSet(integer: from),
toOffset: (to > from) ? to + 1 : to)
}
}) { sample in
RoundedRectangle(cornerRadius: 32, style: .continuous)
.fill(Color(sample.color))
.frame(height: sample.height)
.padding()
}
.padding()
}
}
struct SimpleExample: View {
@State var data = [
Sample(UIColor.systemBlue, 200),
Sample(UIColor.systemGreen, 100),
Sample(UIColor.systemGray, 300)
]
var body: some View {
ReorderableVStack($data) { $sample, isDragged in // <------ Notice the additional `isDragged` parameter
ZStack(alignment: .leading) {
RoundedRectangle(cornerRadius: 32, style: .continuous)
.fill(Color(sample.color))
.frame(height: sample.height)
Image(systemName: "line.3.horizontal")
.foregroundStyle(.secondary)
.padding()
.offset(x: 16)
// This will now be the only place users can drag the view from
.dragHandle() // <------------
}
.scaleEffect(isDragged ? 1.1: 1)
.animation(.easeOut, value: isDragged)
.padding()
}.padding()
}
}
警告
由于此软件包不依赖于 SwiftUI 的原生 onDrag
,因此当用户将元素拖动到父/祖先 ScrollView
的边缘时,它也不会自动触发自动滚动。要启用此行为,需要将 autoScrollOnEdges()
修饰符应用于 ScrollView
。
struct SimpleExample: View {
@State var data = [
Sample(UIColor.systemBlue, 200),
Sample(UIColor.systemGreen, 200),
Sample(UIColor.systemGray, 300),
Sample(UIColor.systemMint, 200),
Sample(UIColor.systemPurple, 300),
Sample(UIColor.orange, 200)
]
var body: some View {
ScrollView {
ReorderableVStack($data) { $sample in
RoundedRectangle(cornerRadius: 32, style: .continuous)
.fill(Color(sample.color))
.frame(height: sample.height)
.padding()
}.padding()
}.autoScrollOnEdges() // <------- This modifier enables the autoscrolling
}
}
private struct Sample2D: Identifiable {
var id: UUID = UUID()
var row: [Sample]
}
struct SimpleExample: View {
@State var data: [Sample2D] = [
.init(row: [.init(UIColor.systemBlue, 200), .init(UIColor.systemGreen, 100), .init(UIColor.systemGray, 200)]),
.init(row: [.init(UIColor.systemRed, 200), .init(UIColor.systemMint, 100), .init(UIColor.systemPurple, 200)]),
.init(row: [.init(UIColor.systemIndigo, 200), .init(UIColor.systemTeal, 100), .init(UIColor.systemYellow, 200)]),
]
var body: some View {
ReorderableVStack($data) { $sample in
HStack {
ZStack {
RoundedRectangle(cornerRadius: 24, style: .continuous)
.fill(Color(UIColor.systemOrange))
.frame(width: 64, height: 64)
.padding()
Image(systemName: "line.3.horizontal")
.foregroundStyle(.secondary)
.padding()
}
.dragHandle()
ReorderableHStack($sample.row) { $sample in
RoundedRectangle(cornerRadius: 24, style: .continuous)
.fill(Color(sample.color))
.frame(width: 64, height: 64)
.padding()
}
}
}
}
}
版权所有 Vis Fitness Inc。在 MIT 许可证 下获得许可