【问题标题】:How can I create text in SwiftUI with NavigationLink (only some words from text)如何使用 NavigationLink 在 SwiftUI 中创建文本(仅文本中的一些单词)
【发布时间】:2021-05-15 19:13:11
【问题描述】:

我正在开发适用于 iOS 的 SwiftUI 应用程序。 我想以这种方式格式化文本,其中蓝色单词应该是 NavigationLinks。文本的外观:

我知道在 SwiftUI 代码中实现 UIKit 是可能的。但是,我不明白如何通过正常工作的 NavigationLink 以这种方式使用 UIKit。

【问题讨论】:

  • 我不确定这是否可行。见here
  • 字符串是静态的吗?如果是这样,您可以创建多个文本视图,蓝色的将有一个 .onTapGesture。要使其动态化,需要更多的工作/思考

标签: swift swiftui swiftui-navigationlink


【解决方案1】:

使用this SO question 作为基础,这是一个解决方案。左对齐但一种方法。

import SwiftUI
struct DynamicLinkTextView: View {
    let text: String = "I want text like this, with NavigationLinks to another View. However, this doesn't work"
    let wordsWLinks: [String] = ["this", "View"]
    @State var selection: String?
    var textArray: [String]{
        text.components(separatedBy: " ")
    }
    var body: some View {
        NavigationView{
            VStack{
                MultilineHStack(textArray){ text in
                    VStack{
                        if wordsWLinks.contains(text.removePunctiation()){
                            NavigationLink(text + " ", destination: Text("link =  \(text)"), tag: text as String, selection: $selection)
                        }else{
                            Text(text + " ").fixedSize()
                        }
                    }
                }
            }
        }
    }
}
//https://stackoverflow.com/questions/57510093/swiftui-how-to-have-hstack-wrap-children-along-multiple-lines-like-a-collectio
public struct MultilineHStack: View {
    struct SizePreferenceKey: PreferenceKey {
        typealias Value = [CGSize]
        static var defaultValue: Value = []
        static func reduce(value: inout Value, nextValue: () -> Value) {
            value.append(contentsOf: nextValue())
        }
    }
    
    private let items: [AnyView]
    @State private var sizes: [CGSize] = []
    
    public init<Data: RandomAccessCollection,  Content: View>(_ data: Data, @ViewBuilder content: (Data.Element) -> Content) {
        self.items = data.map { AnyView(content($0)) }
    }
    
    public var body: some View {
        GeometryReader {geometry in
            ZStack(alignment: .topLeading) {
                ForEach(self.items.indices) { index in
                    self.items[index].background(self.backgroundView()).offset(self.getOffset(at: index, geometry: geometry))
                }
            }
        }.onPreferenceChange(SizePreferenceKey.self) {
            self.sizes = $0
        }
    }
    
    private func getOffset(at index: Int, geometry: GeometryProxy) -> CGSize {
        guard index < sizes.endIndex else {return .zero}
        let frame = sizes[index]
        var (x,y,maxHeight) = sizes[..<index].reduce((CGFloat.zero,CGFloat.zero,CGFloat.zero)) {
            var (x,y,maxHeight) = $0
            x += $1.width
            if x > geometry.size.width {
                x = $1.width
                y += maxHeight
                maxHeight = 0
            }
            maxHeight = max(maxHeight, $1.height)
            return (x,y,maxHeight)
        }
        if x + frame.width > geometry.size.width {
            x = 0
            y += maxHeight
        }
        return .init(width: x, height: y)
    }
    
    private func backgroundView() -> some View {
        GeometryReader { geometry in
            Rectangle()
                .fill(Color.clear)
                .preference(
                    key: SizePreferenceKey.self,
                    value: [geometry.frame(in: CoordinateSpace.global).size]
                )
        }
    }
}
struct DynamicLinkTextView_Previews: PreviewProvider {
    static var previews: some View {
        DynamicLinkTextView()
    }
}
extension String{
    func removePunctiation() -> String {
        self.trimmingCharacters(in: CharacterSet(charactersIn: ",."))
    }
}

【讨论】:

  • 谢谢!真的很有帮助!现在我遇到了一个问题,因为当我在 VStack 中嵌入这样的视图时,SwiftUI 确定这个视图的高度是一行(当它实际上是多行文本时。但我确定我会解决这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-28
  • 1970-01-01
  • 1970-01-01
  • 2022-11-27
  • 2021-02-26
相关资源
最近更新 更多