在此小部件中,如果要进入指定的屏幕,则选项卡会在类型之间导航。如果是论坛,则转到另一个论坛。问题是我需要将当前拍子的类型传递给浮动操作按钮中的按下功能。但是,“浮动动作”按钮位于脚手架的外部。有办法将值传递给浮动操作按钮吗?
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),
)
));
});
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(),
);
}),
),
]);
}
}
为简单起见,使用futureBuilder如果没有从快照中加载选项卡的长度,则可以避免使用全局密钥,而只需在最开始就创建选项卡控制器。
不要忘记进行null检查。 Fab将在加载数据之前显示。
删除DefaultTabController
小部件并创建自己的TabController
-这使您可以向TabController
添加侦听器,该侦听器将在用户每次导航到其他选项卡时触发。您可以使用此机制来获取与当前选项卡的索引关联的数据,例如类型。
这是您提供的代码,具有我上面提到的修改。类型存储在currentType
变量中,您可以在点击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),
),
);
},
);
}
}
您可以将需要传递的数据存储在变量中,并在onPressed
的FloatingActionButton
中使用该变量。