You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI水平ScrollView滚动时如何实现视图居中对齐?

SwiftUI水平ScrollView滚动结束后视图居中对齐方案

你的场景是:水平ScrollView内的图片高度一致、宽度可变,当前使用.scrollTargetBehavior(.viewAligned)时滚动默认对齐leading边缘,但点击视图能通过.scrollPosition(id: $detailScrollPosition, anchor: .center)触发居中对齐,需要实现手动滚动结束后也自动让视图居中。

解决方法

通过自定义ScrollTargetBehavior,修改滚动结束时的目标偏移量,让当前视图自动居中;同时保留点击触发居中的逻辑。

修改后的完整代码

import SwiftUI
import Kingfisher

struct TopPostMediaView: View {
    @State var detailScrollPosition: UUID? = nil
    
    var body: some View {
        ScrollView {
            VStack(alignment: .leading, spacing: 10) {
                GeometryReader { proxy in
                    let containerSize = proxy.size
                    ScrollView(.horizontal) {
                        HStack(spacing: 10) {
                            ForEach(mynewtemp) { pic in
                                KFImage(URL(string: pic.photo))
                                    .resizable()
                                    .aspectRatio(contentMode: .fill)
                                    .frame(maxWidth: containerSize.width)
                                    .overlay(
                                        RoundedRectangle(cornerRadius: 10)
                                            .stroke(Color.gray.opacity(0.4), lineWidth: 1.0)
                                    )
                                    .clipShape(RoundedRectangle(cornerRadius: 10))
                                    .contentShape(RoundedRectangle(cornerRadius: 10))
                                    .onTapGesture {
                                        withAnimation(.easeInOut(duration: 0.15)) {
                                            detailScrollPosition = pic.id
                                        }
                                    }
                                    .frame(maxWidth: containerSize.width, maxHeight: containerSize.height)
                            }
                        }
                        .scrollTargetLayout()
                    }
                    .scrollPosition(id: $detailScrollPosition, anchor: .center)
                    .scrollIndicators(.hidden)
                    .scrollTargetBehavior(CenterAlignedScrollBehavior(containerWidth: containerSize.width))
                    .scrollClipDisabled()
                }
                .frame(height: 250)
            }
        }
    }
}

// 自定义滚动目标行为:让视图滚动结束后居中
struct CenterAlignedScrollBehavior: ScrollTargetBehavior {
    let containerWidth: CGFloat
    
    func updateTarget(_ target: inout ScrollTarget, context: ScrollTargetContext) {
        // 计算让视图居中的偏移量:视图中点 - ScrollView容器的一半宽度
        target.contentOffset.x = target.rect.midX - containerWidth / 2
    }
}

#Preview {
    TopPostMediaView()
}

let mynewtemp: [tempStruct] = [
    tempStruct(id: UUID(), photo: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRmCy16nhIbV3pI1qLYHMJKwbH2458oiC9EmA&s"),
    tempStruct(id: UUID(), photo: "https://th.bing.com/th/id/OIG2.9O4YqGf98tiYzjKDvg7L"),
    tempStruct(id: UUID(), photo: "https://th.bing.com/th/id/OIG2.9O4YqGf98tiYzjKDvg7L")
]

struct tempStruct: Identifiable, Hashable {
    var id: UUID
    var photo: String
}

关键说明

  • 自定义ScrollTargetBehavior:通过updateTarget方法修改滚动结束后的目标偏移量,让视图的中点与ScrollView容器的中点对齐,实现居中效果。
  • 保留原点击逻辑:点击视图时仍通过修改detailScrollPosition触发带动画的居中滚动,与滚动行为保持一致。
  • 简化视图层级:移除了多余的LazyHStack,直接让图片作为HStack的子视图,减少不必要的层级嵌套。

内容的提问来源于stack exchange,提问作者Ahmed Zaidan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 22:40:01