-
Notifications
You must be signed in to change notification settings - Fork 27.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Not able to navigate using tab key when using nested Navigators. #112567
Comments
Hi @MattyBoy4444, thanks for filing the issue. This issue is reproducible on the latest
✅: No Issue ❌: Issue reproduced Demo OP issue (ShellRoute)Screen.Recording.2022-09-29.at.17.08.26.movI also tested with named_routes and see that the issue does not occur when using Tab key. Demo named_routesScreen.Recording.2022-09-29.at.17.03.03.movSample code (named_routes)Modified sample code from https://github.com/flutter/packages/blob/main/packages/go_router/example/lib/named_routes.dart (added // Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// TODO(goderbauer): Refactor the examples to remove this ignore, https://github.com/flutter/flutter/issues/110210
// ignore_for_file: avoid_dynamic_calls
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
// This scenario demonstrates how to navigate using named locations instead of
// URLs.
//
// Instead of hardcoding the URI locations , you can also use the named
// locations. To use this API, give a unique name to each GoRoute. The name can
// then be used in context.namedLocation to be translate back to the actual URL
// location.
final Map<String, dynamic> _families = const JsonDecoder().convert('''
{
"f1": {
"name": "Doe",
"people": {
"p1": {
"name": "Jane",
"age": 23
},
"p2": {
"name": "John",
"age": 6
}
}
},
"f2": {
"name": "Wong",
"people": {
"p1": {
"name": "June",
"age": 51
},
"p2": {
"name": "Xin",
"age": 44
}
}
}
}
''');
void main() => runApp(App());
/// The main app.
class App extends StatelessWidget {
/// Creates an [App].
App({Key? key}) : super(key: key);
/// The title of the app.
static const String title = 'GoRouter Example: Named Routes';
@override
Widget build(BuildContext context) => MaterialApp.router(
routerConfig: _router,
title: title,
debugShowCheckedModeBanner: false,
);
late final GoRouter _router = GoRouter(
debugLogDiagnostics: true,
routes: <GoRoute>[
GoRoute(
name: 'home',
path: '/',
builder: (BuildContext context, GoRouterState state) =>
const HomeScreen(),
routes: <GoRoute>[
GoRoute(
name: 'family',
path: 'family/:fid',
builder: (BuildContext context, GoRouterState state) =>
FamilyScreen(fid: state.params['fid']!),
routes: <GoRoute>[
GoRoute(
name: 'person',
path: 'person/:pid',
builder: (BuildContext context, GoRouterState state) {
return PersonScreen(
fid: state.params['fid']!, pid: state.params['pid']!);
},
),
],
),
],
),
],
);
}
/// The home screen that shows a list of families.
class HomeScreen extends StatelessWidget {
/// Creates a [HomeScreen].
const HomeScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text(App.title),
),
body: Column(
children: [
TextField(),
TextButton(onPressed: () {}, child: Text('Hello')),
Flexible(
child: ListView(
children: <Widget>[
for (final String fid in _families.keys)
ListTile(
title: Text(_families[fid]['name']),
onTap: () => context.go(context.namedLocation('family',
params: <String, String>{'fid': fid})),
)
],
),
),
],
),
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'A Screen',
),
BottomNavigationBarItem(
icon: Icon(Icons.business),
label: 'B Screen',
),
],
),
);
}
}
/// The screen that shows a list of persons in a family.
class FamilyScreen extends StatelessWidget {
/// Creates a [FamilyScreen].
const FamilyScreen({required this.fid, Key? key}) : super(key: key);
/// The id family to display.
final String fid;
@override
Widget build(BuildContext context) {
final Map<String, dynamic> people =
_families[fid]['people'] as Map<String, dynamic>;
return Scaffold(
appBar: AppBar(title: Text(_families[fid]['name'])),
body: ListView(
children: <Widget>[
for (final String pid in people.keys)
ListTile(
title: Text(people[pid]['name']),
onTap: () => context.go(context.namedLocation(
'person',
params: <String, String>{'fid': fid, 'pid': pid},
queryParams: <String, String>{'qid': 'quid'},
)),
),
],
),
);
}
}
/// The person screen.
class PersonScreen extends StatelessWidget {
/// Creates a [PersonScreen].
const PersonScreen({required this.fid, required this.pid, Key? key})
: super(key: key);
/// The id of family this person belong to.
final String fid;
/// The id of the person to be displayed.
final String pid;
@override
Widget build(BuildContext context) {
final Map<String, dynamic> family = _families[fid];
final Map<String, dynamic> person = family['people'][pid];
return Scaffold(
appBar: AppBar(title: Text(person['name'])),
body: Text(
'${person['name']} ${family['name']} is ${person['age']} years old'),
);
}
}
flutter doctor -v[✓] Flutter (Channel stable, 3.3.3, on macOS 12.6 21G115 darwin-x64, locale en-VN)
• Flutter version 3.3.3 on channel stable at /Users/huynq/Documents/GitHub/flutter
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision 18a827f393 (10 hours ago), 2022-09-28 10:03:14 -0700
• Engine revision 5c984c26eb
• Dart version 2.18.2
• DevTools version 2.15.0
[✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
• Android SDK at /Users/huynq/Library/Android/sdk
• Platform android-33, build-tools 31.0.0
• ANDROID_HOME = /Users/huynq/Library/Android/sdk
• Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 11.0.12+0-b1504.28-7817840)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 14.0.1)
• Xcode at /Applications/Xcode14.0.1.app/Contents/Developer
• Build 14A400
• CocoaPods version 1.11.3
[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio (version 2021.2)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 11.0.12+0-b1504.28-7817840)
[✓] IntelliJ IDEA Community Edition (version 2022.2.2)
• IntelliJ at /Applications/IntelliJ IDEA CE.app
• Flutter plugin version 70.0.5
• Dart plugin version 222.4167.21
[✓] IntelliJ IDEA Community Edition (version 2022.1.1)
• IntelliJ at /Users/huynq/Library/Application Support/JetBrains/Toolbox/apps/IDEA-C/ch-0/221.5591.52/IntelliJ IDEA CE.app
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
[✓] VS Code (version 1.71.2)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.48.0
[✓] Connected device (4 available)
• SM T225 (mobile) • R9JT3004VRJ • android-arm64 • Android 12 (API 31)
• iPhone 14 Pro Max (mobile) • 332079AF-E895-4685-910E-7B1E18B0C6B8 • ios • com.apple.CoreSimulator.SimRuntime.iOS-16-0 (simulator)
• macOS (desktop) • macos • darwin-x64 • macOS 12.6 21G115 darwin-x64
• Chrome (web) • chrome • web-javascript • Google Chrome 105.0.5195.125
[✓] HTTP Host Availability
• All required HTTP hosts are available
• No issues found!
[✓] Flutter (Channel master, 3.4.0-33.0.pre.69, on macOS 12.6 21G115 darwin-x64, locale en-VN)
• Flutter version 3.4.0-33.0.pre.69 on channel master at /Users/huynq/Documents/GitHub/flutter_master
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision 16046be55a (28 minutes ago), 2022-09-28 22:19:36 -0400
• Engine revision 38ac18460f
• Dart version 2.19.0 (build 2.19.0-252.0.dev)
• DevTools version 2.17.0
[✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
• Android SDK at /Users/huynq/Library/Android/sdk
• Platform android-33, build-tools 31.0.0
• ANDROID_HOME = /Users/huynq/Library/Android/sdk
• Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 11.0.12+0-b1504.28-7817840)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 14.0.1)
• Xcode at /Applications/Xcode14.0.1.app/Contents/Developer
• Build 14A400
• CocoaPods version 1.11.3
[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio (version 2021.2)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 11.0.12+0-b1504.28-7817840)
[✓] IntelliJ IDEA Community Edition (version 2022.2.2)
• IntelliJ at /Applications/IntelliJ IDEA CE.app
• Flutter plugin version 70.0.5
• Dart plugin version 222.4167.21
[✓] IntelliJ IDEA Community Edition (version 2022.1.1)
• IntelliJ at /Users/huynq/Library/Application Support/JetBrains/Toolbox/apps/IDEA-C/ch-0/221.5591.52/IntelliJ IDEA CE.app
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
[✓] VS Code (version 1.71.2)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.48.0
[✓] Connected device (4 available)
• SM T225 (mobile) • R9JT3004VRJ • android-arm64 • Android 12 (API 31)
• iPhone 14 Pro Max (mobile) • 332079AF-E895-4685-910E-7B1E18B0C6B8 • ios • com.apple.CoreSimulator.SimRuntime.iOS-16-0 (simulator)
• macOS (desktop) • macos • darwin-x64 • macOS 12.6 21G115 darwin-x64
• Chrome (web) • chrome • web-javascript • Google Chrome 105.0.5195.125
[✓] HTTP Host Availability
• All required HTTP hosts are available
• No issues found!
[✓] Flutter (Channel beta, 3.4.0-17.2.pre, on macOS 12.6 21G115 darwin-x64, locale en-VN)
• Flutter version 3.4.0-17.2.pre on channel beta at /Users/huynq/Documents/GitHub/flutter_beta
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision d6260f127f (5 days ago), 2022-09-21 13:33:49 -0500
• Engine revision 3950c6140a
• Dart version 2.19.0 (build 2.19.0-146.2.beta)
• DevTools version 2.16.0
[✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
• Android SDK at /Users/huynq/Library/Android/sdk
• Platform android-33, build-tools 31.0.0
• ANDROID_HOME = /Users/huynq/Library/Android/sdk
• Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 11.0.12+0-b1504.28-7817840)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 14.0)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Build 14A309
• CocoaPods version 1.11.3
[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio (version 2021.2)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 11.0.12+0-b1504.28-7817840)
[✓] IntelliJ IDEA Community Edition (version 2022.1.1)
• IntelliJ at /Users/huynq/Library/Application Support/JetBrains/Toolbox/apps/IDEA-C/ch-0/221.5591.52/IntelliJ IDEA CE.app
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
[✓] VS Code (version 1.71.2)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.48.0
[✓] Connected device (3 available)
• SM T225 (mobile) • R9JT3004VRJ • android-arm64 • Android 12 (API 31)
• macOS (desktop) • macos • darwin-x64 • macOS 12.6 21G115 darwin-x64
• Chrome (web) • chrome • web-javascript • Google Chrome 105.0.5195.125
[✓] HTTP Host Availability
• All required HTTP hosts are available
• No issues found!
Labeling this issue for further investigation. Thank you! |
This is a framework issue related to #109624 I think we need to let focus traverse outside of the navigator. |
cc @craiglabenz |
There isn't any |
@gspencergoog yes I think we talked about this earlier that the ModalRoute is introducing one here
We should probably use a focus traversal group with a custom policy |
I am experiencing the same problem Sample codeimport 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:flutter/services.dart';
void main() async {
runApp(const MainApp());
}
// some extensions for tabs
class ScaffoldWithBottomNavBarTabItem extends BottomNavigationBarItem {
final String initialLocation;
const ScaffoldWithBottomNavBarTabItem(
{required this.initialLocation, required Widget icon, String? label})
: super(icon: icon, label: label);
}
class ScaffoldWithSideNavBarTabItem extends NavigationRailDestination {
final String initialLocation;
const ScaffoldWithSideNavBarTabItem(
{required this.initialLocation, required Widget icon, required Widget selectedIcon, required Widget label})
: super(icon: icon, selectedIcon: selectedIcon, label: label);
}
// tabs
const bottom_nav_bar_tabs = [
ScaffoldWithBottomNavBarTabItem(
initialLocation: '/',
icon: Icon(Icons.home),
label: 'Page1',
),
ScaffoldWithBottomNavBarTabItem(
initialLocation: '/page2',
icon: Icon(Icons.forum),
label: 'Page2',
),
ScaffoldWithBottomNavBarTabItem(
initialLocation: '/page3',
icon: Icon(Icons.search),
label: 'Page3',
),
];
const side_nav_bar_tabs = [
ScaffoldWithSideNavBarTabItem(
initialLocation: '/',
icon: Icon(Icons.home),
selectedIcon: Icon(Icons.home),
label: Text('Page1'),
),
ScaffoldWithSideNavBarTabItem(
initialLocation: '/page2',
icon: Icon(Icons.forum),
selectedIcon: Icon(Icons.forum),
label: Text('Page2'),
),
ScaffoldWithSideNavBarTabItem(
initialLocation: '/page3',
icon: Icon(Icons.search),
selectedIcon: Icon(Icons.search),
label: Text('Page 3'),
),
];
int currentIndex(BuildContext context, List tabs) {
String loc = GoRouterState.of(context).location;
int index = tabs.indexWhere((t) => t.initialLocation.startsWith(loc));
if (index < 0) {
if (loc.startsWith('/user')) {
return tabs.indexWhere((t) => t.initialLocation.endsWith('/user'));
} else if (loc.startsWith('/anime')) {
return tabs.indexWhere((t) => t.initialLocation.endsWith('/browse'));
} else if (loc.startsWith('/browse')) {
return tabs.indexWhere((t) => t.initialLocation.endsWith('/browse'));
} else if (loc.startsWith('/forum')) {
return tabs.indexWhere((t) => t.initialLocation.endsWith('/forum'));
} else {
return 0;
}
} else {
return index;
}
}
void onItemTapped(BuildContext context, List tabs, int tabIndex) {
if (tabIndex != currentIndex) {
context.go(tabs[tabIndex].initialLocation);
}
}
// bottom nav bar
class ScaffoldWithBottomNavbar extends StatelessWidget {
final Widget child;
const ScaffoldWithBottomNavbar({super.key, required this.child});
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Error sample app'),
actions: [
IconButton(
icon: Icon(Icons.search),
onPressed: () => context.goNamed('page3'),
),
]
),
body: child,
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
showSelectedLabels: false,
showUnselectedLabels: false,
currentIndex: currentIndex(context, bottom_nav_bar_tabs),
onTap: (index) => onItemTapped(context, bottom_nav_bar_tabs, index),
items: bottom_nav_bar_tabs,
),
);
}
}
// nav rail
class ScaffoldWithSideNavbar extends StatelessWidget {
final Widget child;
const ScaffoldWithSideNavbar({super.key, required this.child});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Error sample app'),
actions: [
IconButton(
icon: Icon(Icons.search),
onPressed: () => context.goNamed('page3'),
),
]
),
body: Row(
children: [
NavigationRail(
destinations: side_nav_bar_tabs,
selectedIndex: currentIndex(context, side_nav_bar_tabs),
onDestinationSelected: (int index) => onItemTapped(context, side_nav_bar_tabs, index),
groupAlignment: 0.0,
//labelType: NavigationRailLabelType.none,
),
Expanded(
child: child,
),
],
),
);
}
}
// get screen according to screen size
return_screen(BuildContext context, Widget child) {
var device_width = MediaQuery.of(context).size.width;
if (device_width <= 600) {
return ScaffoldWithBottomNavbar(child: child);
} else {
return ScaffoldWithSideNavbar(child: child);
}
}
// router
final router_data = GoRouter(
initialLocation: '/',
routes: <RouteBase>[
ShellRoute(
builder: (context, state, child) {
return return_screen(context, child);
},
routes: <RouteBase>[
GoRoute(
name: 'page1',
path: '/',
builder: (context, state) => Page1(),
),
GoRoute(
name: 'page2',
path: '/page2',
builder: (context, state) => Page2(),
),
GoRoute(
name: 'page3',
path: '/page3',
builder: (context, state) => Page3(),
),
],
),
],
);
// pages
class Page1 extends StatelessWidget {
const Page1({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Row(
children: [
Text('Page 1'),
ElevatedButton(
onPressed: () => print('user pressed btn 1'),
child: Text('btn 1'),
),
ElevatedButton(
onPressed: () => print('user pressed btn 2'),
child: Text('btn 2'),
),
ElevatedButton(
onPressed: () => print('user pressed btn 3'),
child: Text('btn 3'),
),
],
),
),
);
}
}
class Page2 extends StatelessWidget {
const Page2({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: ScaffoldWithSideNavbar(
child: Row(
children: [
Text('Page 2'),
ElevatedButton(
onPressed: () => print('user pressed btn 1'),
child: Text('btn 1'),
),
ElevatedButton(
onPressed: () => print('user pressed btn 2'),
child: Text('btn 2'),
),
ElevatedButton(
onPressed: () => print('user pressed btn 3'),
child: Text('btn 3'),
),
],
),
),
);
}
}
class Page3 extends StatelessWidget {
const Page3({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Row(
children: [
Text('Page 3'),
ElevatedButton(
onPressed: () => print('user pressed btn 1'),
child: Text('btn 1'),
),
ElevatedButton(
onPressed: () => print('user pressed btn 2'),
child: Text('btn 2'),
),
ElevatedButton(
onPressed: () => print('user pressed btn 3'),
child: Text('btn 3'),
),
Text('Please help me get over this problem'),
],
),
),
);
}
}
class LeftIntent extends Intent {}
class RightIntent extends Intent {}
class UpIntent extends Intent {}
class DownIntent extends Intent {}
class ActionIntent extends Intent {}
class MainApp extends StatelessWidget {
const MainApp({super.key});
@override
Widget build(BuildContext context) {
return Shortcuts(
shortcuts: <LogicalKeySet, Intent>{
LogicalKeySet(LogicalKeyboardKey.select): const ActivateIntent(), // OR could be : ActionIntent(),
LogicalKeySet(LogicalKeyboardKey.arrowUp): UpIntent(),
LogicalKeySet(LogicalKeyboardKey.arrowDown): DownIntent(),
LogicalKeySet(LogicalKeyboardKey.arrowLeft): LeftIntent(),
LogicalKeySet(LogicalKeyboardKey.arrowRight): RightIntent(),
},
child: MaterialApp.router(
title: 'Error sample app',
debugShowCheckedModeBanner: false,
routerConfig: router_data,
),
);
}
} |
This comment was marked as duplicate.
This comment was marked as duplicate.
This comment was marked as duplicate.
This comment was marked as duplicate.
thanks |
@huycozy i tried it but it did'nt work |
@huycozy Also you are not using a shell route |
Here is the code Edited codeimport 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:flutter/services.dart';
void main() async {
runApp(const MainApp());
}
// some extensions for tabs
class ScaffoldWithBottomNavBarTabItem extends BottomNavigationBarItem {
final String initialLocation;
const ScaffoldWithBottomNavBarTabItem(
{required this.initialLocation, required Widget icon, String? label})
: super(icon: icon, label: label);
}
class ScaffoldWithSideNavBarTabItem extends NavigationRailDestination {
final String initialLocation;
const ScaffoldWithSideNavBarTabItem(
{required this.initialLocation, required Widget icon, required Widget selectedIcon, required Widget label})
: super(icon: icon, selectedIcon: selectedIcon, label: label);
}
// tabs
const bottom_nav_bar_tabs = [
ScaffoldWithBottomNavBarTabItem(
initialLocation: 'page1',
icon: Icon(Icons.home),
label: 'Page1',
),
ScaffoldWithBottomNavBarTabItem(
initialLocation: 'page2',
icon: Icon(Icons.forum),
label: 'Page2',
),
ScaffoldWithBottomNavBarTabItem(
initialLocation: 'page3',
icon: Icon(Icons.search),
label: 'Page3',
),
];
const side_nav_bar_tabs = [
ScaffoldWithSideNavBarTabItem(
initialLocation: 'page1',
icon: Icon(Icons.home),
selectedIcon: Icon(Icons.home),
label: Text('Page1'),
),
ScaffoldWithSideNavBarTabItem(
initialLocation: 'page2',
icon: Icon(Icons.forum),
selectedIcon: Icon(Icons.forum),
label: Text('Page2'),
),
ScaffoldWithSideNavBarTabItem(
initialLocation: 'page3',
icon: Icon(Icons.search),
selectedIcon: Icon(Icons.search),
label: Text('Page 3'),
),
];
int currentIndex(BuildContext context, List tabs) {
String loc = GoRouterState.of(context).location;
int index = tabs.indexWhere((t) => t.initialLocation.startsWith(loc));
if (index < 0) {
return 0;
} else {
return index;
}
}
void onItemTapped(BuildContext context, List tabs, int tabIndex) {
if (tabIndex != currentIndex) {
context.go(context.namedLocation(tabs[tabIndex].initialLocation));
}
}
// bottom nav bar
class ScaffoldWithBottomNavbar extends StatelessWidget {
final Widget child;
const ScaffoldWithBottomNavbar({super.key, required this.child});
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Error sample app'),
actions: [
IconButton(
icon: Icon(Icons.search),
onPressed: () => context.goNamed('page3'),
),
]
),
body: child,
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
showSelectedLabels: false,
showUnselectedLabels: false,
currentIndex: currentIndex(context, bottom_nav_bar_tabs),
onTap: (index) => onItemTapped(context, bottom_nav_bar_tabs, index),
items: bottom_nav_bar_tabs,
),
);
}
}
// nav rail
class ScaffoldWithSideNavbar extends StatelessWidget {
final Widget child;
const ScaffoldWithSideNavbar({super.key, required this.child});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Error sample app'),
actions: [
IconButton(
icon: Icon(Icons.search),
onPressed: () => context.goNamed('page3'),
),
]
),
body: Row(
children: [
NavigationRail(
destinations: side_nav_bar_tabs,
selectedIndex: currentIndex(context, side_nav_bar_tabs),
onDestinationSelected: (int index) => onItemTapped(context, side_nav_bar_tabs, index),
groupAlignment: 0.0,
//labelType: NavigationRailLabelType.none,
),
Expanded(
child: child,
),
],
),
);
}
}
// get screen according to screen size
return_screen(BuildContext context, Widget child) {
var device_width = MediaQuery.of(context).size.width;
if (device_width <= 600) {
return ScaffoldWithBottomNavbar(child: child);
} else {
return ScaffoldWithSideNavbar(child: child);
}
}
// router
final router_data = GoRouter(
initialLocation: '/',
routes: <RouteBase>[
ShellRoute(
builder: (context, state, child) {
return return_screen(context, child);
},
routes: <RouteBase>[
GoRoute(
name: 'page1',
path: '/',
builder: (context, state) => Page1(),
),
GoRoute(
name: 'page2',
path: '/page2',
builder: (context, state) => Page2(),
),
GoRoute(
name: 'page3',
path: '/page3',
builder: (context, state) => Page3(),
),
],
),
],
);
// pages
class Page1 extends StatelessWidget {
const Page1({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Row(
children: [
Text('Page 1'),
ElevatedButton(
onPressed: () => print('user pressed btn 1'),
child: Text('btn 1'),
),
ElevatedButton(
onPressed: () => print('user pressed btn 2'),
child: Text('btn 2'),
),
ElevatedButton(
onPressed: () => print('user pressed btn 3'),
child: Text('btn 3'),
),
],
),
),
);
}
}
class Page2 extends StatelessWidget {
const Page2({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: ScaffoldWithSideNavbar(
child: Row(
children: [
Text('Page 2'),
ElevatedButton(
onPressed: () => print('user pressed btn 1'),
child: Text('btn 1'),
),
ElevatedButton(
onPressed: () => print('user pressed btn 2'),
child: Text('btn 2'),
),
ElevatedButton(
onPressed: () => print('user pressed btn 3'),
child: Text('btn 3'),
),
],
),
),
);
}
}
class Page3 extends StatelessWidget {
const Page3({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Row(
children: [
Text('Page 3'),
ElevatedButton(
onPressed: () => print('user pressed btn 1'),
child: Text('btn 1'),
),
ElevatedButton(
onPressed: () => print('user pressed btn 2'),
child: Text('btn 2'),
),
ElevatedButton(
onPressed: () => print('user pressed btn 3'),
child: Text('btn 3'),
),
Text('Please help me get over this problem'),
],
),
),
);
}
}
class LeftIntent extends Intent {}
class RightIntent extends Intent {}
class UpIntent extends Intent {}
class DownIntent extends Intent {}
class ActionIntent extends Intent {}
class MainApp extends StatelessWidget {
const MainApp({super.key});
@override
Widget build(BuildContext context) {
return Shortcuts(
shortcuts: <LogicalKeySet, Intent>{
LogicalKeySet(LogicalKeyboardKey.select): const ActivateIntent(), // OR could be : ActionIntent(),
LogicalKeySet(LogicalKeyboardKey.arrowUp): UpIntent(),
LogicalKeySet(LogicalKeyboardKey.arrowDown): DownIntent(),
LogicalKeySet(LogicalKeyboardKey.arrowLeft): LeftIntent(),
LogicalKeySet(LogicalKeyboardKey.arrowRight): RightIntent(),
},
child: MaterialApp.router(
title: 'Error sample app',
debugShowCheckedModeBanner: false,
routerConfig: router_data,
),
);
}
} |
@chunhtai @gspencergoog Please help |
any solution to this, cant seem to focus on widgets in the shellroute widget |
add to P0 as internal bug is P2 |
Our new priority scheme is shifted by two from our old priority scheme which I believe means it is now consistent with Google's internal bug priority scheme. |
#130841) …t trap the focus fixes #112567 Several things I done: 1. add new enum `parentScope` 2. refactor _sortAllDescendants so that it doesn't recursively looking into its descendant when it encounter a FocusScopeNode. 3. When the nextFocus try to focus into a FocusScopeNode, it will try to find the first focusable FocusNode in traversal order and focus it instead if it doesn't have a first focus. 4. Change the default in Navigator to always be `parentScope` 5. Only the root navigator will use `leaveFlutterView` if platform is web. Previously 2 and 3 are not needed because once a focusscope trapped the focus, there isn't a chance where the parent focusscope have to deal with next focus. If we don't do 2 and 3 after the change, it will cause it to stuck in the current scope again. Because once the focus leave the current scope, it needs to also remove the first focus in that scope (so that it can start fresh when focus traversal back to the scope in the future). At this point the current scope will have the primary focus without the first focus. The parent scope will then try to find the next focus, and it will place the focus to the first traversal child in the current scope again. ## Pre-launch Checklist - [ ] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [ ] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [ ] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [ ] I signed the [CLA]. - [ ] I listed at least one issue that this PR fixes in the description above. - [ ] I updated/added relevant documentation (doc comments with `///`). - [ ] I added new tests to check the change I am making, or this PR is [test-exempt]. - [ ] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/wiki/Tree-hygiene#overview [Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene [test-exempt]: https://github.com/flutter/flutter/wiki/Tree-hygiene#tests [Flutter Style Guide]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo [Features we expect every widget to implement]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/wiki/Chat
Looks like #130841 got reverted, can this issue be reopened? |
#134554) …… (#134550)" fixes #112567 This reverts commit 5900c4b. The internal test needs migration. cl/564746935 This is the same of original pr, no new change ## Pre-launch Checklist - [ ] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [ ] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [ ] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [ ] I signed the [CLA]. - [ ] I listed at least one issue that this PR fixes in the description above. - [ ] I updated/added relevant documentation (doc comments with `///`). - [ ] I added new tests to check the change I am making, or this PR is [test-exempt]. - [ ] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/wiki/Tree-hygiene#overview [Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene [test-exempt]: https://github.com/flutter/flutter/wiki/Tree-hygiene#tests [Flutter Style Guide]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo [Features we expect every widget to implement]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/wiki/Chat
flutter#134554) …… (flutter#134550)" fixes flutter#112567 This reverts commit 5900c4b. The internal test needs migration. cl/564746935 This is the same of original pr, no new change ## Pre-launch Checklist - [ ] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [ ] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [ ] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [ ] I signed the [CLA]. - [ ] I listed at least one issue that this PR fixes in the description above. - [ ] I updated/added relevant documentation (doc comments with `///`). - [ ] I added new tests to check the change I am making, or this PR is [test-exempt]. - [ ] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/wiki/Tree-hygiene#overview [Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene [test-exempt]: https://github.com/flutter/flutter/wiki/Tree-hygiene#tests [Flutter Style Guide]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo [Features we expect every widget to implement]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/wiki/Chat
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of |
b/231967193
Steps to Reproduce
This is the ShellRoute example code from go_router with a couple extra controls to demonstrate the focus issues.
Expected results: '
Focus changes
Actual results:
Focus does NOT change
This is using Beta which has the PR #109702 merged.
Code sample
Logs
The text was updated successfully, but these errors were encountered: