skip to Main Content

Can the accessibility text of a UIView be changed based on the direction the focus it received.

Example:

I have a layout as rendered below, Top Label followed by Collection view, followed by Bottom Label.

enter image description here

Collection view has 4 cells(for this example) and these cells have isAccessibilityElement enabled, so Voice over can read each cell’s content, not the collection view as a whole.

This collection view is basically a table with rows and columns.

When Voice Over(VO) focus is shifted (Top -> Bottom) from ‘Top label’ to ‘Cell 1’, the accessibility text of the ‘Cell 1’ should be ‘<Cell 1 content>, table, with n Rows, n Columns>’ and when focus is traversed through other cells in the collection view, it would only read the cell’s accessibility label respectively.

Query:
When the VO’s focus is shifted(Bottom -> Top) from ‘Cell 4’ to ‘Bottom Label’, can the accessibility text of cell 4’s be ‘<Cell 4 content>, table, with n Rows, n Columns>’ instead of its content.

2

Answers


  1. Chosen as BEST ANSWER

    The solution that worked for me is for listening for the element upon receiving the focus, storing the previous elements locally and settings the accessibility label accordingly.

    Below article helped with the solution - link

    Listening for the focus change. [enter image description here

    enter image description here


  2. The accessibility text of a UIView cannot be changed based on the direction of focus it received.

    There are three issues:

    1. Accessibility Focus is aligned to actually focusable elements (such as TextFields which receive keyboard input) not the VoiceOver cursor current position.
    2. The VoiceOver cursor, whilst you can visit the next/previous field, also allows you to immediately jump to a specific item by dragging around your finger, so you can reach a specific item without having to visit its successor/predecessor.
    3. It is better to not convey the item in terms of geometry (columns and rows) because that can change based on font size, and such details are not of semantic relevance.

    I recommend changing the items to be announced with a hint of "1 of 5" or "x of 5". This means when you visit the item it merely says "1", and then after a short pause it will say "1 of 5".

    Here is an example that does this:

    import SwiftUI
    
    struct ContentView: View {
        
        var body: some View {
            VStack {
                ZStack {
                    Rectangle()
                        .frame(height: 40)
                        .foregroundStyle(.orange)
                    Text("Top Label")
                }
                    .background(.orange)
                    .frame(height: 100)
                    .cornerRadius(10)
                MyCollectionView()
                    .background(.gray)
                ZStack {
                    Rectangle()
                        .frame(height: 40)
                        .foregroundStyle(.orange)
                    Text("Bottom Label")
    
                }
            }
            .padding()
        }
    }
    
    struct MyCollectionView: View {
        static var items = [1, 2, 3, 4, 5]
        
        @AccessibilityFocusState private var isFocused: Bool
    
        var body: some View {
            ScrollView {
                LazyVGrid(columns: [GridItem(.adaptive(minimum: 100))]) {
                    ForEach(MyCollectionView.items, id: .self) { item in
                        MyCollectionItem(item: item)
                    }
                }
                .padding(40)
            }
        }
    }
    
    struct MyCollectionItem: View {
        let item: Int
        @State
        var value: String = ""
        
        var body: some View {
            ZStack {
                Rectangle()
                    .foregroundColor(.blue)
                    .frame(height: 100)
                    .cornerRadius(10)
                Text(String(item))
                    .accessibilityHint("(item) of (MyCollectionView.items.count)")
            }
            
        }
    }
    
    #Preview {
        ContentView()
    }
    

    Here is a screenshot taken with the VoiceOver text box at the bottom so you can see what is spoken:
    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search