Passing a value to the floating action button to be used in the bottom sheet

1,907

Solution 1

Remove the DefaultTabController widget and create your own TabController instead - this allows you to add a listener to the TabController which will be triggered every time the user navigates to a different tab. You can use this mechanism to get data associated to the index of the current tab, such as the type.

Here is the code you provided, with the modifications I mentioned above. The type is stored in the currentType variable, which you can use when tapping on the Fab.

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class TabScreen extends StatefulWidget {
  @override
  _TabScreenState createState() => _TabScreenState();
}

class _TabScreenState extends State<TabScreen> with SingleTickerProviderStateMixin {
  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
  TabController tabController;
  String currentType;

  @override
  Widget build(BuildContext context) {
    final bool showfab = MediaQuery.of(context).viewInsets.bottom == 0.0;
    final AuthService authService = Provider.of<AuthService>(context);

    return StreamBuilder<List<String>>(
      stream: forumServices.forumsTypes$,
      builder: (context, snapshot) {
        if (!snapshot.hasData) {
          return const CircularProgressIndicator();
        }
        List<String> types = snapshot.data;

        if (tabController == null) {
          currentType = types.first;

          tabController = TabController(length: types.length, vsync: this);
          tabController.addListener(() {
            currentType = types.elementAt(tabController.index);
          });
        }

        return Scaffold(
          key: _scaffoldKey,
          body: CustomScrollView(
            slivers: <Widget>[
              SliverAppBar(
                title: const Text("kdkdkkd"),
                bottom: TabBar(
                controller: tabController,
                tabs: types.map((String f) =>  Text(f)).toList()),
              ),
              SliverFillRemaining(
                child: StreamBuilder<List<Forums>>(
                  stream: forumServices.forums$,
                  builder: (context, snap) {
                    if (!snap.hasData) {
                      return const CircularProgressIndicator();
                    }
                    final forum = snap.data;

                    return TabBarView(
                      controller: tabController,
                      children: types.map((String type) {
                        List<Forums> listOfThisType = forum.where((Forums fo) => fo.type == type).toList();

                        return ListView(
                          children: listOfThisType.map((thisType) => ForumCard(
                            choosentype: thisType,
                            forumServices: forumServices,
                          )).toList(),
                        );
                      }).toList(),
                    );
                  },
                ),
              ),
            ],
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: () => _showBottom(),
            tooltip: 'Increment',
            child: const Icon(Icons.add),
          ),
        );
      },
    );
  }
}

Solution 2

class Screen extends StatelessWidget {
  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
  final GlobalKey<TabsWidgetState> _tabKey = GlobalKey<TabsWidgetState>();

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<List<String>>(
        future: Future.delayed(
            const Duration(seconds: 1), () => ["Forum", "Question"]),
        builder: (context, snapshot) {
          if (!snapshot.hasData) {
            return CircularProgressIndicator();
          }
          List<String> types = snapshot.data;
          num tabLen = types.length;

          return Scaffold(
              key: _scaffoldKey,
              body: TabsWidget(key: _tabKey, tabLen: tabLen, types: types),
              floatingActionButton: FloatingActionButton(
                onPressed: () => print(_tabKey.currentState.currentQuestion),
                tooltip: 'Increment',
                child: Icon(Icons.add),
              ));
        });
  }
}

class TabsWidget extends StatefulWidget {
  const TabsWidget({
    Key key,
    @required this.tabLen,
    @required this.types,
  }) : super(key: key);

  final num tabLen;
  final List<String> types;

  @override
  TabsWidgetState createState() => TabsWidgetState();
}

class TabsWidgetState extends State<TabsWidget> with SingleTickerProviderStateMixin{

   TabController _tabController;
   String currentQuestion;

  @override
  void initState() {
    _tabController = TabController(length: widget.tabLen, vsync: this)
    ..addListener(() {
      currentQuestion = widget.types[_tabController.index];
    });

  }

  @override
  Widget build(BuildContext context) {
    return CustomScrollView(slivers: <Widget>[
      SliverAppBar(
        title: Text("kdkdkkd"),
        bottom: TabBar(
            controller: _tabController,
            tabs: widget.types.map((String f) {
              return Text(f);
            }).toList()),
      ),
      SliverFillRemaining(
        child: FutureBuilder(
            future: Future.delayed(const Duration(seconds: 1),
                    () => ["Forum", "Question"]),
            builder: (context, snap) {
              if (!snap.hasData) {
                return CircularProgressIndicator();
              }
              final forum = snap.data;
              return TabBarView(
                controller: _tabController,
                children: widget.types.map((String type) {
                  List<String> listofthistype =
                  forum.where((String fo) {
                    return fo == type;
                  }).toList();

                  final cards = listofthistype
                      .map((thistype) => Text(thistype))
                      .toList();

                  return ListView(
                    children: cards,
                  );
                }).toList(),
              );
            }),
      ),
    ]);
  }
}

For simplicity used futureBuilder If your length of tabs aren't loaded from snapshot you can avoid using global key and just create tab controller at the very beginning.

Don't forget to do null checking. Fab will be shown before data is loaded.

Share:
1,907
Aya Elsisy
Author by

Aya Elsisy

Updated on December 11, 2022

Comments

  • Aya Elsisy
    Aya Elsisy over 1 year

    In this widget the tabs navigate between types if it is question it goes a specified screen. If it is forum it goes to another one. The problem is I need to pass the type of the current tap to the on pressed function in the floating action button. However Floating action button is outside the body of the scaffold . Is there is way to pass a value to the floating action button ?

    
    class TabScreen extends StatelessWidget {
    
      final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState();
      @override
      Widget build(BuildContext context) {
        final bool showfab = MediaQuery.of(context).viewInsets.bottom == 0.0;
        final AuthService authService = Provider.of<AuthService>(context);
     return StreamBuilder<List<String>>(
                  stream: forumServices.forumsTypes$,
                  builder: (context, snapshot) {
                    if (!snapshot.hasData) {
                      return CircularProgressIndicator();
                    }
                    List<String> types = snapshot.data;
                    num tabLen = types.length;
    
                    return DefaultTabController(
                        length: tabLen,
                        child: Scaffold(
                          key: _scaffoldKey,
    
                          body: CustomScrollView(slivers: <Widget>[
                            SliverAppBar(
                              title: Text("kdkdkkd"),
                              bottom: TabBar(
                                  tabs: types.map((String f) {
                                return Text(f);
                              }).toList()),
                            ),
                            SliverFillRemaining(
                              child: StreamBuilder<List<Forums>>(
                                  stream: forumServices.forums$,
                                  builder: (context, snap) {
                                    if (!snap.hasData) {
                                      return CircularProgressIndicator();
                                    }
                                    final forum = snap.data;
                                    return TabBarView(
                                      children: types.map((String type) {
                                        List<Forums> listofthistype =
                                            forum.where((Forums fo) {
                                          return fo.type == type;
                                        }).toList();
    
                                        final cards = listofthistype
                                            .map((thistype) => ForumCard(
                                                  choosentype: thistype,
                                                  forumServices: forumServices,
                                                ))
                                            .toList();
    
                                        return ListView(
                                          children: cards,
                                        );
                                      }).toList(),
                                    );
                                  }),
                            ),
                          ]),
                          floatingActionButton:
                            FloatingActionButton(
                                  onPressed: () => _showBottom(),
                                  tooltip: 'Increment',
                                  child: Icon(Icons.add),
                                )
    
                        ));
                  });