我想用虚线填充最后一行剩余的空白。它应该从最后一个单词的末尾开始,一直持续到该行的末尾。这可以用 SwiftUI 甚至 UIKit 实现吗?
我有:
我需要什么:
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
}
}
关于ios - 用点填充文本行中的剩余空白(多行文本)iOS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67195588/