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

SwiftUI中如何在TabView实现带前后缩略图的滑动图片展示?

修改SwiftUI黄道十二宫视图实现多图横向滑动布局

需求概述

当前用TabView单页展示选中的黄道星座图片,需要改成一行内显示左侧缩小的上一张图 + 居中主图 + 右侧缩小的下一张图,支持横向滑动切换。

关键修改点

  • 把TabView换成ScrollView(.horizontal)+HStack,实现横向滚动展示多个视图
  • 计算每个星座的索引,判断它是主图、前序还是后续星座,应用不同缩放比例
  • 处理循环逻辑(首尾星座的前后项衔接)
  • 调整布局让主图始终居中,缩略图缩小显示
  • 保留振动反馈逻辑,同步更新选中状态

修改后的完整代码

struct ZodiacSignsView: View {
    let zodiacSigns = ["aries", "taurus", "gemini", "cancer", "leo", "virgo", "libra", "scorpio", "sagittarius", "capricorn", "aquarius", "pisces"]
    @Binding var selectedZodiacSign: String
    
    private var selectedIndex: Int {
        zodiacSigns.firstIndex(of: selectedZodiacSign) ?? 0
    }
    
    var body: some View {
        GeometryReader { geo in
            let mainImgWidth = geo.size.width * 0.6
            let sideImgWidth = geo.size.width * 0.3
            
            ScrollView(.horizontal, showsIndicators: false) {
                HStack(spacing: -sideImgWidth * 0.5) {
                    ForEach(Array(zodiacSigns.enumerated()), id: \.element) { index, sign in
                        // 计算当前项相对于选中项的位置(处理循环)
                        let relativePos = (index - selectedIndex + zodiacSigns.count) % zodiacSigns.count
                        
                        Image(sign)
                            .resizable()
                            .scaledToFit()
                            .frame(width: relativePos == 0 ? mainImgWidth : sideImgWidth)
                            .opacity(relativePos == 0 ? 1 : 0.7)
                            .onTapGesture {
                                withAnimation {
                                    selectedZodiacSign = sign
                                }
                            }
                    }
                }
                .padding(.horizontal, (geo.size.width - mainImgWidth) / 2)
            }
            .background(
                ZStack {
                    Circle()
                        .stroke(
                            LinearGradient(colors: [Color(red: 1.0, green: 0.502, blue: 0.22), Color(red: 1.0, green: 0.761, blue: 0.22)], startPoint: .top, endPoint: .bottom),
                            lineWidth: 4)
                        .frame(width: 170, height: 170)
                }
            )
            .onChange(of: selectedZodiacSign) { _ in
                // 振动反馈
                let generator = UINotificationFeedbackGenerator()
                generator.notificationOccurred(.success)
            }
            .scrollPosition(id: $selectedIndex, anchor: .center)
        }
        .frame(height: 200) // 根据需求调整视图高度
    }
}

代码说明

  1. GeometryReader:获取父视图尺寸,动态计算主图和缩略图的宽度比例
  2. 相对位置判断:通过relativePos区分主图(0)、前一张(11,循环逻辑)、后一张(1),应用不同尺寸和透明度
  3. 滚动控制:用scrollPosition让选中的主图始终居中,点击缩略图可直接切换到对应主图
  4. HStack负间距:让缩略图和主图部分重叠,优化视觉衔接效果
  5. 振动逻辑保留:切换选中项时依然触发成功类型的振动反馈

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 17:58:12