SwiftUI - 如何在点击时使组件在水平 ScrollView 中居中?

标签 swift swiftui scrollview hstack

我有一个水平 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)
                }

            ...
        }
    }

但是貌似没有效果。有谁知道我该如何正确地做到这一点?

最佳答案

您绝对可以使用 ScrollViewScrollViewReader 来做到这一点。但是,我发现有几件事可能会导致您的代码示例出现问题:

  • 您使用相同的 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 无法自动播放,您可能需要点击它。]

You can see the animated scrolling effect.

请注意,我在 ScrollView 的两端添加了一些空白空间,因此实际上可以将第一个和最后一个元素居中,因为 ScrollViewProxy 永远不会滚动超出限制。

关于SwiftUI - 如何在点击时使组件在水平 ScrollView 中居中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71652543/

相关文章:

swift - 单击按钮计数

SwiftUI:删除后更新 NavigationView (iPad)

widget - 在 Flutter 中实现双向 ListView

android - LinearLayout 和 Webview 在 ScrollVIew 中的大小不一样

ios - 使用 UNNotificationContentExtension 为本地通知显示自定义 UI

ios - 适用于 iOS 和 Swift 3.0 的等效 Android 9 补丁(多个可拉伸(stretch)区域)

ios - 如何创建自定义 TextCell 和 TextRow,其中包含 UITextField 的子类?

ios - NavigationView 下的 SwiftUI WKWebView 不接受 displayMode

xcode - 带有默认 Xcode 12 Core Data 项目的空白屏幕

java - ScrollView onclick 设置可见性为Visible