Dans ce widget, les onglets naviguent entre les types s'il est question qu'il passe à un écran spécifié. Si c'est un forum, il va à un autre. Le problème est que je dois passer le type du robinet actuel à la fonction sur pression dans le bouton d'action flottant. Cependant, le bouton d'action flottant se trouve à l'extérieur du corps de l'échafaudage. Existe-t-il un moyen de transmettre une valeur au bouton d'action flottant?
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), ) )); });
3 Réponses :
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.
Supprimez le widget DefaultTabController
et créez votre propre TabController
à la place - cela vous permet d'ajouter un auditeur au TabController
qui sera déclenché chaque l'heure à laquelle l'utilisateur accède à un autre onglet. Vous pouvez utiliser ce mécanisme pour obtenir des données associées à l'index de l'onglet courant, comme le type.
Voici le code que vous avez fourni, avec les modifications que j'ai mentionnées ci-dessus. Le type est stocké dans la variable currentType
, que vous pouvez utiliser lorsque vous appuyez sur 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), ), ); }, ); } }
Vous pouvez stocker les données dont vous avez besoin pour transmettre une variable et utiliser cette variable dans onPressed
de FloatingActionButton
.
J'ai le même problème. Je veux passer l'instantané au bouton flottant sur la fonction Pressed.
J'ai utilisé un modèle à partir duquel j'obtiens toutes mes données, puis je les rappelle dans le bouton en utilisant le fournisseur