Reputation: 283
I'm trying to create an expandable/collapsible date picker (similar to Apple's date picker in the Date & Time section of the Settings app). I have a tableview that can have a button as one of its table cells. That button shows the currently picked date as its title. Tapping on that button will add a table cell below the button with the new iOS 14 inline
date picker.
The issue I'm facing is that I can interact with the date picker by changing the month and year, but the selected day doesn't change when I tap on different days. I added a target on valueChanged
and the selector method is triggered when I change the month and year, but not when I choose a different day.
I saw there was a similar question on StackOverflow, but the OP deleted it for some reason.
The table cell containing the date picker is simple. I am dequeueing the cell from its own xib and the xib only contains a view with the date picker inside it. I am not setting the height of the date picker cell, but just using UITableView.automaticDimension to get self-sizing cells. I also looked at the view hierarchy and there isn't anything in front of the date picker, so the touches should be sent to the date picker.
Has anyone else had this issue?
Upvotes: 13
Views: 6319
Reputation: 1492
In my case, I have a popup datepickerView with a mask in the background, and I want the datepickerView to disappear when I click background. So I added UITapGestureRecognizer in the background. I can't select the date in the datepicker after adding the gesture
Thanks to @Сергій Насінник, This code fixed my problem:
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()
}
}
Upvotes: 1
Reputation: 33
I had the same issue. In my case problem was in UITapGestureRecognizer, which I've add to hide keyboard.
This code fixed my problem:
tapGesture.cancelsTouchesInView = false
Upvotes: 2
Reputation: 53
Ok I found a work around to seemingly allow a tap gesture on the background view and still have the calendar working; the idea is to add 4 rectangular views around the calendar view and add your tap gesture to those 4 views.
Add a picker background view (I called mine datePickerBGView) to your main view and then add your UIDatePicker (I called mine picker) to this background view and assign the same center point to both views:
picker.center = datePickerBGView.center
Then call this function:
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)
}
Upvotes: 0
Reputation: 273
Just had the same issue, my calendar worked fine initially and eventually stopped working, the UIDatePicker was inside a UIView added through storyboard inside The main View.
Everything worked fine and I could click on the month and year and swipe months left and right. But when trying to click on a day nothing would happen. A new selection could not be made.
In my case reason behind it was adding a tapGesture to my main view for hiding keyboard. This made the calendar days unselectable.
(https://i.sstatic.net/k4AKF.jpg)
Upvotes: 11
Reputation: 11
I had the same issue, and on my side was a problem with how I was adding the picker inside of the cell.
Check you are doing self.contentView addSubview:
not self addSubview
.
Upvotes: 1