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

如何在SwiftUI中自定义UISegmentedControl的高度?

解决SwiftUI中UISegmentedControl高度自定义问题

直接设置frame.size.height不会生效,因为SwiftUI的布局系统会接管UIViewRepresentable的尺寸计算。下面提供两种可靠的解决方式:

方式一:在UIKit层面添加高度约束

在makeUIView方法中,给UISegmentedControl添加明确的高度约束,确保布局系统尊重这个尺寸:

struct SegmentedControl: UIViewRepresentable {
    typealias UIViewType = UISegmentedControl
    
    var items: [String]
    @Binding var selectedSegmentIndex: Int
    
    func makeUIView(context: Context) -> UISegmentedControl {
        let segmentedControl = UISegmentedControl(items: items)
        
        // 添加高度约束
        segmentedControl.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            segmentedControl.heightAnchor.constraint(equalToConstant: 50)
        ])

        segmentedControl.selectedSegmentIndex = selectedSegmentIndex
        segmentedControl.addTarget(context.coordinator, action: #selector(Coordinator.valueChanged(_:)), for: .valueChanged)
        
        // 直接给当前控件设置样式,避免影响全局分段控件
        let titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
        segmentedControl.setTitleTextAttributes(titleTextAttributes, for: .selected)
        segmentedControl.selectedSegmentTintColor = .systemBlue
        
        return segmentedControl
    }
    
    func updateUIView(_ uiView: UISegmentedControl, context: Context) {
        uiView.selectedSegmentIndex = selectedSegmentIndex
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    class Coordinator: NSObject {
        var control: SegmentedControl
        
        init(_ control: SegmentedControl) {
            self.control = control
        }
        
        @objc func valueChanged(_ sender: UISegmentedControl) {
            control.selectedSegmentIndex = sender.selectedSegmentIndex
        }
    }
}

方式二:在SwiftUI布局时直接设置frame

更符合SwiftUI布局逻辑的方式是,在使用封装的控件时直接指定高度:

struct TestingView: View {
    
    enum ProfileSection : String, CaseIterable {
        case tweets = "Tweets"
        case media = "Media"
        case likes = "Likes"
    }
    
    @State var segmentationSelection : ProfileSection = .tweets
    
    var body: some View {
        SegmentedControl(
            items: ProfileSection.allCases.map { $0.rawValue },
            selectedSegmentIndex: Binding(
                get: { ProfileSection.allCases.firstIndex(of: segmentationSelection) ?? 0 },
                set: { newIndex in
                    guard newIndex < ProfileSection.allCases.count else { return }
                    segmentationSelection = ProfileSection.allCases[newIndex]
                }
            )
        )
        .frame(height: 50) // 直接设置高度
        .padding() // 可选:添加内边距优化显示
    }
}

额外优化说明

  • 原代码中使用hashValue绑定索引存在风险(不同字符串可能有相同hash值),改为直接使用枚举的索引更可靠。
  • 避免用UISegmentedControl.appearance()设置全局样式,直接给当前控件设置属性只会影响该实例,不会干扰其他分段控件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 22:54:53