制作指针,在字符串上读取字符串 - SwiftUI

Making Pointer that reads string while over it - SwiftUI

提问人:Yousif Ismat 提问时间:9/15/2023 最后编辑:Yousif Ismat 更新时间:9/15/2023 访问量:52

问:

我想在 SwiftUI 中实现以下行为,但我不知道如何操作:

想象一下,有一个包含字符串(或属性字符串)的文本,你还有一个指针,可以像鼠标图标(或任何图标)一样悬停在字符串的字母上,当指针放在一个字母上时,该字母会突出显示(即颜色不同)。

我不想要的: 我不希望您使用不同的文本并使用 HStack 和 Foreach 将它们相加,我希望它们在一起,因为我希望它适用于所有语言,并且提到的方法仅适用于仅具有不连接字母的语言。

可能吗?

swift 字符串 xcode swiftUI 属性字符串

评论

0赞 Sweeper 9/15/2023
“当指针在字母上时”它是如何做到的?指针是由用户控制(通过拖动?)还是其他方式?
0赞 Yousif Ismat 9/15/2023
拖动就可以了,或者在文本上方有一个固定的指针,当你滚动文本并且指针碰到一个字母时,它会被突出显示?
0赞 Community 9/16/2023
请编辑问题,将其限制在特定问题上,并具有足够的细节以确定适当的答案。
0赞 Yousif Ismat 9/16/2023
我相信很清楚,是什么让你不清楚你是否可以告诉我修复?

答:

0赞 KerryDong 9/15/2023 #1

是的,使用 NSAttributedString,NSTextAttachment 可以满足您的需求。

我把它封装在:HighlightWithCursorLabel

struct HighlightWithCursorLabel: UIViewRepresentable {
    var originText: String
    var color: UIColor
    @Binding var highlightIndex: Int
    
    var configuration = { (view: UILabel) in }
                
    init(originText: String, color: UIColor, highlightIndex: Binding<Int>, configuration: @escaping (UILabel) -> () = { _ in }) {
        self.originText = originText
        self.color = color
        self._highlightIndex = highlightIndex
        self.configuration = configuration
    }
    
    func makeUIView(context: Context) -> UILabel {
        let label = UILabel()
        label.text = originText
        label.textColor = UIColor(Colors.subText)
        return label
    }

    func updateUIView(_ uiView: UILabel, context: Context) {
        configuration(uiView)
        
        if highlightIndex > originText.count { return }
        
        let attributString = NSMutableAttributedString(string: originText)
        
        let nsRange = NSRange(location: 0, length: highlightIndex)
        let attribute = [NSAttributedString.Key.foregroundColor: color]
        attributString.addAttributes(attribute, range: nsRange)

        let attachment = NSTextAttachment(image: UIImage(systemName: "cursorarrow")!.withTintColor(color)) // replace it to any UIImage
        let attachmentString = NSAttributedString(attachment: attachment)

        attributString.insert(attachmentString, at: highlightIndex)
        uiView.attributedText = attributString
    }
}

用法

struct HighlightSampleView: View {
    @State private var highlightIndex: Int = 0
    private var text = "Hello World~~~~~"
    
    var body: some View {
        HighlightWithCursorLabel(originText: text, color: UIColor(red: 0/255, green: 122/255, blue: 255/255, alpha: 1.0), highlightIndex: $highlightIndex)
            .onAppear {
                highlightText()
            }
    }
    
    // To show the highlight effect, replace it when you want to update index
    private func highlightText() {
        Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { timer in
            highlightIndex += 1
            
            if highlightIndex > text.count {
                timer.invalidate()
            }
        }
    }
}

struct HighlightSampleView_Previews: PreviewProvider {
    static var previews: some View {
        HighlightSampleView()
    }
}

结果

enter image description here enter image description here

评论

0赞 Yousif Ismat 9/16/2023
感谢您的帮助,但问题是光标不是作为单独的实体在文本上,而是嵌入在属性字符串中,这会产生我不想要的将文本向左推的效果。你能让它悬停在上面而不干扰文本,除了突出显示吗?
0赞 KerryDong 9/16/2023
如果您只想允许用户将鼠标悬停在文本上并突出显示它,您可以考虑使用具有选择/突出显示文本功能的本机。然后,您可以添加一个并根据用户的点击和拖动不断更新其位置。如果要进一步自定义文本的突出显示颜色,可以尝试使用 、convert(_:from:)glyphIndex(for:in:)。UITextViewUIImageViewNSAttributedString