![](/img/trans.png)
[英]How to get the position of the touch when in UITableView Drag&Drop
[英]How do I modify the background color and shape of drag&drop preview SwiftUI?
我正在尝试使用可拖动单元格(iOS 15)实现简单列表。 目前我有两个基本解决方案:List 和 ScrollView。 这些方法都不会导致我得到适当的结果。
首先,我将提供一些代码:
struct ListItemView: View {
let index: Int
var body: some View {
HStack {
Text("Item \(index)")
.foregroundColor(.white)
Spacer()
}
.padding()
.background(Color.gray)
.clipShape(RoundedRectangle(cornerRadius: 16.0))
}
}
struct ContentView: View {
var body: some View {
List(0 ..< 10) { i in
ListItemView(index: i)
.onDrag {
NSItemProvider(object: String(describing: "item_\(i)") as NSString)
}
.padding(.bottom, 8.0)
.listRowBackground(Color.clear)
.listRowSeparator(.hidden)
.listRowInsets(EdgeInsets(top: 0, leading: 8, bottom: 0, trailing: 8))
}
.background(Color.black)
.listStyle(PlainListStyle())
}
}
结果很好,但是当我开始拖动动作时,我看到我的单元格周围有一些白色矩形,这不是我想要的:
struct ContentView: View {
var body: some View {
ScrollView {
ForEach(0 ..< 10) { i in
ListItemView(index: i)
.onDrag {
NSItemProvider(object: String(describing: "item_\(i)") as NSString)
}
}
}
.background(Color.black)
}
}
结果有点不同:我们看不到任何彩色矩形(我想,这是因为我们没有使用 List 并且拖放功能的机制不同)。 还有没有圆角的缩放预览和形状。
因此,理想的行为是:a)预览的大小与列表项的原始大小相同 b)没有白框的圆角形状
我怎样才能实现它?
从理论上讲,您的NSItemProvider
可以提供一个previewImageHandler
,它是一个绘制您希望系统用作拖动预览的图像的块。 不幸的是,这似乎不起作用。 onDrag
修饰符的文档说它使用视图的图片作为预览图像,它似乎忽略了previewImageHandler
。 如果有人发现其他情况,请发表评论,我会修改答案。 这是我尝试过的:
import SwiftUI
struct ListItem : Identifiable {
let id: Int
let title: String
}
let itemsInList = (0..<10).map { ListItem(id: $0, title: "Item \($0)") }
@ViewBuilder func ListItemView(title : String) -> some View {
ZStack(alignment: .leading) {
RoundedRectangle(cornerRadius: 18, style: .circular)
.foregroundColor(Color(red: 142.0/255.0, green: 142.0/255.0, blue: 142.0/255.0, opacity: 1.0))
Text(title)
.foregroundColor(.white)
.padding()
}
}
struct ContentView: View {
var body: some View {
List(itemsInList) {
let itemTitle = $0.title
ListItemView(title: itemTitle)
.onDrag {
let itemProvider = NSItemProvider()
itemProvider.registerObject("Item \(itemTitle)" as NSString, visibility: .all)
itemProvider.previewImageHandler = {
(completionHandler, expectedClass, options) -> Void in
var resultImage : CGImage?
debugPrint(expectedClass ?? "Unknown")
if let cgContext = CGContext(data: nil,
width: 72,
height: 72,
bitsPerComponent: 8,
bytesPerRow: 16 * (((72 * 4) + 15) / 16),
space: CGColorSpace(name: CGColorSpace.sRGB)!,
bitmapInfo: CGImageAlphaInfo.premultipliedFirst.rawValue) {
let frame = CGRect(x: 0, y: 0, width: 72, height: 72)
cgContext.clear(frame)
cgContext.setFillColor(UIColor.red.cgColor)
cgContext.fillEllipse(in: frame)
resultImage = cgContext.makeImage()
}
if let completionHandler = completionHandler {
if let resultImage = resultImage {
completionHandler(UIImage(cgImage: resultImage), nil)
} else {
completionHandler(nil, NSError(domain: "ItemCompletion", code: -1, userInfo: nil))
}
}
}
return itemProvider
}
}
}
}
struct previews : PreviewProvider {
static var previews: some View {
ContentView()
}
}
我有(现在有)和你描述的一样的问题。 拖动时,我的项目的角不再是圆形的,并且一般项目被切断(好像我会在它们上调用clipped()
)。 在iOS 15之前,我的解决方法是删除预览:
.onDrag({
current = item
return NSItemProvider(object: "\(item.id)" as NSString)
}, preview: {
Text(" ") // replace eventually ...
})
此处的空文本视图比EmptyView()
效果更好,因为它完全删除了任何预览(而不是小指示器)。
但是,对于iOS 16 ,此解决方案不再起作用(他们添加了一些初始拖动动画),甚至显示警告( CLIENT APP ERROR - Neither the view or container of the UITargetedPreview is currently in a window. This is in violation of UIDragInteraction API contract and can cause a severe visual glich. THIS IS A CLIENT APP BUG and will soon be a hard assert. PLEASE FIX ME
)。
因此,您找到任何解决方案了吗?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.