7

I'm using CupertinoTabBar in my flutter app. Problem is the bottomBar shows when keyboard appears, and it shouldn't. Its a bottom bar, it should be in bottom always.

I've not found some way or trick for do this. Maybe someone can guide me to get the right behaviour.

This is my flutter doctor output

Doctor summary (to see all details, run flutter doctor -v):

[✓] Flutter (Channel master, v1.6.1-pre.50, on Linux, locale en_US.UTF-8)

[✓] Android toolchain - develop for Android devices (Android SDK version 28.0.3)

[✓] Android Studio (version 3.3)

[✓] VS Code (version 1.33.1)

[✓] Connected device (1 available)

This are the only options allowed for cupertinoTabBar:

const CupertinoTabBar({
    Key key,
    @required this.items,
    this.onTap,
    this.currentIndex = 0,
    this.backgroundColor,
    this.activeColor,
    this.inactiveColor = CupertinoColors.inactiveGray,
    this.iconSize = 30.0,
    this.border = const Border(
      top: BorderSide(
        color: _kDefaultTabBarBorderColor,
        width: 0.0, // One physical pixel.
        style: BorderStyle.solid,
      ),
    ),
  })

This is how my CupertinoTabBar goes up when keyboard appears:

capture

Update:

I'm trying to validate keyboard's state for don't show the cupertinoTabBar, but it is inside a CupertinoTabScaffold:

return Scaffold(
    body: CupertinoTabScaffold(
      tabBuilder: (BuildContext context, int index) {
        switch (index) {
          case 0: // Home
            return CupertinoTabView(
              navigatorKey: Undoc3Keys.homeNavigator,
              routes: getRoutes(context, store),
              onGenerateRoute: handleRoutes,
              builder: (BuildContext context) => FeedScreen(),
            );
            break;
          case 1: // Preguntar
            return CupertinoTabView(
              navigatorKey: Undoc3Keys.askNavigator,
              routes: getRoutes(context, store),
              onGenerateRoute: handleRoutes,
              builder: (BuildContext context) => SearchResultScreen(
                    arguments: {"askScreen": ""},
                  ),
            );
            break;
          case 2: // Perfil
            return CupertinoTabView(
              navigatorKey: Undoc3Keys.perfilNavigator,
              routes: getRoutes(context, store),
              onGenerateRoute: handleRoutes,
              builder: (BuildContext context) => ProfileScreen(),
            );
            break;
          default:
        }
      },
      tabBar: Undoc3Keys.keyboardStatus // Here is validation of keyboard.
          ? CupertinoTabBar( // A try for making invisible bar.
              items: <BottomNavigationBarItem>[
                BottomNavigationBarItem(
                    icon: Icon(
                      Icons.radio_button_unchecked,
                      color: Colors.transparent,
                    ),
                    backgroundColor: Colors.transparent),
                BottomNavigationBarItem(
                    icon: Icon(
                      Icons.radio_button_unchecked,
                      color: Colors.transparent,
                    ),
                    backgroundColor: Colors.transparent)
              ],
              backgroundColor: Colors.transparent.withOpacity(0.0),
              inactiveColor: Colors.transparent,
              activeColor: Colors.transparent,
              border: Border(
                top: BorderSide(
                  color: Colors.transparent,
                  width: 0.0, // One physical pixel.
                  style: BorderStyle.none,
                ),
              ),
            )
          : _buildTabBar(),
    ),
  );

And it is how is showed the case when keyboard appears:

Still visible CupertinoTabBar

Paula Andrea
  • 230
  • 2
  • 10

1 Answers1

10

If you place your CupertinoTabBar inside the attribute bottomNavigationBar of Scaffold, it should be able to disappear automatically when the keyboard is open, so I'm assuming it is not possible to do that in your situation.

First, you got to know whether the keyboard is open of not. The plugin keyboard_visibility can help you with that.

With that information in hands, you must decide if you want to show CupertinoTabBar or not.

class Foo extends StatefulWidget {
  @override
  _FooState createState() => _FooState();
}

class _FooState extends State<Foo> {
  bool isKeyboardVisible;

  @override
  void initState() {
    super.initState();
    isKeyboardVisible = false;
    KeyboardVisibilityNotification().addNewListener(
      onChange: (isVisible) {
        setState(() => isKeyboardVisible = isVisible);
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        mainAxisSize: MainAxisSize.max,
        mainAxisAlignment: MainAxisAlignment.end,
        children: [
          TextField(),
          SizedBox(height: 50),
          isKeyboardVisible ? SizedBox() : CupertinoTabBar(
            items: [
              BottomNavigationBarItem(
                icon: Icon(Icons.airline_seat_flat_angled),
                title: Text('Item #1'),
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.airline_seat_flat),
                title: Text('Item #2'),
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.airline_seat_individual_suite),
                title: Text('Item #3'),
              ),
            ],
          ),
        ],
      ),
    );
  }
}

Update

You situation is kind of tricky. In this case, I think the better option is creating an invisible CupertinoTabBar:

class InvisibleCupertinoTabBar extends CupertinoTabBar {
  static const dummyIcon = Icon(IconData(0x0020));

  InvisibleCupertinoTabBar()
      : super(
          items: [
            BottomNavigationBarItem(icon: dummyIcon),
            BottomNavigationBarItem(icon: dummyIcon),
          ],
        );

  @override
  Size get preferredSize => const Size.square(0);

  @override
  Widget build(BuildContext context) => SizedBox();

  @override
  InvisibleCupertinoTabBar copyWith({
    Key key,
    List<BottomNavigationBarItem> items,
    Color backgroundColor,
    Color activeColor,
    Color inactiveColor,
    Size iconSize,
    Border border,
    int currentIndex,
    ValueChanged<int> onTap,
  }) => InvisibleCupertinoTabBar();
}

When the keyboard is visible, just show this widget instead.

isKeyboardVisible ? InvisibleCupertinoTabBar() : CupertinoTabBar(
  ...
),
Hugo Passos
  • 7,719
  • 2
  • 35
  • 52
  • Thats a good idea. But I have an additional situation that is my CupetinoTabBar is rendered inside a CupertinoTabScaffold, wich force me to set a tabBar property that must to be a CupertinoTabBar type, it throws an error because SizedBox is not a type allowed for tabbar property of CupertinoTabScaffold. I'm trying to make a CupertinoTabBar "invisible" but it preserves a blur on top of keyboard :S – Paula Andrea May 22 '19 at 16:52
  • Can you please edit your question with the code you just mentioned? – Hugo Passos May 22 '19 at 18:02
  • Thank you! I had done a class that extended from cupertinoTabBar but your implementation is much better. Works as expected. – Paula Andrea May 24 '19 at 16:13
  • @HugoPassos Excellent. It took me almost 2 days to find out how to hide the bottom nav bar in some cases. Your solution made my day. Thank you very much. – Tuan van Duong Feb 08 '20 at 04:09
  • 1
    Got error after upgrading to Flutter 1.17.0. Error `'InvisibleCupertinoTabBar.copyWith' ('InvisibleCupertinoTabBar Function({Color activeColor, Color backgroundColor, Border border, int currentIndex, Size iconSize, Color inactiveColor, List items, Key key, void Function(int) onTap})') isn't a valid override of 'CupertinoTabBar.copyWith'` – Tuan van Duong May 08 '20 at 06:16
  • 2
    I found out I need to change `Size iconSize` into `double iconSize` to fix the error after upgrading to `1.17.0` – Tuan van Duong May 08 '20 at 06:25
  • This is a great solution but the dummy icon can create issues with release builds, where you will see `IconTreeShakerException` failures. This was causing our app to fail in CI, even though local builds worked without issue. There is an easy resolution: create your dummy icon instead with `static const dummyIcon = Icon(null);` This has the same functional outcome for hiding the TabBar, and does not lead to the exception. – Duncan Babbage Jul 03 '23 at 22:15