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) } }
关键修改说明
- 提取重复视图:将单个选项的视图逻辑提取到
segmentItem(for:)方法中,减少代码冗余,方便统一维护样式。 - 动态切换显示内容:根据
isExpanded状态,在展开时渲染所有选项,收缩时仅渲染当前选中的选项。 - 调整点击手势逻辑:
- 展开状态下点击任意选项:选中该选项并自动收缩选择器
- 收缩状态下点击选中项:展开选择器显示全部选项
- 修正宽度计算逻辑:调整frame宽度的赋值逻辑,展开时使用全部选项的总宽度,收缩时使用单个选项宽度。
效果说明
修改后,收缩状态下选择器仅展示当前选中的选项,点击该选项会展开显示所有可选内容;选择任意选项后,选择器自动收缩并展示选中项。
内容的提问来源于stack exchange,提问作者simsab
相关产品推荐
相关产品推荐

