I have a UIPickerView that is used to select musical instruments, and I have a play icon next to each instrument name that I want to play the appropriate sound when the user clicks it, so that they can hear what the instrument sounds like before they select it in the picker.
I have no problem creating images that response to taps in general.
However, within a UIPickerView, an image that is created as part of the row doesn’t seem to receive clicks (I would guess the UIPickerView somehow takes priority?)
What do I need to do to ensure that my images get tap events?
Many thanks!
func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
let parentView = UIView()
let label = UILabel(frame: CGRect(x: 60, y: 0, width: 80, height: 50))
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 50, height:50))
if #available(iOS 13.0, *) {
imageView.image = UIImage.add
let tapGR = UITapGestureRecognizer(target: self, action: #selector(self.imageTapped))
imageView.addGestureRecognizer(tapGR)
imageView.isUserInteractionEnabled = true
} else {
// Fallback on earlier versions
}
label.text = "red"
parentView.addSubview(label)
parentView.addSubview(imageView)
return parentView
}
2
Answers
Good question. I haven’t done a lot with this specific scenario but I’ve done similar stuff with UITableView. Some ideas:
Debug View Hierarchy Icon in XCode
You won’t be able to add a gesture recognizer to the
viewForRow
view — all touches get eaten by the picker view.So, you could write your own picker view which, depending on how closely you want to replicate the built-in picker view, could be fairly simple or super complex.
Or… you can add a tap recognizer to the picker view … then check if the tap is inside the center row’s image view.
Here’s a quick example…
We’ll use this as our custom row view:
The only "non-usual" thing is the
func tappedImageView(_ p: CGPoint) -> Bool
… it will check the passed point and return true if the point is inside the image view frame, or false if it’s not.We’re also going to toggle the image between
UIImage.add
andUIImage.checkmark
so we have some visual feedback.Our tap gesture handler (in the controller class) will:
MyPickerRowView
classSo, here’s the controller class: