繁体   English   中英

如何修改拖放预览SwiftUI的背景颜色和形状?

[英]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())
    }
}

结果很好,但是当我开始拖动动作时,我看到我的单元格周围有一些白色矩形,这不是我想要的:

使用 ScrollView 拖放预览

第二种解决方案(使用 ScrollView)

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM