如何保持拖动预览与原始项目完全相同?

问题描述 投票:0回答:1

考虑使用以下可拖动元素的简化代码

    HStack {
      Icon(icon: .iconDrag)
      Text("Title")
      Spacer()
    }
    .padding(16)
    .onDrag {
      return NSItemProvider(object: id.uuidString as NSString)
    }

这会导致下面的行为,一旦开始拖动,就会显示预览元素,但它只是原始元素大小的一小部分并且具有透明度。

我尝试将

preview : {}
添加到具有相同原始元素副本的
onDrag
中,但它的大小仍然不准确并且具有透明度。有没有办法以某种方式扩展预览(例如使用 uikit),使其与原始元素完全相同?我相信预览元素有最大宽度,此时它可能开始缩小?

ios swift swiftui drag-and-drop
1个回答
0
投票

您可以尝试通过在包装 SwiftUI 视图的

UIDragInteractionDelegate
中采用
UIViewRepresentable
来实现自定义拖动预览:通过使用
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
创建的 UIView,其中包含 SwiftUI 视图。由于您使用原始视图本身进行预览,因此它的大小应与原始视图相同。

© www.soinside.com 2019 - 2024. All rights reserved.