Ke MA
Ke MA

Reputation: 771

About iOS Accessibility. How to transfer focus to pickerView

I have a UITextfield with an inputView of PickerView. I want to achieve that when users double tap on the UITextfield, the pickerView shows up modally, like default, and the focus of accessibility changes from the textfield to the pickerView. This is how I do it for now:

func textFieldDidBeginEditing(textField: UITextField) {
    let dispatchTime: dispatch_time_t = dispatch_time(DISPATCH_TIME_NOW, Int64(0.65 * Double(NSEC_PER_SEC)))
    dispatch_after(dispatchTime, dispatch_get_main_queue(), {
        UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, self.quantityPicker)})
}

This delegate simply gets called when user double taps the textField and send a UIAccessibilityLayoutChangedNotification after a delay of 0.65 seconds to focus on pickerView.

Then questions are:

  1. I used a delay here to wait for the pickerView pop-up animation to be done, but it will be much better if I can know that pickerView animation is done somewhere and put

    UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, self.quantityPicker)

there. So is there any delegate or other simple way to know that pickerView is ready to use?

  1. When I double tap the textField, it will read the content of the textField first until it gets intercepted. Is there anyway to disable this to make it like: when I single tap the button, read accessibilityLabel, trait, hints etc, and when I double tap it, it reads nothing and just does its job.

Upvotes: 4

Views: 2657

Answers (3)

Dale
Dale

Reputation: 3323

You can use notification centre event UIKeyboardDidShowNotification. In the view controller hosting the UITextField add code to viewWillAppear method:

NSNotificationCenter.defaultCenter().addObserver(self, 
                       selector: #selector(self.keyboardDidShow(_:)), 
                       name: UIKeyboardDidShowNotification, 
                       object: nil)

In the viewWillDisappear method add:

NSNotificationCenter.defaultCenter().removeObserver(self)

Then add a method keyboardDidShow:

func keyboardDidShow(notification:NSNotification) {
    UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, self.quantityPicker)
}

Of course if you have other input fields in your view controller you'll need to add some conditional code to keyboardDidShow.

Tested and working. Thanks for the question, I've been chasing the same issue.

Upvotes: 5

Matt Stobbs
Matt Stobbs

Reputation: 639

@Dale's answer in Swift 4:

viewWillAppear

NotificationCenter.default.addObserver(self, selector: #selector(keyboardDidShow(notification:)), name: UIResponder.keyboardDidShowNotification, object: nil)

viewWillDisappear

NotificationCenter.default.removeObserver(self)

keyboardDidShow

@objc func keyboardDidShow(notification: Notification) {
    UIAccessibility.post(notification: .layoutChanged, argument: self.quantityPicker)
}  

Upvotes: 0

MobA11y
MobA11y

Reputation: 18900

If you present the view as part of a separate modal view controller, you can use the viewDidAppear method as the callback you are looking for.

-(void)viewDidAppear:(BOOL)animated {
    UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, outletOfViewYouWantFocused);
}

Upvotes: 0

Related Questions