Home > other >  Change pages of my navigation bar pressing a button
Change pages of my navigation bar pressing a button

Time:08-31

I have a NavigationBar with 3 tabs and i want to change the current tab or destination when i push on a button.

The navigation bar:

bottomNavigationBar: NavigationBar(
    elevation: 2,
    labelBehavior: NavigationDestinationLabelBehavior.onlyShowSelected,
    selectedIndex: index,
    onDestinationSelected: (index) {
      setState(() => this.index = 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',
      ),
    ],
  ),

The class with button:

class BuildQRCards extends StatefulWidget {
  final Products products;
  final QRViewController? controller;

  const BuildQRCards({
    required this.products,
    this.controller,
    Key? key,
  }) : super(key: key);

  @override
  State<BuildQRCards> createState() => _BuildQRCardsState();
}

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();
                              setState(() {
                                setState(() => this.index = 2);
                              });
                            },
                            child: const Text('Añadir'),
                          ),
                        ],
                      ),
                    ),
                    child: const Text(
                      'Añadir al Carro',
                    ),
                  ),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

Where the dialog shows up when a qr its scanned

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());
                }
              }),
        ),
      ),
    ),
  );
});
}

The shoppage class:

String productid = '';

void passID(String? id) {
  id = productid;
}

Stream<List<Products>> readProducts() => FirebaseFirestore.instance
    .collection('products')
    .where('id', isEqualTo: productid)
    .snapshots()
    .map((snapshot) =>
        snapshot.docs.map((doc) => Products.fromJson(doc.data())).toList());

class ShopListPage extends StatefulWidget {
  const ShopListPage({super.key});

  @override
  State<ShopListPage> createState() => _ShopListPageState();
}

class _ShopListPageState extends State<ShopListPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Theme.of(context).colorScheme.background,
      body: 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 ListView(
                  children: products
                      .map((p) => BuildListCards(products: p))
                      .toList());
            } else {
              return const Center(child: CircularProgressIndicator());
            }
          }),
      floatingActionButton: FloatingActionButton(
        child: const Icon(
          Icons.paid,
        ),
        onPressed: () {},
      ),
    );
  }
}

CodePudding user response:

new answer

This has two approaches Using a function and using result from navigator.pop

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(home: NavigationExample());
  }
}

class NavigationExample extends StatefulWidget {
  const NavigationExample({super.key});

  @override
  State<NavigationExample> createState() => _NavigationExampleState();
}

class _NavigationExampleState extends State<NavigationExample> {
  int currentPageIndex = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      bottomNavigationBar: NavigationBar(
        onDestinationSelected: (int index) {
          setState(() {
            currentPageIndex = index;
          });
        },
        selectedIndex: currentPageIndex,
        destinations: const <Widget>[
          NavigationDestination(
            icon: Icon(Icons.explore),
            label: 'Explore',
          ),
          NavigationDestination(
            icon: Icon(Icons.commute),
            label: 'Commute',
          ),
          NavigationDestination(
            selectedIcon: Icon(Icons.bookmark),
            icon: Icon(Icons.bookmark_border),
            label: 'Saved',
          ),
        ],
      ),
      body: <Widget>[
        MyPage1(
          showTab2: () {
            // how to use a function when they are in the same tab list
            setState(() {
              setState(() {
                currentPageIndex = 2;
              });
            });
          },
        ),
        Container(
          color: Colors.green,
          alignment: Alignment.center,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const Text('Page 2'),
              TextButton(
                  onPressed: () async {
                    // how to use the result
                    final int? result =
                        await Navigator.push(context, MaterialPageRoute(
                      builder: (context) {
                        return MyNewPage();
                      },
                    ));

                    if (result != null) {
                      setState(() {
                        currentPageIndex = result;
                      });
                    }
                  },
                  child: Text("new page"))
            ],
          ),
        ),
        Container(
          color: Colors.blue,
          alignment: Alignment.center,
          child: const Text('Page 3'),
        ),
      ][currentPageIndex],
    );
  }
}

class MyPage1 extends StatelessWidget {
  final Function showTab2;
  const MyPage1({Key? key, required this.showTab2}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.red,
      alignment: Alignment.center,
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          const Text('Page 1'),
          TextButton(
              onPressed: () {
                showTab2();
              },
              child: Text("Show tab 3"))
        ],
      ),
    );
  }
}

class MyNewPage extends StatelessWidget {
  const MyNewPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
          child: Center(
        child: TextButton(
          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);
                      Navigator.pop(context);
                    },
                    child: const Text('Cancelar')),
                TextButton(
                  onPressed: () {
                    // passID(widget.products.id);
                    // widget.controller!.resumeCamera();
                    Navigator.pop(context);
                    Navigator.pop(context, 0);
                  },
                  child: const Text('Añadir'),
                ),
              ],
            ),
          ),
          child: Text("Show dialog"),
        ),
      )),
    );
  }
}

/// END OF NEW ANSWER

//old answer This line is what changes the tabs

 setState(() {
    setState(() => this.index = index);
  });

Hence if you want to change the tab through a different button just add something like this

 setState(() {
    setState(() => this.index = newTabIndex);
  });

where newTabIndex is the index of the tap you want to

in your case, you might have something like this

TextButton(
  onPressed: () {
    passID(products.id);
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (BuildContext context) =>
        BuildListCards(
          products: products)));
    controller!.resumeCamera();
    setState(() {
      setState(() => this.index = 1); // I am assuming 1 is the index of the tab you want to show
    });
  },
  child: const Text('Añadir')),
  • Related