Как перейти на другую страницу на другой вкладке с помощью CupertinoTabBar?
Aug 21 2020
У меня две вкладки - Tab1 и Tab2. Tab1 имеет 3 страницы - Tab1 Page1, Tab1 Page2, Tab1 Page3.
Я хочу иметь возможность переходить с Tab2 на Tab1 Page2. Я могу переключить индекс с помощью, controller.index = 0
но не знаю, как перейти на страницу 2 этой вкладки. Какое чистое решение для этого?

// main.dart
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Cupertino Tab Bar Demo',
theme: ThemeData(primarySwatch: Colors.blue, textTheme: TextTheme()),
home: SafeArea(child: Scaffold(body: MyHomePage('Cupertino Tab Bar Demo Home Page'))),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage(this.title);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var navigatorKeyList = [GlobalKey<NavigatorState>(), GlobalKey<NavigatorState>()];
var currentIndex = 0;
var controller = CupertinoTabController(initialIndex: 0);
@override
Widget build(BuildContext context) {
return CupertinoTabScaffold(
controller: controller,
tabBar: CupertinoTabBar(
onTap: (index) {
if (currentIndex == index) {
// Navigate to the tab's root route
navigatorKeyList[index].currentState.popUntil((route) {
return route.isFirst;
});
}
currentIndex = index;
},
items: [
BottomNavigationBarItem(title: Text('Tab 1'), icon: Icon(Icons.ac_unit)),
BottomNavigationBarItem(title: Text('Tab 2'), icon: Icon(Icons.ac_unit)),
],
),
tabBuilder: (BuildContext _, int index) {
switch (index) {
case 0:
return CupertinoTabView(
navigatorKey: navigatorKeyList[index],
routes: {
'/': (context) => WillPopScope(
child: Page1(),
onWillPop: () => Future<bool>.value(true),
),
'page1b': (context) => Page1b(),
'page1c': (context) => Page1c(),
},
);
case 1:
return CupertinoTabView(
navigatorKey: navigatorKeyList[index],
routes: {
'/': (context) => WillPopScope(
child: Page2(controller),
onWillPop: () => Future<bool>.value(true),
)
},
);
default:
return Text('Index must be less than 2');
}
},
);
}
}
// Tab1 Page1
class Page1 extends StatelessWidget {
Page1();
@override
Widget build(BuildContext context) {
return BaseContainer(
Column(
children: <Widget>[
Container(
child: Text(
'Tab1',
style: Theme.of(context).textTheme.headline4,
),
),
FlatButton(
color: Colors.lightGreen,
child: Text('Go to Tab1 Page2'),
onPressed: () {
Navigator.pushNamed(context, 'page1b');
},
)
],
),
);
}
}
// Tab1 Page2
class Page1b extends StatelessWidget {
Page1b();
@override
Widget build(BuildContext context) {
return BaseContainer(
Column(
children: <Widget>[
Container(
child:
Text('Tab1 Page2', style: Theme.of(context).textTheme.headline4),
),
FlatButton(
color: Colors.lightGreen,
child: Text('Go to Tab1 Page3'),
onPressed: () {
Navigator.pushNamed(context, 'page1c');
},
)
],
),
);
}
}
// Tab2
class Page2 extends StatelessWidget {
final CupertinoTabController controller;
const Page2(this.controller);
@override
Widget build(BuildContext context) {
return BaseContainer(
Column(
children: <Widget>[
Container(
child: Text(
'Tab2',
style: Theme.of(context).textTheme.headline4,
),
),
FlatButton(
color: Colors.lightGreen,
child: Text('Go to Tab1 Page2 (TODO)'),
onPressed: () {
// TODO I want this to go to Tab1 Page2
this.controller.index = 0;
Navigator.of(context).pushNamed('page1b');
},
)
],
),
);
}
}
Ответы
2 chunhunghan Aug 21 2020 at 06:02
Вы можете скопировать и вставить полный код ниже
Шаг 1: Вы можете перейти navigatorKeyList[0])
к Page2
Шагу 2: вызовите navigatorKey.currentState.pushNamed("page1b");
и изменитеindex
фрагмент кода
return CupertinoTabView(
navigatorKey: navigatorKeyList[index],
routes: {
'/': (context) => WillPopScope(
child: Page2(controller, navigatorKeyList[0]),
onWillPop: () => Future<bool>.value(true),
)
},
);
...
class Page2 extends StatelessWidget {
final CupertinoTabController controller;
final GlobalKey<NavigatorState> navigatorKey;
const Page2(this.controller, this.navigatorKey);
...
FlatButton(
color: Colors.lightGreen,
child: Text('Go to Tab1 Page2 (TODO)'),
onPressed: () {
navigatorKey.currentState.pushNamed("page1b");
this.controller.index = 0;
},
)
рабочая демонстрация

полный код
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Cupertino Tab Bar Demo',
theme: ThemeData(primarySwatch: Colors.blue, textTheme: TextTheme()),
home: SafeArea(
child:
Scaffold(body: MyHomePage('Cupertino Tab Bar Demo Home Page'))),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage(this.title);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var navigatorKeyList = [
GlobalKey<NavigatorState>(),
GlobalKey<NavigatorState>()
];
var currentIndex = 0;
var controller = CupertinoTabController(initialIndex: 0);
@override
Widget build(BuildContext context) {
return CupertinoTabScaffold(
controller: controller,
tabBar: CupertinoTabBar(
onTap: (index) {
if (currentIndex == index) {
// Navigate to the tab's root route
navigatorKeyList[index].currentState.popUntil((route) {
return route.isFirst;
});
}
currentIndex = index;
},
items: [
BottomNavigationBarItem(
title: Text('Tab 1'), icon: Icon(Icons.ac_unit)),
BottomNavigationBarItem(
title: Text('Tab 2'), icon: Icon(Icons.ac_unit)),
],
),
tabBuilder: (BuildContext _, int index) {
switch (index) {
case 0:
return CupertinoTabView(
navigatorKey: navigatorKeyList[index],
routes: {
'/': (context) => WillPopScope(
child: Page1(),
onWillPop: () => Future<bool>.value(true),
),
'page1b': (context) => Page1b(),
'page1c': (context) => Page1c(),
},
);
case 1:
return CupertinoTabView(
navigatorKey: navigatorKeyList[index],
routes: {
'/': (context) => WillPopScope(
child: Page2(controller, navigatorKeyList[0]),
onWillPop: () => Future<bool>.value(true),
)
},
);
default:
return Text('Index must be less than 2');
}
},
);
}
}
// Tab1 Page1
class Page1 extends StatelessWidget {
Page1();
@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Container(
child: Text(
'Tab1',
style: Theme.of(context).textTheme.headline4,
),
),
FlatButton(
color: Colors.lightGreen,
child: Text('Go to Tab1 Page2'),
onPressed: () {
Navigator.pushNamed(context, 'page1b');
},
)
],
),
);
}
}
// Tab1 Page2
class Page1b extends StatelessWidget {
Page1b();
@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Container(
child: Text('Tab1 Page2',
style: Theme.of(context).textTheme.headline4),
),
FlatButton(
color: Colors.lightGreen,
child: Text('Go to Tab1 Page3'),
onPressed: () {
Navigator.pushNamed(context, 'page1c');
},
)
],
),
);
}
}
class Page1c extends StatelessWidget {
Page1c();
@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Container(
child: Text('Tab1 Page2',
style: Theme.of(context).textTheme.headline4),
),
FlatButton(
color: Colors.lightGreen,
child: Text('Go to Tab1 Page3'),
onPressed: () {
Navigator.pushNamed(context, 'page1c');
},
)
],
),
);
}
}
// Tab2
class Page2 extends StatelessWidget {
final CupertinoTabController controller;
final GlobalKey<NavigatorState> navigatorKey;
const Page2(this.controller, this.navigatorKey);
@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Container(
child: Text(
'Tab2',
style: Theme.of(context).textTheme.headline4,
),
),
FlatButton(
color: Colors.lightGreen,
child: Text('Go to Tab1 Page2 (TODO)'),
onPressed: () {
navigatorKey.currentState.pushNamed("page1b");
this.controller.index = 0;
},
)
],
),
);
}
}
полный код 2
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Cupertino Tab Bar Demo',
theme: ThemeData(primarySwatch: Colors.blue, textTheme: TextTheme()),
home: SafeArea(
child:
Scaffold(body: MyHomePage('Cupertino Tab Bar Demo Home Page'))),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage(this.title);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var navigatorKeyList = [
GlobalKey<NavigatorState>(),
GlobalKey<NavigatorState>()
];
int currentIndex = 0;
var controller = CupertinoTabController(initialIndex: 0);
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return CupertinoTabScaffold(
controller: controller,
tabBar: CupertinoTabBar(
onTap: (index) {
if (currentIndex == index) {
// Navigate to the tab's root route
navigatorKeyList[index].currentState.popUntil((route) {
return route.isFirst;
});
}
currentIndex = index;
},
items: [
BottomNavigationBarItem(
title: Text('Tab 1'), icon: Icon(Icons.ac_unit)),
BottomNavigationBarItem(
title: Text('Tab 2'), icon: Icon(Icons.ac_unit)),
],
),
tabBuilder: (BuildContext _, int index) {
switch (index) {
case 0:
return CupertinoTabView(
navigatorKey: navigatorKeyList[index],
routes: {
'/': (context) => WillPopScope(
child: Page1(controller, navigatorKeyList[1]),
onWillPop: () => Future<bool>.value(true),
),
'page1b': (context) => Page1b(),
'page1c': (context) => Page1c(),
},
);
case 1:
return CupertinoTabView(
navigatorKey: navigatorKeyList[index],
routes: {
'/': (context) => WillPopScope(
child: Page2(controller, navigatorKeyList[0]),
onWillPop: () => Future<bool>.value(true),
)
},
);
default:
return Text('Index must be less than 2');
}
},
);
}
}
// Tab1 Page1
class Page1 extends StatelessWidget {
final CupertinoTabController controller;
final GlobalKey<NavigatorState> navigatorKey;
const Page1(this.controller, this.navigatorKey);
@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Container(
child: Text(
'Tab1',
style: Theme.of(context).textTheme.headline4,
),
),
FlatButton(
color: Colors.lightGreen,
child: Text('Go to Tab2 Page2'),
onPressed: () async {
controller.index = 1;
await Future.delayed(Duration(seconds: 1), () {});
navigatorKey.currentState.pushNamed("/");
},
)
],
),
);
}
}
// Tab1 Page2
class Page1b extends StatelessWidget {
Page1b();
@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Container(
child: Text('Tab1 Page2',
style: Theme.of(context).textTheme.headline4),
),
FlatButton(
color: Colors.lightGreen,
child: Text('Go to Tab1 Page3'),
onPressed: () {
Navigator.pushNamed(context, 'page1c');
},
)
],
),
);
}
}
class Page1c extends StatelessWidget {
Page1c();
@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Container(
child: Text('Tab1 Page2',
style: Theme.of(context).textTheme.headline4),
),
FlatButton(
color: Colors.lightGreen,
child: Text('Go to Tab1 Page3'),
onPressed: () {
Navigator.pushNamed(context, 'page1c');
},
)
],
),
);
}
}
// Tab2
class Page2 extends StatelessWidget {
final CupertinoTabController controller;
final GlobalKey<NavigatorState> navigatorKey;
const Page2(this.controller, this.navigatorKey);
@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Container(
child: Text(
'Tab2',
style: Theme.of(context).textTheme.headline4,
),
),
FlatButton(
color: Colors.lightGreen,
child: Text('Go to Tab1 Page2 (TODO)'),
onPressed: () async {
navigatorKey.currentState.pushNamed("page1b");
await Future.delayed(Duration(seconds: 1), () {});
this.controller.index = 0;
},
)
],
),
);
}
}
полный код 3
return CupertinoTabView(
navigatorKey: navigatorKeyList[index],
routes: {
'/': (context) => WillPopScope(
child: Page1(controller, navigatorKeyList),
onWillPop: () => Future<bool>.value(true),
),
'page2b': (context) => Page2b(),
'page3b': (context) => Page3b(),
},
);
...
import 'package:cupertino_tab_bar/base_widget.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class Page1 extends StatelessWidget {
final CupertinoTabController controller;
final List<GlobalKey<NavigatorState>> navigatorKeyList;
const Page1(this.controller, this.navigatorKeyList);
@override
Widget build(BuildContext context) {
return BaseContainer(
Column(
children: <Widget>[
Container(
child: Text(
'Tab1',
style: Theme.of(context).textTheme.headline4,
),
),
FlatButton(
color: Colors.lightGreen,
child: Text('Go to Tab2 Page2'),
onPressed: () async{
controller.index = 1;
await Future.delayed(Duration(seconds: 1), () {});
navigatorKeyList[1].currentState.pushNamed("page2b");
},
),
FlatButton(
color: Colors.lightGreen,
child: Text('Go to Tab3 Page2'),
onPressed: () async{
controller.index = 2;
await Future.delayed(Duration(seconds: 1), () {});
navigatorKeyList[2].currentState.pushNamed("page3b");Navigator.pushNamed(context, 'page3b');
},
)
],
),
);
}
}