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

SwiftUI可展开自定义分段选择器:收缩时仅显示选中项

SwiftUI可展开分段选择器:收缩时仅显示选中项的修改方案

你的自定义分段选择器当前收缩时会显示左侧选项,要实现收缩状态下仅显示当前选中项,可通过以下修改实现:

原始代码

struct CustomSegmentedPicker: View {
    
    @Binding var preselectedIndex: Int
    
    @State var isExpanded = false
    
    var options: [String]
    let color = Color.orange

    var body: some View {
        HStack {
            ScrollView(.horizontal) {
                HStack(spacing: 4) {
                    ForEach(options.indices, id:\.self) { index in
                        let isSelected = preselectedIndex == index
                        ZStack {
                            Rectangle()
                                .fill(isSelected ? color : .white)
                                .cornerRadius(30)
                                .padding(5)
                                .onTapGesture {
                                    preselectedIndex = index
                                    withAnimation(.easeInOut(duration: 0.5)) {
                                        isExpanded.toggle()
                                    }
                                }
                        }
                        .shadow(color: Color(UIColor.lightGray), radius: 2)
                        .overlay(
                            Text(options[index])
                                .fontWeight(isSelected ? .bold : .regular)
                                .foregroundColor(isSelected ? .white : .black)
                        )
                        .frame(width: 80)
                    }
                }
            }
            .transition(.move(edge: .trailing))
            .frame(width: isExpanded ? 80 : CGFloat(options.count) * 80 + 10, height: 50)
            .background(Color(UIColor.cyan))
            .cornerRadius(30)
            .clipped()
            Spacer()
        }
    }
}

修改后的代码

struct CustomSegmentedPicker: View {
    
    @Binding var preselectedIndex: Int
    
    @State var isExpanded = false
    
    var options: [String]
    let color = Color.orange
    let itemWidth: CGFloat = 80

    var body: some View {
        HStack {
            ScrollView(.horizontal) {
                HStack(spacing: 4) {
                    // 根据展开状态切换显示内容
                    if isExpanded {
                        ForEach(options.indices, id:\.self) { index in
                            segmentItem(for: index)
                        }
                    } else {
                        // 收缩时仅显示选中的选项
                        segmentItem(for: preselectedIndex)
                    }
                }
            }
            .transition(.move(edge: .trailing))
            // 调整frame宽度逻辑:展开时显示全部选项宽度,收缩时固定单个选项宽度
            .frame(width: isExpanded ? CGFloat(options.count) * itemWidth + 10 : itemWidth, height: 50)
            .background(Color(UIColor.cyan))
            .cornerRadius(30)
            .clipped()
            Spacer()
        }
    }
    
    // 提取选项视图为单独方法,避免重复代码
    private func segmentItem(for index: Int) -> some View {
        let isSelected = preselectedIndex == index
        return ZStack {
            Rectangle()
                .fill(isSelected ? color : .white)
                .cornerRadius(30)
                .padding(5)
                .onTapGesture {
                    withAnimation(.easeInOut(duration: 0.5)) {
                        if isExpanded {
                            // 展开状态下:选中选项并收缩
                            preselectedIndex = index
                            isExpanded = false
                        } else {
                            // 收缩状态下:点击选中项展开选择器
                            isExpanded = true
                        }
                    }
                }
        }
        .shadow(color: Color(UIColor.lightGray), radius: 2)
        .overlay(
            Text(options[index])
                .fontWeight(isSelected ? .bold : .regular)
                .foregroundColor(isSelected ? .white : .black)
        )
        .frame(width: itemWidth)
    }
}

关键修改说明

  1. 提取重复视图:将单个选项的视图逻辑提取到segmentItem(for:)方法中,减少代码冗余,方便统一维护样式。
  2. 动态切换显示内容:根据isExpanded状态,在展开时渲染所有选项,收缩时仅渲染当前选中的选项。
  3. 调整点击手势逻辑:
    • 展开状态下点击任意选项:选中该选项并自动收缩选择器
    • 收缩状态下点击选中项:展开选择器显示全部选项
  4. 修正宽度计算逻辑:调整frame宽度的赋值逻辑,展开时使用全部选项的总宽度,收缩时使用单个选项宽度。

效果说明

修改后,收缩状态下选择器仅展示当前选中的选项,点击该选项会展开显示所有可选内容;选择任意选项后,选择器自动收缩并展示选中项。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 02:10:51