考虑遵循简化的代码,用于可以拖动的元素,

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

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

我试着用相同的原始元素复制添加preview : {}onDrag,但它的大小仍然不准确,它有透明度.有没有一种方法来扩展预览(比如使用uikit),使其与原始元素完全相同?我相信预览元素的最大宽度在哪一点开始收缩也许?

enter image description here

推荐答案

您可以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视图.由于您使用的是原始视图本身进行预览,所以它的大小应该与原始视图相同.

Ios相关问答推荐

使用音频单元播放音频流,出现爆裂声

UIImage大小调整工作,但转换为上传数据时恢复到原始大小

如何删除NavigationView中的默认透明标头?

许多文本字段的性能问题

在 iOS 上启用明文本地流量在 .NET MAUI 中不起作用

尽管存在浮点错误,如何显示正确的计算结果.计算器应用程序

'DismissAction'类型的值没有成员'wrappedValue'在SwiftUI的Xcode中

带有属性包装器的不可用属性

AVPlayer 退出全屏

iOS 中的 [Class new] 和 [[Class alloc] init] 有什么区别?

iOS 11 navigationItem.titleView 宽度未设置

在 Swift 中将 HTML 转换为纯文本

UIView 和 initWithFrame 以及一个 NIB 文件.如何加载 NIB 文件?

如何使用 Contacts Framework 获取 iOS 9 中的所有联系人记录

以编程方式创建按钮并设置背景图像

如何在 UILabel 中找到文本子字符串的 CGRect?

如何使用完成按钮制作 UIPickerView?

UINavigationBar - 以编程方式设置标题?

如何使用 presentModalViewController 创建透明视图

打开 XIB 文件后 Xcode 6.3 冻结/挂起