如何让TextField生成的DatePicker不遮挡iPhone X Home指示器
解决DatePicker遮挡Home Indicator的问题 & 更友好的实现方案
一、先搞定你当前的遮挡问题
你直接把DatePicker设为TextField的inputView时,它默认会紧贴屏幕底部,完全没考虑iPhone X及以后机型的安全区域(就是Home Indicator那一块的间距)。给你个简单的解决思路:给DatePicker套个容器View,通过约束让它避开安全区域:
// 1. 创建容器View,高度设为DatePicker默认的216 let pickerContainer = UIView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: 216)) // 2. 初始化你的DatePicker let myDatePicker = UIDatePicker() myDatePicker.datePickerMode = .date // 按需设置日期模式 // 3. 关闭自动布局转换,给DatePicker加约束 myDatePicker.translatesAutoresizingMaskIntoConstraints = false pickerContainer.addSubview(myDatePicker) NSLayoutConstraint.activate([ myDatePicker.leadingAnchor.constraint(equalTo: pickerContainer.leadingAnchor), myDatePicker.trailingAnchor.constraint(equalTo: pickerContainer.trailingAnchor), myDatePicker.topAnchor.constraint(equalTo: pickerContainer.topAnchor), // 关键:让DatePicker底部对齐容器的安全区域底部,自动避开Home Indicator myDatePicker.bottomAnchor.constraint(equalTo: pickerContainer.safeAreaLayoutGuide.bottomAnchor) ]) // 4. 把容器设为TextField的inputView textField.inputView = pickerContainer
这样DatePicker就会像系统键盘一样自动留出底部安全区域的空间啦。
二、更适合新手的实现方式
其实直接用inputView的方式虽然可行,但新手容易踩适配坑,而且交互体验不如系统原生弹窗友好。推荐两种更省心的方案:
方案1:用UIAlertController嵌入DatePicker
系统会自动处理所有适配,包括安全区域,代码逻辑也清晰:
// 给TextField加点击触发事件,或者用UITextFieldDelegate的textFieldShouldBeginEditing方法调用 @objc func showDatePickerAlert() { let alert = UIAlertController(title: "选择日期", message: "\n\n\n\n\n\n", preferredStyle: .alert) let datePicker = UIDatePicker() datePicker.datePickerMode = .date datePicker.preferredDatePickerStyle = .wheels // iOS13+支持滚轮样式 // 把DatePicker加到Alert的view里 alert.view.addSubview(datePicker) datePicker.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ datePicker.leadingAnchor.constraint(equalTo: alert.view.leadingAnchor, constant: 20), datePicker.trailingAnchor.constraint(equalTo: alert.view.trailingAnchor, constant: -20), datePicker.topAnchor.constraint(equalTo: alert.view.topAnchor, constant: 40) ]) // 添加取消和确定按钮 alert.addAction(UIAlertAction(title: "取消", style: .cancel)) alert.addAction(UIAlertAction(title: "确定", style: .default) { [weak self] _ in // 处理选中的日期,赋值给TextField let formatter = DateFormatter() formatter.dateStyle = .medium self?.textField.text = formatter.string(from: datePicker.date) }) present(alert, animated: true) }
方案2:底部弹窗式DatePicker(贴近键盘体验)
这种弹出位置和键盘一致,用户接受度更高,同样不用自己处理适配:
@objc func showBottomDatePicker() { let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) let datePicker = UIDatePicker() datePicker.datePickerMode = .date datePicker.preferredDatePickerStyle = .wheels // 添加DatePicker到Alert alert.view.addSubview(datePicker) datePicker.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ datePicker.leadingAnchor.constraint(equalTo: alert.view.leadingAnchor), datePicker.trailingAnchor.constraint(equalTo: alert.view.trailingAnchor), datePicker.topAnchor.constraint(equalTo: alert.view.topAnchor), datePicker.heightAnchor.constraint(equalToConstant: 216) ]) // 调整Alert的整体高度,适配DatePicker和按钮 alert.preferredContentSize = CGSize(width: view.frame.width, height: 216 + 60) // 添加操作按钮 alert.addAction(UIAlertAction(title: "取消", style: .cancel)) alert.addAction(UIAlertAction(title: "确定", style: .default) { [weak self] _ in let formatter = DateFormatter() formatter.dateStyle = .medium self?.textField.text = formatter.string(from: datePicker.date) }) // 适配iPad(如果你的App要兼容iPad的话) if let popover = alert.popoverPresentationController { popover.sourceView = textField popover.sourceRect = textField.bounds } present(alert, animated: true) }
这两种方案都不用手动处理安全区域,系统会自动搞定,而且交互更贴近用户习惯,新手也更容易理解和维护。
内容的提问来源于stack exchange,提问作者Hao
相关产品推荐
相关产品推荐

