在UIViewRepresentable中嵌入容器视图的UIDatePicker如何设置固有高度
在UIViewRepresentable中嵌入容器视图的UIDatePicker如何设置固有高度
我来帮你分析这个问题,你遇到的核心问题是把UIDatePicker放进自定义容器后,作为UITextField的inputView时高度显示异常。直接用UIDatePicker没问题,是因为系统已经默认识别它的固有尺寸,但自定义容器需要明确告诉系统尺寸规则,另外你的代码里还有个小疏漏导致日期选择的回调不会触发,我一起帮你修正。
问题根源拆解
- 自定义容器的自动布局遮罩未关闭,导致你添加的约束和系统默认的自动布局规则冲突,尺寸计算异常;
- UIDatePicker没有绑定值变化的监听事件,导致选择日期后无法同步到绑定的变量;
- 自定义容器的固有尺寸逻辑可以更明确,确保系统能正确识别它的高度。
修正后的完整代码
struct DatePickerTextField: UIViewRepresentable { private let dateFormatter: DateFormatter = { let dateFormatter = DateFormatter() dateFormatter.dateFormat = "dd.MM.yyyy" return dateFormatter }() public var placeholder: String @Binding public var date: Date? func makeUIView(context: Context) -> UITextField { let textField = UITextField() let datePicker = UIDatePicker() let container = DatePickerContainer() // 关键:关闭容器的自动布局遮罩,让自定义约束生效 container.translatesAutoresizingMaskIntoConstraints = false datePicker.translatesAutoresizingMaskIntoConstraints = false container.addSubview(datePicker) NSLayoutConstraint.activate([ datePicker.leadingAnchor.constraint(equalTo: container.leadingAnchor), datePicker.trailingAnchor.constraint(equalTo: container.trailingAnchor), datePicker.topAnchor.constraint(equalTo: container.topAnchor), datePicker.bottomAnchor.constraint(equalTo: container.bottomAnchor) ]) datePicker.datePickerMode = .date datePicker.preferredDatePickerStyle = .inline // 新增:给DatePicker绑定值变化监听,触发回调更新绑定变量 datePicker.addTarget(context.coordinator, action: #selector(context.coordinator.dateValueChanged), for: .valueChanged) // 可选:给容器设置明确高度约束,或依赖子视图固有尺寸 container.heightAnchor.constraint(equalToConstant: 300).isActive = true textField.inputView = container // Accessory View 逻辑保持不变 let toolbar = UIToolbar() toolbar.sizeToFit() let flexibleSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: context.coordinator, action: #selector(context.coordinator.doneButtonAction)) toolbar.setItems([flexibleSpace, doneButton], animated: true) textField.inputAccessoryView = toolbar context.coordinator.dateChanged = { self.date = datePicker.date } context.coordinator.doneButtonTapped = { if self.date == nil { self.date = datePicker.date } textField.resignFirstResponder() } return textField } class DatePickerContainer: UIView { override init(frame: CGRect) { super.init(frame: frame) // 关键:关闭自动布局遮罩 translatesAutoresizingMaskIntoConstraints = false } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override var intrinsicContentSize: CGSize { // 两种可选方案: // 1. 固定高度(推荐inline风格的DatePicker用300左右) return CGSize(width: UIView.noIntrinsicMetric, height: 300) // 2. 完全依赖子视图的固有尺寸 // return subviews.compactMap { $0.intrinsicContentSize }.first ?? CGSize(width: UIView.noIntrinsicMetric, height: 300) } } func updateUIView(_ uiView: UITextField, context: Context) { if let selectedDate = self.date { uiView.text = self.dateFormatter.string(from: selectedDate) } } func makeCoordinator() -> Coordinator { Coordinator() } class Coordinator { public var dateChanged: (() -> Void)? public var doneButtonTapped: (() -> Void)? @objc func dateValueChanged() { self.dateChanged?() } @objc func doneButtonAction() { self.doneButtonTapped?() } } }
关键修改点说明
- 关闭容器的自动布局遮罩:在
DatePickerContainer的初始化方法和使用前,都设置translatesAutoresizingMaskIntoConstraints = false,避免系统默认布局和自定义约束冲突; - 绑定DatePicker的值变化事件:通过
addTarget给UIDatePicker添加valueChanged监听,确保选择日期后能触发回调更新绑定变量; - 明确容器的尺寸规则:要么给容器添加固定高度约束,要么让它的固有尺寸依赖子视图(UIDatePicker)的尺寸,两种方式都能解决高度异常问题。
这样修改后,容器作为inputView就能正确显示高度,同时日期选择的回调也能正常工作了。你可以根据需求调整容器高度,或者让它完全适配DatePicker的固有尺寸。
内容来源于stack exchange
相关产品推荐
相关产品推荐

