您可以try 通过采用UIViewRepresentable
中的UIDragInteractionDelegate
来实现自定义拖动预览,以包装SwiftUI视图:通过使用UIDragPreview
并设置UIDragItem
的预览提供程序,您可以为预览指定一个与原始视图大小相同且不具有任何透明度的自定义视图.
+---------------------------------+
| +----+ +-------------------+ |
| |Icon| |Title | |
| +----+ +-------------------+ |
| | UIViewRepresentable wrapper |
| +-------------------------------+
| | UIDragInteractionDelegate |
+---------------------------------+
|
| Custom drag behavior
| (UIDragInteractionDelegate)
v
+----------------------------------+
| UIDragPreview (Custom preview) |
| Same size, no transparency |
+----------------------------------+
灵感来自Client/Frontend/TabChrome/TopBar/LocationView/LocationViewTouchHandler.swift
import SwiftUI
import UIKit
// Wrap your SwiftUI view in a UIViewRepresentable
struct DraggableView: UIViewRepresentable {
var text: String
func makeUIView(context: Context) -> UIView {
let view = UIHostingController(rootView: DraggableTextView(text: text)).view!
view.backgroundColor = .clear
let dragInteraction = UIDragInteraction(delegate: context.coordinator)
view.addInteraction(dragInteraction)
return view
}
func updateUIView(_ uiView: UIView, context: Context) {}
func makeCoordinator() -> Coordinator {
Coordinator()
}
class Coordinator: NSObject, UIDragInteractionDelegate {
func dragInteraction(_ interaction: UIDragInteraction, itemsForBeginning session: UIDragSession) -> [UIDragItem] {
let provider = NSItemProvider(object: "Dragged content" as NSString)
let item = UIDragItem(itemProvider: provider)
item.previewProvider = { return UIDragPreview(view: interaction.view!) }
return [item]
}
}
}
// Your original SwiftUI view
struct DraggableTextView: View {
var text: String
var body: some View {
HStack {
Image(systemName: "hand.point.up.left.fill") // Example icon
Text(text)
Spacer()
}
.padding(16)
.background(Color.gray) // For demo purposes
}
}
struct ContentView: View {
var body: some View {
DraggableView(text: "Draggable Text")
}
}
代码中的关键部分应该允许"相同大小,无透明度"的拖动预览是previewProvider
关闭UIDragItem
.
item.previewProvider = { return UIDragPreview(view: interaction.view!) }
UIDragPreview
初始化器被传递给interaction.view
,这是由UIHostingController
创建的UI视图,内部有SwiftUI视图.由于您使用的是原始视图本身进行预览,所以它的大小应该与原始视图相同.