我有一個 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..
uj5u.com熱心網友回復:
這涉及更多。它需要與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以獲得新的讀數。這有點脆弱,但這是做你想做的唯一方法。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/337920.html
