如何在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
相关产品推荐
相关产品推荐

