Flutter中如何点击按钮切换NavigationBar的当前页面?
实现Flutter导航栏标签页与弹窗按钮的页面切换
我有一个包含3个标签页的NavigationBar,需求是点击弹窗中的按钮时,切换到指定的标签页(购物车页面,即第三个标签页)。以下是相关代码:
Home类导航栏代码
body: IndexedStack( index: currentPageIndex, children: <Widget>[ const ShopPage(), QRScanner(showTab2: () { setState(() { setState(() { currentPageIndex = 2; }); }); }), const ShopListPage(), ], ), bottomNavigationBar: NavigationBar( elevation: 2, labelBehavior: NavigationDestinationLabelBehavior.onlyShowSelected, selectedIndex: currentPageIndex, onDestinationSelected: (int index) { setState(() => currentPageIndex = index); }, destinations: const [ NavigationDestination( icon: Icon(Icons.store_outlined), selectedIcon: Icon(Icons.store), label: 'Tienda', ), NavigationDestination( icon: Icon(Icons.qr_code_scanner_outlined), selectedIcon: Icon(Icons.qr_code_scanner), label: 'Escaner', ), NavigationDestination( icon: Icon(Icons.shopping_cart_outlined), selectedIcon: Icon(Icons.shopping_cart), label: 'Carrito', ), ], ),
QRScanner页面弹窗函数代码
void onQRViewCreated(QRViewController controller) { setState(() { this.controller = controller; }); controller.scannedDataStream.listen((scanData) { setState(() { result = scanData; }); controller.pauseCamera(); Stream<List<Products>> readProducts() => FirebaseFirestore.instance .collection('products') .where('id', isEqualTo: '${result!.code}') .snapshots() .map((snapshot) => snapshot.docs .map((doc) => Products.fromJson(doc.data())) .toList()); Future<bool> onWillPop() async { return false; } showDialog( barrierDismissible: false, context: context, builder: (BuildContext context) => WillPopScope( onWillPop: () async => false, child: WillPopScope( onWillPop: onWillPop, child: Dialog( insetPadding: const EdgeInsets.all(8), child: StreamBuilder<List<Products>>( stream: readProducts(), builder: (context, snapshot) { if (snapshot.hasError) { return Text('Algo ha ocurrido! ${snapshot.error}'); } else if (snapshot.hasData) { final products = snapshot.data!; return Container( margin: const EdgeInsets.all(8), child: Column( mainAxisSize: MainAxisSize.min, children: products .map((p) => BuildQRCards( // 此类包含需触发页面切换的按钮 products: p, controller: controller,)) .toList()), ); } else { return const Center(child: CircularProgressIndicator()); } }), ), ), ), ); }); }
BuildQRCard类代码
class _BuildQRCardsState extends State<BuildQRCards> { @override Widget build(BuildContext context) { return Card( clipBehavior: Clip.antiAlias, child: SizedBox( width: 300, child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ Image(image: NetworkImage(widget.products.imageUrl)), ListTile( title: Text(widget.products.name), subtitle: Text('Precio: ${widget.products.price}\$'), ), Row( mainAxisAlignment: MainAxisAlignment.end, children: [ Padding( padding: const EdgeInsets.fromLTRB(0, 0, 8, 8), child: ElevatedButton( style: ButtonStyle( foregroundColor: MaterialStateProperty.all<Color>( const Color(0xFFFFFFFF), ), backgroundColor: MaterialStateProperty.all<Color>( const Color(0xFF6750A4), ), ), onPressed: () { Navigator.pop(context); widget.controller!.resumeCamera(); }, child: const Text( 'Cancelar', ), ), ), Padding( padding: const EdgeInsets.fromLTRB(0, 0, 8, 8), child: ElevatedButton( style: ButtonStyle( foregroundColor: MaterialStateProperty.all<Color>( const Color(0xFFFFFFFF), ), backgroundColor: MaterialStateProperty.all<Color>( const Color(0xFF6750A4), ), ), onPressed: () => showDialog( context: context, barrierDismissible: false, builder: (BuildContext context) => AlertDialog( content: Text( '¿Desea añadir el producto ${widget.products.name} a la lista de compras?', textAlign: TextAlign.center, ), actions: <Widget>[ TextButton( onPressed: () { Navigator.pop(context); }, child: const Text('Cancelar')), TextButton( onPressed: () { passID(widget.products.id); widget.controller!.resumeCamera(); }, child: const Text('Añadir'), ), ], ), ), child: const Text( 'Añadir al Carro', ), ), ), ], ), ], ), ), ); } }
解决方案
通过回调函数传递实现弹窗按钮触发标签页切换,步骤如下:
更新Home类中QRScanner的初始化
添加切换到购物车的回调,简化原有的嵌套setState:QRScanner( showTab2: () { setState(() { currentPageIndex = 2; }); }, // 新增切换到购物车的回调 switchToCart: () { setState(() { currentPageIndex = 2; }); }, ),修改QRScanner类的定义
添加switchToCart回调参数,并传递给BuildQRCards:class QRScanner extends StatefulWidget { final VoidCallback showTab2; final VoidCallback switchToCart; // 新增参数 const QRScanner({super.key, required this.showTab2, required this.switchToCart}); @override State<QRScanner> createState() => _QRScannerState(); }在创建BuildQRCards时传递回调:
BuildQRCards( products: p, controller: controller, switchToCart: widget.switchToCart, // 传递回调 )修改BuildQRCards类的定义
添加switchToCart回调参数,并在确认添加产品时触发:class BuildQRCards extends StatefulWidget { final Products products; final QRViewController? controller; final VoidCallback switchToCart; // 新增参数 const BuildQRCards({super.key, required this.products, this.controller, required this.switchToCart}); @override State<BuildQRCards> createState() => _BuildQRCardsState(); }更新确认按钮的逻辑
在"Añadir"按钮的onPressed中,关闭所有弹窗并触发标签页切换:TextButton( onPressed: () { passID(widget.products.id); widget.controller!.resumeCamera(); // 关闭确认弹窗 Navigator.pop(context); // 关闭产品详情弹窗 Navigator.pop(context); // 触发切换到购物车标签页 widget.switchToCart(); }, child: const Text('Añadir'), ),
内容的提问来源于stack exchange,提问作者Willders Carvajal
相关产品推荐
相关产品推荐

