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

SwiftUI实现带两侧预览效果的分页滚动视图方法

SwiftUI 实现带两侧预览的居中分页滚动视图

需求是实现一个水平分页滚动视图,每个页面为带数字的圆形,滚动时页面始终居中,且两侧能露出相邻页面的预览。以下是针对你的代码问题的解决方案:

问题分析

  • 初始代码中containerRelativeFrame的span: 5让页面占满容器宽度,无法露出两侧预览;
  • 修改后的代码通过span:4和手动添加padding试图实现预览,但滚动时无法保证页面居中,且布局逻辑不够精准。

实现方案

通过自定义滚动目标行为(scrollTargetBehavior)来控制分页对齐,结合容器相对尺寸和合理的间距设置,实现滚动居中+两侧预览的效果:

struct PageView: View {
    var number: Int
    var body: some View {
        ZStack {
            Circle()
                .fill(.blue) // 添加上色,方便查看效果
                .padding(50)
            Text("\(number)")
                .font(.largeTitle)
                .foregroundStyle(.white)
        }
    }
}

struct ContentView: View {
    var body: some View {
        ScrollView(.horizontal) {
            HStack(spacing: 20) { // 设置页面间的间距
                ForEach(1..<5) { i in
                    PageView(number: i)
                        // 每个页面占容器宽度的3/5,留出两侧预览空间
                        .containerRelativeFrame(.horizontal, count: 5, span: 3)
                }
            }
            .padding(.horizontal, 20) // 给首尾页面添加水平内边距,保证预览可见
        }
        .scrollTargetBehavior(.custom { context in
            // 自定义滚动目标的偏移量,让页面始终居中
            let targetWidth = context.target.rect.width
            let containerWidth = context.containerSize.width
            // 计算需要偏移的距离,使目标页面居中
            let offset = (containerWidth - targetWidth) / 2 - context.target.rect.minX
            return ScrollTargetBehaviorResult(offset: offset)
        })
        .scrollIndicators(.hidden) // 可选:隐藏滚动指示器
    }
}

关键说明

  1. 页面尺寸控制:containerRelativeFrame(.horizontal, count: 5, span: 3)表示将容器宽度分为5等份,每个页面占3份,剩下的2份(左右各1份)用于显示相邻页面的预览。
  2. 自定义滚动行为:通过.custom滚动目标行为,计算每个页面需要偏移的距离,确保滚动结束后页面始终居中于容器。
  3. 间距与内边距:HStack(spacing:20)保证页面间的间隔,.padding(.horizontal,20)让首尾页面也能在边缘位置露出部分预览。

内容的提问来源于stack exchange,提问作者Berry Blue

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 09:16:09