swift - SwiftUi如何防止文本自动截断以适应
问题描述
我有一个包含多个项目的 hstack,当第一个文本太长时,它会被截断,并且行中的其他元素也会被截断,因此元素仍在 hstack 中,但对齐方式很奇怪,我发布了问题的屏幕截图以及我想要达到的目标。如果用户名太长并且不适合它,我需要它应该与其他元素换行。
[![这就是现在发生的事情][1]][1]
[![这就是我需要的][2]][2]
HStack {
Text("longtext username test")
// Block 1
Text(Image(systemName: "network")) +
Text("12345")
// Block 2
Text(Image(systemName: "network")) +
Text("2.0K")
// Block 3
Text(Image(systemName: "network")) +
Text("2H")
// Block 4
Text(Image(systemName: "network"))
Text(Image(systemName: "network"))
Text(Image(systemName: "network"))
}
[1]: https://i.stack.imgur.com/Bj1Cb.png
[2]: https://i.stack.imgur.com/wITRf.png
// if the username is short and fit in the line
// Place all items in the same line
short-username text2 text3 text4..
// If the username is too long and doesn't fit
// Make a new line with all the other elements
long-username
text2 text3 test4..
解决方案
这涉及更多一点。它需要与PreferenceKeys
. 这段代码可能会被缩短,但它可以工作......
struct InlineTextView: View {
@State var userName = "longtext username test"
@State var userNamePref: CGFloat = 0
@State var additionalTextPref: CGFloat = 0
@State var hStackPref: CGFloat = 0
@State var totalWidth: CGFloat = 0
@State var isTooWide: Bool = true
var body: some View {
GeometryReader {outerGeometry in
VStack(alignment: .leading, spacing: 20) {
Group {
if isTooWide {
Text(userName)
.background(GeometryReader { userGeometry in
Color.clear.preference(
key: UsernameWidthPreferenceKey.self,
value: userGeometry.size.width)
})
additionalInlineText
.onTapGesture {
print("tapped")
}
.background(GeometryReader { addGeometry in
Color.clear.preference(
key: AdditionalWidthPreferenceKey.self,
value: addGeometry.size.width)
})
} else {
HStack {
Text(userName)
.background(GeometryReader { geometry in
Color.clear.preference(
key: UsernameWidthPreferenceKey.self,
value: geometry.size.width)
})
additionalInlineTextView
.background(GeometryReader { geometry in
Color.clear.preference(
key: AdditionalWidthPreferenceKey.self,
value: geometry.size.width)
})
}
}
}
.onPreferenceChange(UsernameWidthPreferenceKey.self) {
userNamePref = max($0, userNamePref)
totalWidth = userNamePref + additionalTextPref
isTooWide = totalWidth > outerGeometry.size.width
print("userNamePref = \(userNamePref)")
print("additionalTextPref = \(additionalTextPref)")
print("hStackPref = \(hStackPref)")
print("totalWidth = \(totalWidth)")
print("outerGeo = \(outerGeometry.size.width)")
}
.onPreferenceChange(AdditionalWidthPreferenceKey.self) {
additionalTextPref = max($0, additionalTextPref)
totalWidth = userNamePref + additionalTextPref
isTooWide = totalWidth > outerGeometry.size.width
print("userNamePref = \(userNamePref)")
print("additionalTextPref = \(additionalTextPref)")
print("hStackPref = \(hStackPref)")
print("totalWidth = \(totalWidth)")
print("outerGeo = \(outerGeometry.size.width)")
}
Button {
if userName == "longtext username test" {
userNamePref = 0
userName = "userName"
} else {
userNamePref = 0
userName = "longtext username test"
}
} label: {
Text("Change name.")
}
}
}
}
var additionalInlineText: Text {
// Block 1
Text(Image(systemName: "network")) +
Text("12345") +
// Block 2
Text(Image(systemName: "network")) +
Text("2.0K") +
// Block 3
Text(Image(systemName: "network")) +
Text("2H") +
// Block 4
Text(Image(systemName: "network")) +
Text(Image(systemName: "network")) +
Text(Image(systemName: "network")) +
Text("1234")
}
}
private extension InlineTextView {
struct UsernameWidthPreferenceKey: PreferenceKey {
static let defaultValue: CGFloat = 0
static func reduce(value: inout CGFloat,
nextValue: () -> CGFloat) {
value = max(value, nextValue())
}
}
struct AdditionalWidthPreferenceKey: PreferenceKey {
static let defaultValue: CGFloat = 0
static func reduce(value: inout CGFloat,
nextValue: () -> CGFloat) {
value = max(value, nextValue())
}
}
}
编辑:使 AdditionalInlineText 可点击并更改名称以明确它是文本。
是的,GeometryReader
确定屏幕的宽度,而首选项键确定视图的宽度。我开始他们,VStack
所以他们读他们的最大宽度。如果您注意到何时userName
更改,我会重置userNamePref
以获取新读数。这有点脆弱,但它是做你想做的事情的唯一方法。
推荐阅读
- ios - 为什么我在快速向上移动键盘时视图和滚动视图之间出现差距?
- c# - NavigationView 不会在启用/需要页面缓存的情况下切换
- php - 如何从 mapbox 中的 php 文件中获取多个实时数据标记?
- angular - 如何在不更改默认超时的情况下向 browser.wait() 添加消息?
- javascript - ES6:根据另一个数组顺序对数组进行排序
- javascript - 使用 Leaflet.PolylineDecorator 我得到未定义的读取属性“破折号”
- java - 黄瓜junit中的标签继承
- visual-studio-code - VS Code:您可以为“猜测编码”设置允许的编码吗?
- python - 在为包创建“别名”时使导入工作
- crystal-reports - 水晶报表休息空间