我有一个水平 ScrollView ,其中有一个 HStack。它包含多个 subview ,由 ForEach 呈现。我想让它在点击这些 subview 时,它们在 View 中垂直居中。例如,我有:
ScrollView(.horizontal) {
HStack(alignment: .center) {
Circle() // for demonstration purposes, let's say the subviews are circles
.frame(width: 50, height: 50)
Circle()
.frame(width: 50, height: 50)
Circle()
.frame(width: 50, height: 50)
}
.frame(width: UIScreen.main.bounds.size.width, alignment: .center)
}
我试过这段代码:
ScrollViewReader { scrollProxy in
ScrollView(.horizontal) {
HStack(alignment: .center) {
Circle()
.frame(width: 50, height: 50)
.id("someID3")
.frame(width: 50, height: 50)
.onTapGesture {
scrollProxy.scrollTo(item.id, anchor: .center)
}
Circle()
.frame(width: 50, height: 50)
.id("someID3")
.frame(width: 50, height: 50)
.onTapGesture {
scrollProxy.scrollTo(item.id, anchor: .center)
}
...
}
}
但是貌似没有效果。有谁知道我该如何正确地做到这一点?
最佳答案
您绝对可以使用 ScrollView
和 ScrollViewReader
来做到这一点。但是,我发现有几件事可能会导致您的代码示例出现问题:
- 您使用相同的 ID
"someID3"
两次。 - 我看不到你的
item.id
来自哪里,所以我无法判断它是否真的包含相同的 ID ("someID3"
)。 - 我不知道为什么在同一个 View 区域有两个具有相同边界的框架。这应该不是问题,但最好始终保持简单。
这是一个工作示例:
import SwiftUI
@main
struct MentalHealthLoggerApp: App {
var body: some Scene {
WindowGroup {
ScrollViewReader { scrollProxy in
ScrollView(.horizontal) {
HStack(alignment: .center, spacing: 10) {
Color.clear
.frame(width: (UIScreen.main.bounds.size.width - 70) / 2.0)
ForEach(Array(0..<10), id: \.self) { id in
ZStack(alignment: .center) {
Circle()
.foregroundColor(.primary.opacity(Double(id)/10.0))
Text("\(id)")
}
.frame(width: 50, height: 50)
.onTapGesture {
withAnimation {
scrollProxy.scrollTo(id, anchor: .center)
}
}
.id(id)
}
Color.clear
.frame(width: (UIScreen.main.bounds.size.width - 70) / 2.0)
}
}
}
}
}
}
在这里您可以看到它的实际效果:
[编辑:如果 GIF 无法自动播放,您可能需要点击它。]
请注意,我在 ScrollView
的两端添加了一些空白空间,因此实际上可以将第一个和最后一个元素居中,因为 ScrollViewProxy
永远不会滚动超出限制。
关于SwiftUI - 如何在点击时使组件在水平 ScrollView 中居中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71652543/