CupertinoTabBar를 사용하여 다른 탭에서 다른 페이지로 이동하는 방법은 무엇입니까?

Aug 21 2020

Tab1과 Tab2의 두 개의 탭이 있습니다. Tab1에는 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');
            },
          )
        ],
      ),
    );
  }
}