Flutter CupertinoTabBar display CupertinoTabView like Поделиться страницей в Instagram - PullRequest
1 голос
/ 28 мая 2020

это первый вопрос, который я задаю в StackOverflow, и я надеюсь, что предоставлю все необходимое для правильного ответа.

Я создаю клон Instagram, и я хочу использовать CupertinoTabBar для mimi c the поведение приложения Instagram.

Поведение в Instagram: Gif

Основная проблема на данный момент заключается в том, что я хочу отобразить полностраничный диалог для создания сообщения, нажав значок на Панель навигации. Обычно я бы использовал такой код:

Navigator.of(
          context,
          rootNavigator: true,
        ).push<...>(
          SlidePageTransitionBuilder<...>(
            builder: ...,
            transitionCurve: routeCurve,
            transitionDuration: routeDuration,
          ),
        );

Но, к сожалению, я не могу поместить этот Navigator.pu sh на нажатую иконку панели, поскольку он ожидает возвращаемого типа виджета, который Я не знаю, как обеспечить ожидаемое поведение.

Чья-то помощь очень ценится. Пожалуйста, дайте мне знать, если вам нужна дополнительная информация.

Пример кода проекта:

Git Hub Repo

main.dart:

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