Hello Everyone, I am working on moving TalkBack ac...
# compose
r
Hello Everyone, I am working on moving TalkBack accessibility focus across multiple menus. Currently, the focus moves correctly to the first menu when navigating back from another screen using the back button, but not to the second and third which focus always stays on back icon. I have created three FocusRequester objects and, based on the selected menu, I call requestFocus(). I am passing these requester objects as a Triple to another composable and then applying them in three different menus using modifier.focusRequester(focusRequesters.first) (and similarly for the others). However, I am not sure what might be going wrong. Please find the code snippet with issue video in thread accessibility
val selectedJourney = cachingManager.getCurrentJourney() val increaseFocusRequester = remember { FocusRequester() } val reduceFocusRequester = remember { FocusRequester() } val cancelFocusRequester = remember { FocusRequester() } LaunchedEffect(selectedJourney) { if (context.isAccessibilityEnable()) { awaitFrame() when (selectedJourney) { Journey.INCREASE -> increaseFocusRequester.requestFocus() Journey.REDUCE -> reduceFocusRequester.requestFocus() Journey.CANCEL -> cancelFocusRequester.requestFocus() else -> {} } } } MenuSection( FocusRequesters = Triple (increaseFocusRequester, reduce FocusRequester, cancel FocusRequester) @Composable private fun MenuSection( focusRequesters: TripleFocusRequester, FocusRequester, FocusRequester ) { MenuTileItem( modifier = Modifier .fillMaxWidth() .padding(top = semanticSpaceFixed24DP) .focusRequester(focusRequesters.first), type = MenuTileItemType.INCREASE_LIMIT, enabled = viewModel.isJourneyDisabled(Journey.INCREASE.name), onClick = { viewModel.cacheSelectedJourney(Journey.INCREASE) navController.navigate(Screen.ImportantToKnowRoute.route) } )      MenuTileItem( modifier = Modifier .fillMaxWidth() .padding(top = semanticSpaceFixed24DP) .focusRequester(focusRequesters.second), type = MenuTileItemType.INCREASE_LIMIT, enabled = viewModel.isJourneyDisabled(Journey.INCREASE.name), onClick = { viewModel.cacheSelectedJourney(Journey.INCREASE) navController.navigate(Screen.ImportantToKnowRoute.route) } )      MenuTileItem( modifier = Modifier .fillMaxWidth() .padding(top = semanticSpaceFixed24DP) .focusRequester(focusRequesters.third), type = MenuTileItemType.INCREASE_LIMIT, enabled = viewModel.isJourneyDisabled(Journey.INCREASE.name), onClick = { viewModel.cacheSelectedJourney(Journey.INCREASE) navController.navigate(Screen.ImportantToKnowRoute.route) } )
l
TalkBack focus is different from keyboard navigation focus - focus requester allows you to control keyboard focus but it's separate from TalkBack. You can't programmatically control TalkBack in this way
r
Could you please suggest how to control TalkBack focus?
l
You can't control it really, it's controlled by the system. You can use semantics to adjust traversal order and things but you can't programmatically move focus
r
Ok, if possible could you please share how we can use semantic to adjust traversal order based on video steps like navigation between screen?
Even with semantic we cannot move focus right?
All the guidance is here
r
Ok thanks, one question will semantic traversal will move focus into different elements right?
l
It controls how accessibility moves when the user navigates through the application with a11y
r
Ok got it. Thank you for the guidance
Hi @Louis Pullen-Freilich [G] I have tried setting semantic isTraversalGroup flag & traversalIndex but it is not moving to different menu automatically, like I am expecting focus should come to corresponding menu which triggers the navigation. val menuItems = listOf( EligibleJourney.INCREASE, EligibleJourney.REDUCE, EligibleJourney.CANCEL ) // Assign a unique traversalIndex to each item. // The selected item gets a traversalIndex of 0f. // The other items get a traversalIndex of 1f, 2f, etc., in their original order. val traversalIndices = mutableMapOfEligibleJourney, Float() var currentIndex = 1f menuItems.forEach { item -> if (item == selectedJourney) { traversalIndices[item] = 0f } else { traversalIndices[item] = currentIndex currentIndex += 1f } } // Menu item for 'INCREASE' journey. MenuTileItem( modifier = Modifier .fillMaxWidth() .padding(top = semanticSpaceFixed24DP) .semantics { traversalIndex = traversalIndices[EligibleJourney.INCREASE] ?: 1f }, type = MenuTileItemType.INCREASE_LIMIT, enabled = viewModel.isJourneyDisabled(EligibleJourney.INCREASE.name).not(), onClick = { viewModel.cacheSelectedJourney(EligibleJourney.INCREASE) navController.navigate(Screen.ImportantToKnowRoute.route) } ) // Menu item for 'REDUCE' journey. MenuTileItem( modifier = Modifier .fillMaxWidth() .padding(top = semanticSpaceFixed24DP) .semantics { traversalIndex = traversalIndices[EligibleJourney.REDUCE] ?: 2f }, type = MenuTileItemType.REDUCE_LIMIT, enabled = viewModel.isJourneyDisabled(EligibleJourney.REDUCE.name).not(), onClick = { viewModel.cacheSelectedJourney(EligibleJourney.REDUCE) navController.navigate(Screen.ImportantToKnowRoute.route) } ) // Menu item for 'CANCEL' journey. MenuTileItem( modifier = Modifier .fillMaxWidth() .padding(top = semanticSpaceFixed24DP) .semantics { traversalIndex = traversalIndices[EligibleJourney.CANCEL] ?: 3f }, type = MenuTileItemType.CANCEL_OVERDRAFT, enabled = viewModel.isJourneyDisabled(EligibleJourney.CANCEL.name).not(), onClick = { viewModel.cacheSelectedJourney(EligibleJourney.CANCEL) navController.navigate(Screen.ImportantToKnowRoute.route) } ) }
Can TalkBack focus move automatically using semantic traversal property?
l
No it doesn't work this way, the docs contain more information
r
Ok, i have checked but don't find other way. If possible could you please check my code and suggest what semantic traversal property I can use in order to move TalkBack focus which triggers the navigation ? Because I have never worked on semantic for TalkBack focus and this issue is pending since long time
l
You can't control TalkBack focus in this way, the system has some rules and behaviour which are important for user consistency. You can help inform the order in which focus is moved but you can't redirect focus to a different item without user action
You can follow a bug like: http://issuetracker.google.com/issues/405795969 There are some issues here with the default behavior / restoring focus, so future changes there might improve this situation. But until then there is nothing you can really do from the user side
r
Ok thanks for sharing the details.