拖动一个TextView在SwiftUI中使用onDrag修饰符会拖动整个集合。

huangapple go评论59阅读模式
英文:

dragging on one TextView drags entire collection in SwiftUI with onDrag modifier

问题

I'll provide the translation of the code you provided, excluding the code comments:

import SwiftUI

struct EmojiArtDocumentView: View {
    @ObservedObject var document: EmojiArtDocument
    let defaultmojiFontSize: CGFloat = 40
    var body: some View {
        VStack(spacing: 0) {
            documentBody
            palette
        }
        .padding()
    }
    
    var documentBody: some View {
        GeometryReader { geometry in
            ZStack {
                Color.yellow
                ForEach(document.emojis) { emoji in
                    Text(emoji.text)
                        .font(.system(size: fontSize(for: emoji)))
                        .position(position(for: emoji, in: geometry))
                }
            }
        }
    }
    
    private func drop(providers: [NSItemProvider], at location: CGPoint) -> Bool {
        false
    }
    
    private func fontSize(for emoji: EmojiArt.Emoji) -> CGFloat {
        CGFloat(emoji.size)
    }
    
    private func position(for emoji: EmojiArt.Emoji, in geometry: GeometryProxy) -> CGPoint {
        convertFromEmojiCoordinates((emoji.x, emoji.y), in: geometry)
    }
    
    private func convertFromEmojiCoordinates(_ location: (x: Int, y: Int), in geometry: GeometryProxy) -> CGPoint {
        let center = geometry.frame(in: .local).center
        return CGPoint(
            x: center.x + CGFloat(location.x),
            y: center.y + CGFloat(location.y)
        )
    }
    
    var palette: some View {
        ScrollingEmojisView(emojis: testemojis)
            .font(.system(size: defaultmojiFontSize))
    }
    
    let testemojis = "😀🥰😌😇🤓🤩🤪😤👻"
}

struct ScrollingEmojisView: View {
    let emojis: String
    
    var body: some View {
        ScrollView(.horizontal) {
            HStack {
                ForEach(emojis.map {String($0) }, id: \.self) { emoji in
                    Text(emoji)
                        .onDrag {
                            NSItemProvider(object: emoji as NSString)
                        }
                }
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        EmojiArtDocumentView(document: EmojiArtDocument())
    }
}

extension CGRect {
    var center: CGPoint {
        CGPoint(x: midX, y: midY)
    }
}

Please note that the code you provided includes some HTML escape sequences (e.g., > and ") that need to be decoded when used in Swift. If you encounter issues, make sure to decode these properly in your code.

英文:

I'm trying to work through the EmojiArt app on Stanford 193p 2021, if that reference helps. Otherwise, as the title says, I'm trying to add an onDrag modifier on each of the emoji chars, but it appears as if when I drag on one, the entire string of emoji chars gets dragged. how to fix this?

import SwiftUI
struct EmojiArtDocumentView: View {
@ObservedObject var document: EmojiArtDocument
let defaultmojiFontSize: CGFloat = 40
var body: some View {
VStack(spacing: 0) {
documentBody
palette
}
.padding()
}
var documentBody: some View {
GeometryReader { geometry in
ZStack {
Color.yellow
ForEach(document.emojis) { emoji in
Text(emoji.text)
.font(.system(size: fontSize(for: emoji)))
.position(position(for: emoji, in: geometry))
}
}
}
//        .onDrop(of: [.plainText], isTargeted: nil) {
//            providers, location in
//            return false
//        }
}
private func drop(providers: [NSItemProvider], at location: CGPoint) -> Bool {
false
}
private func fontSize(for emoji: EmojiArt.Emoji) -> CGFloat {
CGFloat(emoji.size)
}
private func position(for emoji: EmojiArt.Emoji, in geometry: GeometryProxy) -> CGPoint {
convertFromEmojiCoordinates((emoji.x, emoji.y), in: geometry)
}
private func convertFromEmojiCoordinates(_ location: (x: Int, y: Int), in geometry: GeometryProxy) -> CGPoint {
let center = geometry.frame(in: .local).center
return CGPoint(
x: center.x + CGFloat(location.x),
y: center.y + CGFloat(location.y)
)
}
var palette: some View {
ScrollingEmojisView(emojis: testemojis)
.font(.system(size: defaultmojiFontSize))
}
let testemojis = "😀🥰😌😇🤓🤩🤪😤👻"
}
struct ScrollingEmojisView: View {
let emojis: String
var body: some View {
ScrollView(.horizontal) {
HStack {
ForEach(emojis.map {String($0) }, id: \.self) { emoji in
Text(emoji)
.onDrag {
NSItemProvider(object: emoji as NSString)
}
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
EmojiArtDocumentView(document: EmojiArtDocument())
}
}
extension CGRect {
var center: CGPoint {
CGPoint(x: midX, y: midY)
}
}

答案1

得分: 1

你可以尝试插入 ZStack 并修改 documentBody 属性中的 ForEach,如下所示:

ForEach(document.emojis) { emoji in
ZStack {
Text(emoji.text)
.font(.system(size: fontSize(for: emoji)))
}
.position(position(for: emoji, in: geometry))
.gesture(
DragGesture()
.onChanged { dragValue in
document.moveEmoji(emoji, by: dragValue.translation, in: geometry)
}
)
}

这样,每个 ZStack 将被识别为一个可拖动的单独视图,您将能够拖动单个表情符号字符。

英文:

You can try to insert ZStack and modify ForEach of the documentBody property as below:

ForEach(document.emojis) { emoji in
ZStack {
Text(emoji.text)
.font(.system(size: fontSize(for: emoji)))
}
.position(position(for: emoji, in: geometry))
.gesture(
DragGesture()
.onChanged { dragValue in
document.moveEmoji(emoji, by: dragValue.translation, in: geometry)
}
)
}

This way, each ZStack will be recognized as a separate draggable view, and you will be able to drag individual emoji characters.

huangapple
  • 本文由 发表于 2023年4月20日 10:44:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/76060143.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定