iOS accessibility fields grouped by View - ios

As I understand it the accessibility tool on iOS reads top down and left to right. Is there a way to group by view so that two views next to each other at equal height (one on the right and one on the left) will not have their respective elements read together (right left, right left) but rather all the right view's elements followed by the left view's elements?

Using the UIAccessibilityContainer protocol and especially the shouldGroupAccessibilityElement instance property may help you grouping all the accessible elements to be read out by VoiceOver in a specific order. 👍
I suggest to take a look at this good example including {code snippet (ObjC;Swift) + illustration} that highlights the way to spell out a numeric keypad following a predetermined sequence. 😉

The accepted answer is good, but to save the next person more reading here's what you can do:
func setAccessibility() {
/// groups all elements into a single accessibility element.
/// The order isn't important for screen reader.
accessibilityElements = [rightLabel, leftLabel]
/// required
isAccessibilityElement = true
/// grouping does not auto generate accessibilityLabel content,
/// so you can setup the text as you like.
let rightText = rightLabel.text ?? ""
let leftText = leftLabel.text ?? ""
accessibilityLabel = "\(rightText), \(leftText)"
}
The order of the array of elements isn't really important to a screen reader as the label still needs to be constructed separately. There may be other purposes for keeping the order though.

Related

Custom NSMenuItem with right-aligned detail text label

What I want to implement
I am looking for a way to display a title label and a detail text label in a NSMenuItem.
Preferably it would look something like this:
The Title Label is left aligned with all the other NSMenuItem's
titles
The Detail Text Label is right-aligned
The Detail Text Label has a different text color than the title
Selection/Submenus etc. work as expected
What have I tried already
By reading the documentation I found the following possible implementations:
Create a custom NSView and set NSMenuItem.view
Use a default NSMenuItem and use a NSAttributedString
First I tried to use a custom NSView. However I could not get the NSMenuItem to size correctly in order to display all the available text. I guess some autoresizing masks do not work correctly but I am not sure. Also this way I would need to re-implement selection/arrow for the submenu, ...
Then I started to experiment with NSAttributedString. I calculate the title with the most characters and then pad the string with title += string.padding(toLength: maxTitleLength, withPad: " ", startingAt: 0). The NSAttributedString colors the title and the detail label differently. However this does not seem to work since the detail labels are not correctly aligned although the title is padded to the same length. I guess this makes sense since characters have different widths?
TL;DR - Question
So is there any other way to implement the desired design which I did not find? Do you have any advice for me on how to implement this?
Nevermind I found the answer myself. Actually it works for me now by using the view property of the NSMenuItem to set a custom view. This answer lead me to the right direction: Highlighting a NSMenuItem with a custom view?.

Accessibility: focus on a view

In my application (that has to be accessible for blind user) I have this scenario (its a grammatic exercise)
When I try it on a device turning on VoiceOver, first it focus on the first part of the sentence, so in that case it read "Kesha" and when i swipe right to read the next part it read the second part of the sentence "the contract because...". What I want is to make it also focus on the gray box (that is a UIViewelement) before it read the second part of the sentence, so that the user know where that empty box is in the sentence, but i don't know how to do that.
I alread tried grayBox.accessibilityLabel = "empty box" or grayBox.accessibilityHint = "empty box" but it just don't set the focus on that view and it doesn't speak. I also tried to put an empty UILabel inside the box but I have some issue positioning that in the right order and I don't think it is the right way to do it. Any suggestion?
On the UIView that you want to 'receive focus' you just need to enable accessibility or mark it as an accessible element, An example:
myGreyView.isAccessibilityElement = true
myGreyView.accessibilityLabel = "A grey box"
myGreyView.accessibilityHint = "this is a secretive box. I don't know what it does"
You can also tick a box in the UIView's properties in xcode interface builder "Accessibility Enabled" I think its called. Which also lets you set the label and hint.
For more information see this Apple guide to VoiceOver
In regards to the order of elements being read out. Is the first part and second part different UILabels or one label?
Are you adding these in code or Xib/Storyboard? Depending on the order they are added as subviews can effect the order VoiceOver reads items out.
When adding the 3x UI elements add them in this order below.
UILabel - "Kesha"
UIView - Gray box, "A grey box"
UILabel - "the contract because it was not fair."
If you have added them via Interface builder (Xib/Storyboard) make sure the order is correct in the view hierarchy.
If this fails you could try overriding the method "accessibilityElements" and return an array of the labels and grey view in the order you want them read out.

iOS: creating an expandable label

I'm trying to create an expandable label that looks like the one in the picture:
I have two problems:
How do I make the label truncate the tail such that it leaves enough place for the More button/clickable text?
How do I place the More text?
Maybe, I am going about it the wrong way? Instead of playing with the number of lines, should I maybe try to calculate how much text goes into one and a half line and present it only, and then when clicking More I present the whole text?
Would appreciate any advice, thanks!
You can use this library to achieve your expected output.
https://github.com/apploft/ExpandableLabel
Specify the number of lines you want to display default.
expandableLabel.numberOfLines = 2
Set true if the label should be collapsed or false for expanded.
expandableLabel.collapsed = true
collapsedAttributedLink
Set the link name that is shown when collapsed.
expandableLabel.collapsedAttributedLink = NSAttributedString(string: "More")
expandedAttributedLink
Set the link name that is shown when expanded. It is optional and can be nil.
expandableLabel.expandedAttributedLink = NSAttributedString(string: "Less")

VoiceOver accessibility focus on a series of elements

Say I have a dialog box like this:
and I want to focus on title, then body and then each button one after another. I am able to focus on body using
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, dialog.bodyLabel);
but is there any way to define a set of elements we want to focus instead of a single one?
EDIT:
I have also tried to make a list of elements I want to focus on using this syntax:
dialog.accessibilityElements = #[dialog.titleLable, dialog.bodyLable, etc];
but it just reads the first element (in this case dialog.titleLable) and doesn't move to the next one. Any thoughts?
The default value is set to NO for all the elements.
set the isAccessibleElement to YES for the all individual elements in the dialog
and then you can do
dialog.accessibilityElements = #[dialog.titleLable, dialog.bodyLable];
so that voice over reads title label first and body label next.

UserInteractive Substring in text Label

i am generating a label in a view with label text retrieving from a JSON file.
now there are certain texts(values) retrieved from the JSON file that are user interactive texts (URL/some action) and some are not.
Now i am retrieving the data which are user interactive, setting them as text of a UILabel (which i created dynamically) and setting it in the view (PS. my view controller only has a 2 views inside,one that is default and another in which i am generating the label).
The problem that is arising is that the interactive strings(labels) are set in one line and the ones that are not interactive are set in the next line(as i am creating individial labels for them) even if its a single word.
I want to set the labels (with the texts - interactive/noninteractive) side by side untill there is no space.
Cant wrap my head around it because its a logical problem.
Any help is appreciated

Resources