How to Set the Accessibility Label for a Particular Segment of a Uisegmentedcontrol

How do I set the accessibility label for a particular segment of a UISegmentedControl?

I'm just getting started with KIF myself, so I haven't tested this, but it may be worth a try. I'm sure I'll have the same issue soon, so I'd be interested to hear if it works.

First, UIAccessibility Protocol Reference has a note under accessibilityLabel that says:

"If you supply UIImage objects to display in a UISegmentedControl, you can set this property on each image to ensure that the segments are properly accessible."

So, I'm wondering if you could set the accessibilityLabel on each NSString object as well and be able to use that to access each segment with KIF. As a start, you could try creating a couple of strings, setting their accessibility labels, and using [[UISegmentedControl alloc] initWithItems:myStringArray]; to populate it.

Please update us on your progress. I'd like to hear how this goes

How to Focus Accessibility On A Particular Segment in A UISegmentedControl

I created a blank project as follows to reproduce the problem:
Sample Image

The solution is taking the selectedIndex to display the selected segment and providing the appropriate segment object for the VoiceOver notification: easy, isn't it?

I naively thought that getting the subview in the segmented control subviews array with the selectedIndex would do the job but that's definitely not possible because the subviews can move inside this array as the following snapshot highlights (red framed first element for instance):
Sample Image
The only way to identify a unique segment is its frame, so I pick up the segmented control index and the frame of the selected segment to pass them to the previous view controller.

That will allow to display (index) and read out (frame that identifies the object for the notification) the appropriate selected segment when this screen will appear after the transition.

Hereafter the code snippets for the view controller that contains the 'Next Screen' button:

class SOFSegmentedControl: UIViewController, UpdateSegmentedIndexDelegate {

var segmentIndex = 0
var segmentFrame = CGRect.zero

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

if let segueName = segue.identifier {
if (segueName == "SegmentSegue") {
if let destVC = segue.destination as? SOFSegmentedControlBis {

destVC.delegate = self
destVC.segmentIndex = segmentIndex
destVC.segmentFrame = segmentFrame
}
}
}
}

@IBAction func buttonAction(_ sender: UIButton) { self.performSegue(withIdentifier: "SegmentSegue", sender: sender) }

func updateSegmentIndex(_ index: Int, withFrame frame: CGRect) {

segmentIndex = index
segmentFrame = frame
}
}

... and for the view controller that displays the segmented control:

protocol UpdateSegmentedIndexDelegate: class { 
func updateSegmentIndex(_ index: Int, withFrame frame: CGRect)
}

class SOFSegmentedControlBis: UIViewController {

@IBOutlet weak var mySegmentedControl: UISegmentedControl!

var delegate: UpdateSegmentedIndexDelegate?
var segmentFrame = CGRect.zero
var segmentIndex = 0
var segmentFrames = [Int:CGRect]()

override func viewDidLoad() {
super.viewDidLoad()

mySegmentedControl.addTarget(self,
action: #selector(segmentedControlValueChanged(_:)),
for: .valueChanged)

mySegmentedControl.selectedSegmentIndex = segmentIndex
}

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)

print(mySegmentedControl.subviews)

let sortedFrames = mySegmentedControl.subviews.sorted(by: { $0.frame.origin.x < $1.frame.origin.x})

for (index, segment) in sortedFrames.enumerated() { segmentFrames[index] = segment.frame }

if (self.segmentFrame == CGRect.zero) {
UIAccessibility.post(notification: .screenChanged,
argument: mySegmentedControl)
} else {
mySegmentedControl.subviews.forEach({
if ($0.frame == self.segmentFrame) {
UIAccessibility.post(notification: .screenChanged,
argument: $0)
}
})
}
}

@objc func segmentedControlValueChanged(_ notif: NSNotification) {

delegate?.updateSegmentIndex(mySegmentedControl.selectedSegmentIndex,
withFrame: segmentFrames[mySegmentedControl.selectedSegmentIndex]!) }
}

The final result is as follows:
Sample Image
Sample Image

  1. Double tap to go to the next screen.
  2. Select the next element to focus the second segment.
  3. Double tap to select the focused element.
  4. Get back to the previous screen thanks to the Z gesture natively known by iOS with the navigation controller. The delegate passes the index and the frame of the selected segment.
  5. Double tap to go to the next screen.
  6. The segment that was formerly selected is read out by VoiceOver and still selected.

You can now Focus Accessibility On A Particular Segment in A UISegmentedControl following this rationale.

I try to avoid "hacky" solutions (like the one I just referenced), but I'm willing to consider anything.

Unfortunately, this solution is a hacky one... sorry. However, it works and I couldn't find another one anywhere else: see it as a personal fix unless you get a cleaner one to share? ;o)

UPDATE... That's probably a topic for a second question.

I can't reproduce the behavior of your update: if you create a dedicated topic for this problem, please add the most detailed code and context so as to provide the most accurate solution.

VoiceOver with UISegmentedControl in Swift

In line with Andy's comment I coded:

    segmentedControl.subviews[0].accessibilityLabel = "Seg 2";
segmentedControl.subviews[1].accessibilityLabel = "Seg 1";
segmentedControl.subviews[2].accessibilityLabel = "Seg 0";

Not the best, note subviews are reverse to appearance, but appears to be the only way at this time.

Greg

How do I set the accessibility label for a view in xcode4's interface builder?

To set the variable programmatically you can use its property like this:

UIButton *someButton = [[UIButton alloc] init];
someButton.titleLabel.text = @"Your Button's Text";
someButton.accessibilityLabel = @"SomeNSString";

In the InterfaceBuilder -- built into XCode 4 -- you just have to select the UI item you want to have an accessibility label. The "Identity Inspector", in the "Utility"-pane, offers a textfield where you can enter any label-text you want.

Sample Image

Localized UISegmentedControl

Use - (void)setTitle:(NSString *)title forSegmentAtIndex:(NSUInteger)segment



Related Topics



Leave a reply



Submit