如何用.inline样式UIDatePicker填充UITextField?显示异常求解决方案
问题:UIDatePicker.inline样式作为UITextField inputView显示异常
我在待办类App中使用UIDatePicker作为UITextField的inputView,旧iOS版本中.wheels样式可正常从底部弹出替代键盘。但应用户需求更换为.inline日历样式后,点击文本框时,选择器仅在屏幕底部显示为一小条,点击该区域才会正常弹出完整日历选择器。
我尝试过设置自定义frame、调用picker.sizeToFit(),均未解决问题。有消息称苹果不建议将.inline样式作为inputView,但未找到官方说明。我希望保持与App内其他选择器一致的交互逻辑,不想单独特殊处理UIDatePicker,现寻求可行的实现方式或替代方案。
相关代码:
class ExpirationDatePickerGenerator { static var pickerStyle: UIDatePickerStyle = .inline static func instantiateExpirationDatePicker(for textField: UITextField, in view: ExpirationDatePickerDelegate) { let picker = UIDatePicker() picker.datePickerMode = .date let calendar = Calendar.autoupdatingCurrent picker.minimumDate = calendar.date(byAdding: .day, value: 1, to: Date()) picker.addTarget(view, action: #selector(view.userDidSelectDate(_:)), for: .valueChanged) picker.sizeToFit() textField.inputView = picker let inputAccessory = picker.createInputAccessoryViewToolbar(inputView: textField) textField.inputAccessoryView = inputAccessory } }
视图控制器viewDidLoad中调用:
ExpirationDatePickerGenerator.instantiateExpirationDatePicker(for: expirationDateTextField, in: self)
可行解决方案
方案一:自定义容器视图包装UIDatePicker
.inline样式的UIDatePicker作为inputView时,系统不会自动计算其完整高度,通过给picker包裹一个容器视图,让容器视图适配inputView的标准尺寸,即可让picker正常显示:
修改instantiateExpirationDatePicker方法:
static func instantiateExpirationDatePicker(for textField: UITextField, in view: ExpirationDatePickerDelegate) { let picker = UIDatePicker() picker.datePickerMode = .date picker.preferredDatePickerStyle = .inline let calendar = Calendar.autoupdatingCurrent picker.minimumDate = calendar.date(byAdding: .day, value: 1, to: Date()) picker.addTarget(view, action: #selector(view.userDidSelectDate(_:)), for: .valueChanged) // 创建容器视图作为inputView let containerView = UIView() picker.translatesAutoresizingMaskIntoConstraints = false containerView.addSubview(picker) // 约束picker在容器内居中,预留上下边距 NSLayoutConstraint.activate([ picker.centerXAnchor.constraint(equalTo: containerView.centerXAnchor), picker.topAnchor.constraint(equalTo: containerView.topAnchor, constant: 16), picker.bottomAnchor.constraint(equalTo: containerView.bottomAnchor, constant: -16) ]) textField.inputView = containerView let inputAccessory = picker.createInputAccessoryViewToolbar(inputView: textField) textField.inputAccessoryView = inputAccessory }
方案二:子类化UIDatePicker重写intrinsicContentSize
通过子类化强制返回足够容纳inline日历的高度,让系统正确识别picker的尺寸:
static func instantiateExpirationDatePicker(for textField: UITextField, in view: ExpirationDatePickerDelegate) { // 子类化重写固有尺寸 class InlineDatePicker: UIDatePicker { override var intrinsicContentSize: CGSize { // 根据iOS版本调整高度,320px足以容纳完整inline日历 return CGSize(width: UIView.noIntrinsicMetric, height: 320) } } let picker = InlineDatePicker() picker.datePickerMode = .date picker.preferredDatePickerStyle = .inline let calendar = Calendar.autoupdatingCurrent picker.minimumDate = calendar.date(byAdding: .day, value: 1, to: Date()) picker.addTarget(view, action: #selector(view.userDidSelectDate(_:)), for: .valueChanged) textField.inputView = picker let inputAccessory = picker.createInputAccessoryViewToolbar(inputView: textField) textField.inputAccessoryView = inputAccessory }
注意事项
- 苹果虽未明确禁止
.inline样式作为inputView,但inputView的设计初衷是替代键盘,inline日历更适合作为页面内静态控件,不过上述方案可规避显示异常问题。 - 需在iOS 15及以上版本测试(inline样式仅支持iOS 15+),确保不同系统版本显示一致。
内容的提问来源于stack exchange,提问作者swiftsquirrel
相关产品推荐
相关产品推荐

