在 iOS 14 中以编程方式打开 UIDatePicker

Posted

技术标签:

【中文标题】在 iOS 14 中以编程方式打开 UIDatePicker【英文标题】:Open UIDatePicker programmatically in iOS 14 【发布时间】:2020-11-29 13:18:40 【问题描述】:

我有这个普通的UIDatePicker(抱歉不是英文的,请忽略):

但问题是它只在我按下日期选择器时出现:

我想知道如何在第一张图片中显示日期选择器(它用模糊效果覆盖了所有屏幕)仅使用代码,因此用户不需要按日期选择器显示日期选择器。谢谢。

【问题讨论】:

您是如何创建该用户界面的?故事板?代码?你有插座吗? 故事板,是的,我确实有一个出口。但是当我按下紧凑菜单时,会生成第一张图片中的菜单 你找到解决办法了吗? 不,还没有。 . 您可以使用yourPicker.becomeFirstResponder() 强制对象成为第一响应者。这应该或多或少地模拟点击日期字段。 【参考方案1】:

您可以使用具有.compact 样式的 datePicker 并在其顶部放置一个 UILabel 并为其设置背景颜色以将 datePicker 隐藏在其后面,并确保标签用户交互已禁用然后您应该能够点击 datePicker,它将显示模式,然后更改 datePicker 的值您可以使用自己的日期格式化程序相应地设置标签的文本,您也可以同时使用 datePicker 和 @987654325 中的标签@ 并使其剪辑到边界

【讨论】:

这是一个聪明的解决方法。它对我有用。我有两个并排的日期选择器。只需确保它们正确排列,以便(较小)标签的点击通过。 我正在使用此解决方法并在点击 datePicker 时隐藏标签,但 ios 15 导致我不再从日期选择器中捕获点击 ***.com/questions/69620836/…【参考方案2】:

我也有同样的问题。我正在使用以下技巧:

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() ) )

然后我只需在视图顶部添加这个日期选择器,它应该会打开这个弹出窗口。

【讨论】:

感谢您的建议,但我不会将此标记为已接受,因为它不能回答我的所有问题。用户仍然必须按下日期选择器才能打开它。我想要一个解决方案,而不是用户按下我只用代码来做。 我认为这是最接近实现此功能的方法【参考方案3】:

不可能在代码中用UIKit14 打开UIDatePicker

UIDatePicker 没有执行此操作的 API UIKit 不允许我们创建对 UIKit 有任何影响的 UIEventsUITouch 对象。

【讨论】:

我知道,我正在寻找一种解决方法,其结果与按下日期选择器的结果相同 @TLGCodin' 这不可能 我不这么认为 我创建了一个赏金,很高兴看到有人告诉我我错了 我有一个问题可以帮助您解决这个问题,什么会触发日期选择器出现?我知道你说过你想要以编程方式,但这背后必须有一个行动。用户会点击任何东西吗?应用会在某个特定点或行为打开它吗?【参考方案4】:

不幸的是,无法以编程方式显示日期选择器弹出窗口,至少不要诉诸可能导致您的应用被拒绝的黑客攻击:

UIDatePicker 控件不公开任何可通过sendActions(for:) 以编程方式触发的事件 - allControlEvents 返回一个空选项集

在 iOS 上以编程方式模拟用户点击是不可能的 - 没有公共 API 来实现这一点,所有解决方法都意味着诉诸私有 API

如果以上还不够,UIDatePicker 的 UI 结构由私有类组成:

结论是,在其当前状态下,UIDatePicker UI 只能通过用户交互来控制。也许这会在未来发生变化,例如UIButton 的暴露动作用于触发与用户点击按钮时相同的行为,所以也许UIDatePicker 将来会暴露这样的动作。

【讨论】:

除非应用崩溃,否则没有人会拒绝应用。 @Dmitry 使用私有 (iOS SDK) API 保证会导致您的二进制文件被提交到 AppStore 后运行的工具自动拒绝。 从未见过这种情况发生。【参考方案5】:

我不知道这是否仍然有效,但您可以使用新的 UIDatePicker 的.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

【讨论】:

如果你能很好地调整弹出框的大小,这非常聪明【参考方案6】:

更新:这不再适用于 iOS 15。

@Amr Mohamed 的答案很聪明,在日期选择器视图上放置标签,但这也会在点击日期选择器视图时导致故障,当日期选择器 vc 动画出来时,您还可以看到日期选择器。

所以我们需要“隐藏”日期选择器视图,但也要让它保持交互。 (不能只使用isHidden = truealpha = 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

然后你可以把这个不可见的日期选择器放在你的标签/其他视图的顶部。一旦你点击标签(实际上是点击了日期选择器),日期选择器 vc 就会动画出来。

【讨论】:

这很棒。谢谢! 此代码不起作用,因为 Alpha 设置为 0 的视图变得不可点击【参考方案7】:

我认为唯一的非 hacky 方法是创建一个新的视图控制器,在其中添加一个具有嵌入式样式的 UIDatePicker 实例,然后以模态或弹出框的形式呈现控制器。

【讨论】:

重复? ***.com/a/63333081/14016301【参考方案8】:

它可以切换到旧样式的日期选择器:

        if (@available(iOS 13.4, *)) 
            [datePicker setPreferredDatePickerStyle:UIDatePickerStyleWheels];
        

【讨论】:

有时正确答案超出了最初问题的范围。 嬉皮士这个答案不是你的财产***.com/a/64710218/14016301【参考方案9】:

日期选择器在 iOS v14.0 中发生了变化,之前它是一个内联轮。 现在在 iOS v14.0 中,您可以做的是告诉它是内联的,它会显示内联日历(无弹出窗口):

if #available(iOS 14.0, *) 
     datePicker.preferredDatePickerStyle = UIDatePickerStyle.inline         

注意:您可能需要修复帧大小,因为日期选择器在 iOS 13(滚轮)和 iOS 14(日历)中看起来会有所不同,因此您可能需要版本 13 的“else”..

【讨论】:

【参考方案10】:

您可以从情节提要中将日期选择器的首选样式设置为“内联”。这样,您将直接获得全屏日期选择。

以下是日期选择器如何查找首选样式“紧凑”(您拥有的样式):

与“内联”(您正在寻找的那个):

【讨论】:

【参考方案11】:

定义这些变量

var datePicker: UIDatePicker!
var datePickerConstraints = [NSLayoutConstraint]()
var blurEffectView: UIView!

然后创建一个函数showDatePicker(),调用它来触发UIDatePicker 的显示。首先,创建一个与他的父视图大小相同的子视图,并给它一个模糊效果。然后添加UIDatePicker,作为模糊视图顶部的子视图。

   func showDatePicker() 
        datePicker = UIDatePicker()
        datePicker?.date = Date()
        datePicker?.locale = .current
        datePicker?.preferredDatePickerStyle = .inline
        datePicker?.addTarget(self, action: #selector(dateSet), for: .valueChanged)
        addDatePickerToSubview()
    

    func addDatePickerToSubview() 
        guard let datePicker = datePicker else  return 
        // Give the background Blur Effect
        let blurEffect = UIBlurEffect(style: UIBlurEffect.Style.regular)
        blurEffectView = UIVisualEffectView(effect: blurEffect)
        blurEffectView.frame = self.view.bounds
        blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        self.view.addSubview(blurEffectView)
        self.view.addSubview(datePicker)
        datePicker.translatesAutoresizingMaskIntoConstraints = false
        centerDatePicker()
        view.bringSubviewToFront(datePicker)
    

    func centerDatePicker() 
        guard let datePicker = datePicker else  return 
        // Center the Date Picker
        datePickerConstraints.append(datePicker.centerYAnchor.constraint(equalTo: self.view.centerYAnchor))
        datePickerConstraints.append(datePicker.centerXAnchor.constraint(equalTo: self.view.centerXAnchor))
        NSLayoutConstraint.activate(datePickerConstraints)
    

最后,在UIDatePicker 中选择一个日期

 @objc func dateSet() 
        // Get the date from the Date Picker and put it in a Text Field
        compactDatePicker.date = datePicker.date
        blurEffectView.removeFromSuperview()
        datePicker.removeFromSuperview()
    

不完全确定模糊效果,因此希望有人可以在此解决方案的基础上进行构建。

【讨论】:

但是没有dateTextField。有一个紧凑的日期选择器,它的想法是像用户点击它一样打开它。 我不知道有任何方法可以“伪造”用户点击紧凑型日期选择器,所以我认为使用上面的代码我会通过以内联样式呈现另一个日期选择器来伪造它,然后在被解雇时,将原始紧凑日期选择器的值设置为刚刚显示的值。【参考方案12】:

我猜你正在使用 compact 日期选择器样式,它是 iOS 14 上的一项新功能。而且我认为你可以简单地使用 inline 样式而不是 compact 来显示完整的日历用户界面。并且不要忘记UIDatePicker 只是一个UIView,因此您可以自定义您的演示文稿以实现您想要的模糊效果。

【讨论】:

是的,我知道。但是没有办法用代码打开紧凑的日期选择器,然后当用户关闭它时,它又变小了? 什么样的动作会触发全屏选择器UI的呈现? 按下 UIMenu 中的项目 您可以使用inline 样式的 UI 以编程方式呈现全屏选择器,并使用自定义视图来显示所选日期。 但是动画呢?【参考方案13】:

如果您想继续使用***格式,可以在故事板上将样式设置为***,

或使用此代码

datePicker.preferredDatePickerStyle = .wheels

【讨论】:

没有。再次阅读我的问题。 这不仅仅是关于您的具体问题。有时,当我搜索继续使用***的方法时,此页面会显示给我,并且它会显示在谷歌上,以供将来搜索相同内容的其他人使用。我发布了这个答案来帮助那些人。在我的回答中,我还提到这是为想要继续使用***的人提供的解决方案 谢谢 Mona!我正在找这个。 为什么这个答案有这么多的负面评价......如果有人在情节提要上设置日期选择器,答案就很好......

以上是关于在 iOS 14 中以编程方式打开 UIDatePicker的主要内容,如果未能解决你的问题,请参考以下文章

如何在 iOS 8.0+ 中以编程方式打开设备设置应用程序而不是应用程序设置

在 iOS 中以编程方式将用户带到后台刷新设置

在没有 alertView 的情况下使用 UIWebView 在 iOS 中以编程方式拨打电话

如何在 SwiftUI 中以编程方式滚动列表?

如何在 iOS 开发中以编程方式使用接近传感器?

在 iPhone 中以编程方式从另一个应用程序打开设置应用程序