如何移除UIPickerView中的不透明灰色矩形?附相关实现代码参考
解决方法
要移除UIPickerView默认的灰色选中指示框,只需在makeUIView方法初始化UIPickerView后补充以下代码:
// 隐藏旧版本系统的选中指示框 picker.showsSelectionIndicator = false // iOS13及以上系统清空选中指示条颜色 if #available(iOS 13.0, *) { picker.selectionIndicatorColor = .clear }
代码优化建议
- 不要把数据源
data定义为全局变量,建议将其作为CustomPicker的内部存储属性,初始化时传入对应数据,提升组件复用性 - 实现
viewForRow代理方法时复用系统提供的回收视图,避免每次滚动都新建视图,提升滚动性能 - 补充空实现的
updateUIView方法逻辑,实现外部绑定selected值变化时,选择器自动滚动到对应选项 - 行高、行宽、字体样式、颜色等常量建议抽离为可配置属性,避免硬编码,后续调整样式无需修改组件内部逻辑
- 给文字标签添加自适应字号属性,避免内容过长时显示截断
修改后完整代码
struct CustomPicker: UIViewRepresentable { @Binding var selected: String // 数据源改为组件内部属性,初始化时传入 let data: [String] // 可配置样式常量,也可新增更多自定义属性 private let rowWidth: CGFloat = 155 private let rowHeight: CGFloat = 77 private let fontSize: CGFloat = 40 private let textColor = UIColor(red: 0.1215686277, green: 0.01176470611, blue: 0.4235294163, alpha: 1) func makeCoordinator() -> Coordinator { return CustomPicker.Coordinator(parent: self) } func makeUIView(context: Context) -> UIPickerView { let picker = UIPickerView() // 隐藏选中指示框 picker.showsSelectionIndicator = false if #available(iOS 13.0, *) { picker.selectionIndicatorColor = .clear } picker.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) picker.dataSource = context.coordinator picker.delegate = context.coordinator return picker } func updateUIView(_ uiView: UIPickerView, context: Context) { // 外部绑定值变化时自动同步选择器选中状态 guard let row = data.firstIndex(of: selected) else { return } uiView.selectRow(row, inComponent: 0, animated: false) } class Coordinator: NSObject, UIPickerViewDelegate, UIPickerViewDataSource { var parent: CustomPicker init(parent: CustomPicker) { self.parent = parent } func numberOfComponents(in pickerView: UIPickerView) -> Int { return 1 } func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { return parent.data.count } func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView { let labelTag = 1001 let targetView: UIView let targetLabel: UILabel // 复用回收的视图 if let reusedView = view, let label = reusedView.viewWithTag(labelTag) as? UILabel { targetView = reusedView targetLabel = label } else { // 不存在可复用视图时新建 let newView = UIView(frame: CGRect(x: 0, y: 0, width: parent.rowWidth, height: parent.rowHeight)) newView.clipsToBounds = true newView.layer.cornerRadius = parent.rowHeight / 2 newView.backgroundColor = .clear let newLabel = UILabel(frame: newView.bounds) newLabel.tag = labelTag newLabel.textAlignment = .center newLabel.font = .systemFont(ofSize: parent.fontSize, weight: .regular) newLabel.textColor = parent.textColor newLabel.adjustsFontSizeToFitWidth = true newView.addSubview(newLabel) targetView = newView targetLabel = newLabel } targetLabel.text = parent.data[row] return targetView } func pickerView(_ pickerView: UIPickerView, widthForComponent component: Int) -> CGFloat { return parent.rowWidth } func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat { return parent.rowHeight } func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { parent.selected = parent.data[row] } } } // 使用示例 // struct DemoView: View { // @State private var selected = "25" // private let data = ["23","24","25","26","27","28","29"] // var body: some View { // CustomPicker(selected: $selected, data: data) // .frame(height: 300) // } // }
内容的提问来源于stack exchange,提问作者Yotzin Castrejon
相关产品推荐
相关产品推荐

