ios - 用点填充文本行中的剩余空白(多行文本)iOS

标签 ios swiftui uikit uilabel

我想用虚线填充最后一行剩余的空白。它应该从最后一个单词的末尾开始,一直持续到该行的末尾。这可以用 SwiftUI 甚至 UIKit 实现吗?

我有:

what I have

我需要什么:

what I need

struct ContentView: View {
    var body: some View {
        let fontSize = UIFont.preferredFont(forTextStyle: .headline).lineHeight
        let text = "stackoverflow stackoverflow stackoverflow stackoverflow stackoverflow stackoverflow stackoverflow stackoverflow"
        
        HStack(alignment: .lastTextBaseline, spacing: .zero) {
            HStack(alignment: .top, spacing: .zero) {
                Circle()
                    .foregroundColor(.green)
                    .frame(width: 6, height: 6)
                    .frame(height: fontSize, alignment: .center)
                ZStack(alignment: .bottom) {
                    HStack(alignment: .lastTextBaseline, spacing: .zero) {
                        Text("")
                            .font(.headline)
                            .padding(.leading, 5)
                        Spacer(minLength: 10)
                            .overlay(Line(), alignment: .bottom)
                    }
                    HStack(alignment: .lastTextBaseline, spacing: .zero) {
                        Text(text)
                            .font(.headline)
                            .padding(.leading, 5)
                        Spacer(minLength: 10)
                    }
                }
            }
        }
    }
}

struct Line: View {

    var width: CGFloat = 1

    var color = Color.gray

    var body: some View {
        LineShape(width: width)
            .stroke(style: StrokeStyle(lineWidth: 3, dash: [3]))
            .foregroundColor(color)
            .frame(height: width)
    }
}

private struct LineShape: Shape {

    var width: CGFloat

    func path(in rect: CGRect) -> Path {
        var path = Path()
        path.move(to: CGPoint())
        path.addLine(to: CGPoint(x: rect.width, y: .zero))
        return path

    }
}

最佳答案

这是我的有点老套但更简单的解决方案:向文本添加白色突出显示,以便它覆盖虚线。

我们可以使用 NSAttributedString 添加突出显示。 SwiftUI 默认不支持这个,所以我们需要使用 UIViewRepresentable 。就是这样,基于 this answer :

struct HighlightedText: View {
    var text: String
    @State private var height: CGFloat = .zero
    private var fontStyle: UIFont.TextStyle = .body
    
    init(_ text: String) { self.text = text }

    var body: some View {
        InternalHighlightedText(text: text, dynamicHeight: $height, fontStyle: fontStyle)
            .frame(minHeight: height) /// allow text wrapping
            .fixedSize(horizontal: false, vertical: true) /// preserve the Text sizing
    }

    struct InternalHighlightedText: UIViewRepresentable {
        var text: String
        @Binding var dynamicHeight: CGFloat
        var fontStyle: UIFont.TextStyle

        func makeUIView(context: Context) -> UILabel {
            let label = UILabel()
            label.numberOfLines = 0
            label.lineBreakMode = .byWordWrapping
            label.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
            label.font = UIFont.preferredFont(forTextStyle: fontStyle)
            return label
        }

        func updateUIView(_ uiView: UILabel, context: Context) {
            let attributedText = NSAttributedString(string: text, attributes: [.backgroundColor: UIColor.systemBackground])
            uiView.attributedText = attributedText /// set white background color here
            uiView.font = UIFont.preferredFont(forTextStyle: fontStyle)

            DispatchQueue.main.async {
                dynamicHeight = uiView.sizeThatFits(CGSize(width: uiView.bounds.width, height: CGFloat.greatestFiniteMagnitude)).height
            }
        }
    }
    
    /// enable .font modifier
    func font(_ fontStyle: UIFont.TextStyle) -> HighlightedText {
        var view = self
        view.fontStyle = fontStyle
        return view
    }
}

然后,只需替换 Text(text)HighlightedText(text) .

struct ContentView: View {
    var body: some View {
        let fontSize = UIFont.preferredFont(forTextStyle: .headline).lineHeight
        let text = "stackoverflow stackoverflow stackoverflow stackoverflow stackoverflow stackoverflow stackoverflow stackoverflow"
        
        HStack(alignment: .lastTextBaseline, spacing: .zero) {
            HStack(alignment: .top, spacing: .zero) {
                Circle()
                    .foregroundColor(.green)
                    .frame(width: 6, height: 6)
                    .frame(height: fontSize, alignment: .center)
                ZStack(alignment: .bottom) {
                    HStack(alignment: .lastTextBaseline, spacing: .zero) {
                        Text("")
                            .font(.headline)
                            .padding(.leading, 5)
                        Spacer(minLength: 10)
                            .overlay(Line(), alignment: .bottom)
                    }
                    HStack(alignment: .lastTextBaseline, spacing: .zero) {
                        HighlightedText(text) /// here!
                            .font(.headline)
                            .padding(.leading, 5)
                        Spacer(minLength: 10)
                    }
                }
            }
        }
    }
}

struct Line: View {

    var width: CGFloat = 1
    var color = Color.gray
    var body: some View {
        LineShape(width: width)
            .stroke(style: StrokeStyle(lineWidth: 3, dash: [3]))
            .foregroundColor(color)
            .frame(height: width)
    }
}

private struct LineShape: Shape {

    var width: CGFloat
    func path(in rect: CGRect) -> Path {
        var path = Path()
        path.move(to: CGPoint())
        path.addLine(to: CGPoint(x: rect.width, y: .zero))
        return path

    }
}
<表类=“s-表”> <标题> 之前 之后 <正文> Dots at overlapping last line of text Dots stopping at last line of text

关于ios - 用点填充文本行中的剩余空白(多行文本)iOS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67195588/

相关文章:

iphone - NSDate 没有返回正确的日期

ios - 不使用 Storyboard创建 iMessage 应用程序

ios - 如何在 Swift 中使用 firstIndex 查找所有结果

ios - 自定义弹出对话框

iOS App(使用核心数据)更新后崩溃,但只有 App Store 版本

ios - 关于如何记录 Websocket API 的建议

ios - UIView 动画在动画期间确定中心

MacOS 上的 SwiftUI : Call a function when NavigationLink Clicked

swiftui - 在SwiftUI中实现标签列表

ios - UIButton:在文本下方以 x pts 间距画一条线?