Closed
Description
When showModalBottomSheet
is called with isDismissible
false
, the default A11Y focus on bottom sheet is not always on the first element.
Steps to Reproduce
With talkback
Talkback version: 12.2
Device: pixel6
OS: Android 12
The following code sample adds two ways to open the bottom sheet - from the floating action button, and from the app bar.
With the following code sample, open the bottom sheet by pressing the floating action button.
When isDismissible is false, the default A11Y focus is inconsistent, depending on where the bottom sheet was triggered from.
- Triggered from the app bar button - the default A11Y will focus on the button (bad - expected focus to be on the title)
- Triggered from the floating action button - the default A11Y will focus on the title (good)
When isDismissible is true, the default A11Y focus will be on the title (good).
Code sample
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _showBottomSheet() {
showModalBottomSheet<SafeArea>(
context: context,
// !!! This is very important to reproduce the a11y focus issue. !!!
// Without it, the title will always get focused by default.
// With it, trigger from app bar with focus on button while trigger from
// floating action button will focus on title.
isDismissible: false,
builder: (_) => Semantics(
scopesRoute: true,
explicitChildNodes: true,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text('This is title'),
TextButton(
onPressed: Navigator.of(context).pop,
child: const Text('Ok'),
),
],
),
),
);
}
void _incrementCounter() {
_showBottomSheet();
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title, style: TextStyle(fontFamily: 'ProductSans')),
actions: [
TextButton(
onPressed: _showBottomSheet,
child: Text('ShowBottomSheet'),
)
],
),
body: Center(
child: Text(
'Button tapped $_counter time${_counter == 1 ? '' : 's'}.',
key: Key('CountText'),
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
),
);
}
}
See b/237621905 for more details.