这是我在 StackOverflow 上提出的第一个问题,我希望我能提供正确回答所需的一切。
我正在构建 Instagram 克隆,我想使用 CupertinoTabBar 来模仿 Instagram 的应用行为。
Instagram 上的行为: Gif
目前的主要挑战是我想通过点击 NavigationBar 上的图标来显示整页对话以创建帖子。通常,我会使用如下代码:
Navigator.of(
context,
rootNavigator: true,
).push<...>(
SlidePageTransitionBuilder<...>(
builder: ...,
transitionCurve: routeCurve,
transitionDuration: routeDuration,
),
);
但不幸的是,我无法将此 Navigator.push 放在按下的条形图标上,因为它需要一个返回类型的小部件,我不知道如何在具有预期行为的同时提供它。
非常感谢某人的帮助。如果您需要更多信息,请告诉我。
示例项目代码:
主要飞镖:
import 'package:flutter/material.dart';
import 'cupertino_home_scaffold.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
TabItem _currentTab = TabItem.timeline;
final Map<TabItem, GlobalKey<NavigatorState>> navigatorKeys = {
TabItem.timeline: GlobalKey<NavigatorState>(),
TabItem.map: GlobalKey<NavigatorState>(),
TabItem.share: GlobalKey<NavigatorState>(),
TabItem.account: GlobalKey<NavigatorState>(),
};
Map<TabItem, WidgetBuilder> get widgetBuilders {
return {
TabItem.timeline: (_) => SomePage(),
TabItem.map: (_) => SomePage(),
TabItem.share: (context) =>
PostPage(), //Should be displayed with Navigator.push...,
TabItem.account: (_) => SomePage(),
};
}
void _select(TabItem tabItem) {
if (tabItem == _currentTab) {
navigatorKeys[tabItem].currentState.popUntil((route) => route.isFirst);
} else {
setState(() {
_currentTab = tabItem;
});
}
}
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async =>
!await navigatorKeys[_currentTab].currentState.maybePop(),
child: CupertinoHomeScaffold(
navigatorKeys: navigatorKeys,
currentTab: _currentTab,
onSelectTab: _select,
widgetBuilders: widgetBuilders,
),
);
}
}
cupertino_home_scaffold.dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class CupertinoHomeScaffold extends StatelessWidget {
const CupertinoHomeScaffold({
Key key,
@required this.currentTab,
@required this.onSelectTab,
@required this.widgetBuilders,
@required this.navigatorKeys,
}) : super(key: key);
final TabItem currentTab;
final ValueChanged<TabItem> onSelectTab;
final Map<TabItem, WidgetBuilder> widgetBuilders;
final Map<TabItem, GlobalKey<NavigatorState>> navigatorKeys;
@override
Widget build(BuildContext context) {
return CupertinoTabScaffold(
tabBar: CupertinoTabBar(
items: [
_buildItem(TabItem.timeline),
_buildItem(TabItem.map),
_buildItem(TabItem.share),
_buildItem(TabItem.account),
],
onTap: (index) => onSelectTab(TabItem.values[index]),
),
tabBuilder: (context, index) {
final item = TabItem.values[index];
print(item);
return CupertinoTabView(
navigatorKey: navigatorKeys[item],
builder: (context) => widgetBuilders[item](context),
);
},
);
}
BottomNavigationBarItem _buildItem(TabItem tabItem) {
final itemData = TabItemData.allTabs[tabItem];
final color = currentTab == tabItem ? Colors.black : Colors.grey;
return BottomNavigationBarItem(
icon: Icon(
itemData.icon,
color: color,
),
title: Text(
itemData.title,
style: TextStyle(color: color),
),
);
}
}
enum TabItem { timeline, map, share, account }
class TabItemData {
const TabItemData({@required this.title, @required this.icon});
final String title;
final IconData icon;
static const Map<TabItem, TabItemData> allTabs = {
TabItem.timeline: TabItemData(title: 'Home', icon: Icons.home),
TabItem.map: TabItemData(title: 'Map', icon: Icons.pin_drop),
TabItem.share: TabItemData(title: 'Share', icon: Icons.add_circle_outline),
TabItem.account: TabItemData(title: 'Account', icon: Icons.person),
};
}