无法在 iOS 14 内联 DatePicker 中点击天数

Unable to Tap Days in iOS 14 inline DatePicker

我正在尝试创建一个 expandable/collapsible 日期选择器(类似于 Apple 在“设置”应用的“日期和时间”部分中的日期选择器)。我有一个 table 视图,可以将按钮作为其 table 单元格之一。该按钮显示当前选择的日期作为其标题。点击该按钮将在带有新 iOS 14 inline 日期选择器的按钮下方添加一个 table 单元格。

我面临的问题是,我可以通过更改月份和年份来与日期选择器进行交互,但是当我点击不同的日期时,所选日期并没有改变。我在 valueChanged 上添加了一个目标,当我更改月份和年份时会触发选择器方法,但当我选择不同的日期时不会。

我在 Whosebug 上看到有类似的问题,但不知为何被 OP 删除了。

包含日期选择器的 table 单元格很简单。我正在从它自己的 xib 中取出单元格,而 xib 只包含一个带有日期选择器的视图。我没有设置日期选择器单元格的高度,只是使用 UITableView.automaticDimension 来获取 self-sizing 单元格。我还查看了视图层次结构,日期选择器前面没有任何内容,因此应该将触摸发送到日期选择器。

还有其他人遇到过这个问题吗?

我遇到了同样的问题,我这边的问题是我如何在单元格内添加选择器。

检查你在做 self.contentView addSubview: 而不是 self addSubview

刚遇到同样的问题,我的日历最初工作正常但最终停止工作,UIDatePicker 在通过主视图中的情节提要添加的 UIView 中。

一切正常,我可以点击月份和年份并左右滑动月份。但是当试图点击一天时什么也不会发生。无法进行新的选择。

在我的例子中,它背后的原因是在我的主视图中添加了一个 tapGesture 来隐藏键盘。这使得日历日无法选择。

(https://i.stack.imgur.com/k4AKF.jpg)

好吧,我找到了一个变通办法,似乎允许在背景视图上进行点击手势,并且日历仍然有效;这个想法是在日历视图周围添加 4 个矩形视图,并将您的点击手势添加到这 4 个视图。

将选择器背景视图(我称为我的 datePickerBGView)添加到您的主视图,然后将您的 UIDatePicker(我称为我的选择器)添加到该背景视图并为两个视图分配相同的中心点:

picker.center = datePickerBGView.center

然后调用这个函数:

func addDismissGesture() {
    
    //Work around because with the .inline date picker style tap gestures on the background view interfere with the day selection action on the picker's calendar view
    let leftDismissActionTap = UITapGestureRecognizer(target: self, action: #selector(dismissCalendar))
    let rightDismissActionTap = UITapGestureRecognizer(target: self, action: #selector(dismissCalendar))
    let topDismissActionTap = UITapGestureRecognizer(target: self, action: #selector(dismissCalendar))
    let bottomDismissActionTap = UITapGestureRecognizer(target: self, action: #selector(dismissCalendar))
    let leftDismissArea = UIView()
    let rightDismissArea = UIView()
    let topDismissArea = UIView()
    let bottomDismissArea = UIView()

    leftDismissArea.frame = CGRect(x: 0, y: 0, width: picker.frame.minX - view.frame.minX, height: view.frame.height)
    rightDismissArea.frame = CGRect(x: picker.frame.maxX, y: 0, width: view.frame.maxX - picker.frame.maxX, height: view.frame.height)
    topDismissArea.frame = CGRect(x: leftDismissArea.frame.maxX, y: 0, width: rightDismissArea.frame.minX - leftDismissArea.frame.maxX, height: picker.frame.minY - view.frame.minY)
    bottomDismissArea.frame = CGRect(x: leftDismissArea.frame.maxX, y: picker.frame.maxY, width:rightDismissArea.frame.minX - leftDismissArea.frame.maxX, height:  view.frame.maxY - picker.frame.maxY)
    
    datePickerBGView.addSubview(leftDismissArea)
    datePickerBGView.addSubview(rightDismissArea)
    datePickerBGView.addSubview(topDismissArea)
    datePickerBGView.addSubview(bottomDismissArea)
    
    leftDismissArea.addGestureRecognizer(leftDismissActionTap)
    rightDismissArea.addGestureRecognizer(rightDismissActionTap)
    topDismissArea.addGestureRecognizer(topDismissActionTap)
    bottomDismissArea.addGestureRecognizer(bottomDismissActionTap)
    
    leftDismissArea.backgroundColor = UIColor.black.withAlphaComponent(0.3)
    rightDismissArea.backgroundColor = UIColor.black.withAlphaComponent(0.3)
    topDismissArea.backgroundColor = UIColor.black.withAlphaComponent(0.3)
    bottomDismissArea.backgroundColor = UIColor.black.withAlphaComponent(0.3)
    
    datePickerBGView.bringSubviewToFront(picker)
}

我遇到了同样的问题。在我的例子中,问题出在 UITapGestureRecognizer 中,我添加它来隐藏键盘。

这段代码解决了我的问题:

tapGesture.cancelsTouchesInView = false

在我的例子中,我有一个在背景中带有遮罩的弹出式 datepickerView,我希望 datepickerView 在我单击背景时消失。所以我在后台添加了 UITapGestureRecognizer。添加手势后我无法select日期选择器中的日期

感谢@Сергій Насінник,此代码解决了我的问题:

tapGesture.cancelsTouchesInView = false

import UIKit
import SnapKit

class PopUpDatePickerView: UIView {
    
    let contentView = UIView()
    let datePicker = UIDatePicker()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = .black.withAlphaComponent(0.4)
        
        
        contentView.backgroundColor = .white
        contentView.layer.cornerRadius = 16
        addSubview(contentView)
        contentView.snp.makeConstraints { make in
            make.bottom.equalTo(self.safeAreaLayoutGuide).offset(-10)
            make.left.right.equalToSuperview().inset(5)
        }
        
        datePicker.tintColor = .black
        contentView.addSubview(datePicker)
        datePicker.snp.makeConstraints { make in
            make.edges.equalToSuperview().inset(20)
        }
        
        if #available(iOS 14.0, *) {
            datePicker.preferredDatePickerStyle = .inline
        }
        
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tapHandler(_:)))
        tapGesture.cancelsTouchesInView = false
        addGestureRecognizer(tapGesture)
        
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    @objc func tapHandler(_ sender: UITapGestureRecognizer) {
        guard
            !self.contentView.frame.contains(sender.location(in: self))  else {
            return
        }
        removeFromSuperview()
    }
}