我有一个普通的 UIDatePicker
(抱歉,它不是英文,请忽略):
但问题是只有在我按下日期选择器时它才会出现:
我想知道如何像第一张图中那样显示日期选择器(覆盖整个屏幕并带有模糊效果),仅通过代码,这样用户就不需要按下日期选择器来显示日期选择器。谢谢。
我有一个普通的 UIDatePicker
(抱歉,它不是英文,请忽略):
但问题是只有在我按下日期选择器时它才会出现:
我想知道如何像第一张图中那样显示日期选择器(覆盖整个屏幕并带有模糊效果),仅通过代码,这样用户就不需要按下日期选择器来显示日期选择器。谢谢。
.compact
样式的 datePicker,并在其上方放置一个 UILabel
,并为其设置背景颜色以隐藏 datePicker
,然后确保标签的用户交互已禁用,然后您就可以在 datePicker 上轻触它,它将显示模态视图,然后更改 datePicker 的值,您可以使用自己的日期格式化程序相应地设置标签的文本,您还可以将 datePicker 和标签都放在一个 UIView
中,并将其裁剪到边界内。很遗憾,目前无法编程显示日期选择器弹出窗口,至少不能使用可能导致您的应用被拒绝的黑客技巧:
UIDatePicker控件不公开任何可通过sendActions(for:)
触发的事件-allControlEvents
返回一个空选项集
在iOS上正式不可能模拟用户点击-没有公共API可以实现这一点,所有解决方法都意味着诉诸私有API
如果以上还不够,那么UIDatePicker的UI结构由私有类组成:
结论是,在其当前状态下,只能通过用户交互来控制UIDatePicker
UI。也许将来会改变,例如UIButton
公开操作以触发与用户点击按钮时相同的行为,因此也许UIDatePicker
将来会公开这样的操作。
我也有同样的问题。我使用以下 hack:
let datePicker = UIDatePicker(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
datePicker.preferredDatePickerStyle = .compact
// Removes Labels
datePicker.subviews.forEach({ $0.subviews.forEach({ $0.removeFromSuperview() }) })
然后我只需在视图顶部添加此日期选择器,它将打开此弹出窗口。
无法使用UIKit14
中的代码打开UIDatePicker
UIDatePicker
没有相应的APIUIKit
不允许我们创建一个对UIKit
产生任何影响的UIEvents
或UITouch
对象。.inline
样式。然后使用自己的视图和动画来模仿.compact
样式的DatePicker的外观。let secondDatePicker = UIDatePicker()
secondDatePicker.preferredDatePickerStyle = .inline
self.view.addSubview(secondDatePicker)
secondDatePicker.translatesAutoresizingMaskIntoConstraints = false
secondDatePicker.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
secondDatePicker.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
更新:在iOS15上,这个方法不再有效。
@Amr Mohamed的答案很聪明,他给日期选择器视图添加了一个标签,但是当点击日期选择器视图时,这也会导致一个故障,当日期选择器视图动画退出时,你也可以看到日期选择器。
所以我们需要“隐藏”日期选择器视图,但又让它保持可交互状态。(我们不能只使用isHidden = true
或者alpha = 0
,否则就无法点击了)
这是我在我的项目中所做的:
extension UIView {
func loopDescendantViews(_ closure: (_ subView: UIView) -> Void) {
for v in subviews {
closure(v)
v.loopDescendantViews(closure)
}
}
}
let datePicker = UIDatePicker()
datePicker.preferredDatePickerStyle = .compact
datePicker.loopDescendantViews {
$0.alpha = $0 is UIControl ? 1 : 0
}
接下来,您可以将这个不可见的日期选择器放在标签/其他视图之上。一旦您点击标签(实际上是点击了日期选择器),日期选择器视图控制器将会动画弹出。
为了确保我们没有漏掉任何显而易见的东西,.inline
样式可以在不需要用户单击日期或时间标签的情况下显示完整的日历。有了这个功能,可以安排任何与显示日历和选定/默认日期等相关的行为...
我找到了一种方法,可以让它在iOS 14和iOS 15上都能正常工作,但由于它读取层次结构,所以可能会在任何即将推出的iOS版本中停止工作:
// The callback from your tap gesture or whatever you use:
func handleTapOnView() {
let datePickerGesture: UIGestureRecognizer? = {
guard let compactView = datePicker.subviews.first else { return nil }
// iOS 15
if let dateLabel = compactView.subviews
.first(where: { String(describing: type(of: $0)).hasSuffix("DateLabel") }),
let gesture = dateLabel.gestureRecognizers?.first {
return gesture
}
// iOS 14
if let gesture = compactView.gestureRecognizers?.last {
return gesture
}
return nil
}()
datePickerGesture?.state = .ended
}
.hasSuffix("DateLabel")
,如果想要聚焦时间选择部分,请使用.hasSuffix("TimeLabel")
。我正在使用这个扩展来设置UIDatePicker
的每个子视图的clear
颜色,然后像其他人建议的那样使用一个UILabel
。
extension UIDatePicker {
private func traverse(view: UIView) {
for subview in view.subviews {
self.traverse(view: subview)
// Setting alpha to 0 disables userInteraction.
subview.alpha = 0.02
}
}
func paintClear() {
self.traverse(view: self)
}
}
yourPicker.becomeFirstResponder()
强制使一个对象成为第一响应者。这应该更或多或少地模拟了对日期字段的轻触。 - Sanzio Angeli