【问题标题】:Transparent bottom navigation bar in flutter颤动中的透明底部导航栏
【发布时间】:2019-06-19 09:20:16
【问题描述】:

我是新来的颤振。我正在尝试实现这个 UI

我还没有找到任何在颤振中创建透明底部导航栏的完整解决方案。

我尝试过使用

BottomNavigationBarItem(
        backgroundColor: Colors.transparent,
        icon: e,
        activeIcon: _activeIcons[_index],
        title: Text(
          title[_index],
          style: AppStyle.tabBarItem,
        ),
      )

但这似乎不起作用。请帮忙。

【问题讨论】:

  • 我想这可能是你需要的:stackoverflow.com/questions/49307858/…
  • 我刚刚尝试过,但它不起作用。你能赞成这个问题吗?我是 stack-overflow 的新手,人们不赞成。
  • 你能告诉你使用 @magicleon94 链接的 Theme 方法,这样我们就可以看到它为什么不起作用?
  • 现在我不能,因为我在工作。如果可以的话,我会解释如何根据您的需要调整链接的问题。至于现在,我刚刚链接的答案解决了 NavigationBar 的背景需求。
  • 深入思考,我意识到这不会提供与预期相同的结果,因为两个女孩的图像会在 NavigationBar 上方。我建议使用带有两个女孩图像的Stack 作为底层(堆栈的底部)和全屏Column,将MainAxisSize 设置为MainAxisSize.maxMainAxisAlignment 设置为MainAxisAlignment.end。我可以将其写在答案中,但我现在无法对其进行测试,因此我更喜欢写评论。希望对你有帮助

标签: dart flutter flutter-layout


【解决方案1】:

给定的答案都不适合我,我发现了一些非常重要的事情:您必须添加属性extendBody: true

如果为true,并且指定了bottomNavigationBar或persistentFooterButtons,那么body会延伸到Scaffold的底部,而不是仅仅延伸到bottomNavigationBar或persistentFooterButtons的顶部。

当 bottomNavigationBar 具有非矩形形状时,此属性通常很有用,例如 CircularNotchedRectangle,它会在栏的顶部边缘添加一个 FloatingActionButton 大小的凹口。在这种情况下,指定 extendBody: true 确保脚手架的主体将通过底部导航栏的凹槽可见

backgroundColor: Color(0x00ffffff), 一起。

注意:带 0x 的颜色是十六进制的 ARGB 值 (0xAARRGGBB),所以 ffffff 之前的 00 表示最大透明度,您可以通过将 00 增加到 ff(十六进制为 255)来增加不透明度。

完整代码示例:

import 'package:flutter/material.dart';

class NavigationBar extends StatefulWidget {
  static int _selectedIndex = 0;

  @override
  NavigationBarState createState() => NavigationBarState();
}

class NavigationBarState extends State<NavigationBar> {
  void _onItemTapped(int index) {
    setState(() {
      NavigationBar._selectedIndex = index;
    });
  }

  @override
  Widget build(BuildContext context) {

    return BottomNavigationBar(
        elevation: 0, // to get rid of the shadow
        currentIndex: NavigationBar._selectedIndex,
        selectedItemColor: Colors.amber[800],
        onTap: _onItemTapped,
        backgroundColor: Color(0x00ffffff), // transparent, you could use 0x44aaaaff to make it slightly less transparent with a blue hue.
        type: BottomNavigationBarType.fixed,
        unselectedItemColor: Colors.blue,
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            label: 'Home',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.grade),
            label: 'Level',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.notifications),
            label: 'Notification',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.school),
            label: 'Achievements',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.settings),
            label: 'Settings',
          ),
        ]
    );
  }

  @override
  Size get preferredSize => const Size.fromHeight(kToolbarHeight);
}

然后你的 MaterialApp 返回:

return MaterialApp(
                home: Scaffold(
                    extendBody: true, // very important as noted
                    bottomNavigationBar: NavigationBar(), // here you make use of the transparent bar.
                    body: Container(
                        decoration: BoxDecoration(
                            image: DecorationImage(
                                image: ExactAssetImage("assets/background.png"), // because if you want a transparent navigation bar I assume that you have either a background image or a background color. You need to add the image you want and also authorize it in pubspec.yaml
                                fit: BoxFit.fill
                            ),
                        ),
                        child: Container(
                              // the body of your app
                        ),
                    ),
                ),
            );
        }
    }

我希望它会有所帮助。

【讨论】:

  • 这应该是官方接受的答案!就是这么简单。而不是使用双或三脚手架lol
  • 这是我认为的最佳答案。此外,如果您的小部件树中有 SafeArea 小部件,您可能必须将底部设置为 false。 (SafeArea(bottom: false, child:...)
  • 最佳答案,我可以将它与另一个导航栏插件一起使用
  • 还在代码上方的简短信息中添加type: BottomNavigationBarType.fixed,,tnx
【解决方案2】:

我尝试使用 cmets 中讨论的 Stack 方法:

  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Stack(
          children: <Widget>[
            Container(
              decoration: BoxDecoration(
                image: DecorationImage(
                    image: AssetImage('assets/background.jpg'),
                    fit: BoxFit.cover),
              ),
            ),
            Align(
                alignment: Alignment.bottomCenter,
                child: Theme(
                    data: Theme.of(context)
                        .copyWith(canvasColor: Colors.transparent),
                    child: BottomNavigationBar(
                      currentIndex: 0,
                      items: [
                        BottomNavigationBarItem(
                            icon: Icon(Icons.home), title: Text('Home')),
                        BottomNavigationBarItem(
                            icon: Icon(Icons.home), title: Text('Home')),
                        BottomNavigationBarItem(
                            icon: Icon(Icons.home), title: Text('Home'))
                      ],
                    ))),
          ],
        ),
      ),
    );
  }

编辑:BottomNavigationBar 的内置高度为8.0,您无法更改它并导致奇怪的阴影效果。如果你想删除它,你可以像这样实现你自己的底栏:

Align(
                alignment: Alignment.bottomCenter,
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: <Widget>[
                  IconButton(icon: Icon(Icons.home, color: Theme.of(context).accentColor,), onPressed: () {},),
                  IconButton(icon: Icon(Icons.home, color: Theme.of(context).accentColor,), onPressed: () {},),
                  IconButton(icon: Icon(Icons.home, color: Theme.of(context).accentColor,), onPressed: () {},),
                ],)),

【讨论】:

  • 非常感谢。拯救了我的一天。你能帮忙解决另一个问题吗?我希望 ListItem 占据全部可用高度和宽度,但它似乎不适用于 Expanded。
  • 让我为此创建另一个问题。
  • 没问题,但我想你会想使用 ListTile 以外的其他东西,因为它们有固定的高度 afaik。
  • 还有哪些集合结构提供这样的功能?
  • ListView 不必由ListTiles 组成,孩子可以是任何类型的小部件,所以我想您可以只使用Row 或创建自己的版本ListTile.
【解决方案3】:

这就是我实现这一目标的方式

    return Scaffold(
      body: Builder(
        builder: (context) => Container(
          decoration: bgAuthenticationDecoration(),
          child: _HomeBodyWidget(_currentIndex),
        ),
      ),
      bottomNavigationBar: BottomNavigationBar(items: <BottomNavigationBarItem>[
        BottomNavigationBarItem(icon: Icon(Icons.home,),title: Container()),
        BottomNavigationBarItem(icon: Icon(Icons.message),title: Container()),
        BottomNavigationBarItem(icon: Icon(Icons.list),title: Container()),
        BottomNavigationBarItem(icon: Icon(Icons.favorite),title: Container()),
        BottomNavigationBarItem(icon: Icon(Icons.supervised_user_circle),title: Container()),
      ],
      backgroundColor:Colors.black.withOpacity(0.1),),
      extendBodyBehindAppBar: true,
      extendBody: true,
    );

然后您必须在应用主题中将画布颜色设置为透明。

canvasColor: Colors.transparent

希望这会有所帮助。

编码愉快!

【讨论】:

    【解决方案4】:

    这是我的方法:

    Stack(
          children: <Widget>[
            Container(
              decoration: BoxDecoration(
                image: DecorationImage(
                  fit: BoxFit.fill,
                  image: NetworkImage("https://cdn.pixabay.com/photo/2018/09/17/16/24/cat-3684184_960_720.jpg")
                )
              ),
            ),
            Column(
              mainAxisSize: MainAxisSize.max,
              mainAxisAlignment: MainAxisAlignment.end,
              children: <Widget>[
                Theme(
                  data: Theme.of(context).copyWith(canvasColor: Colors.transparent),
                  child: BottomNavigationBar(
                    items: [
                      BottomNavigationBarItem(
                          icon: Icon(Icons.photo_camera), title: Text("Test")),
                      BottomNavigationBarItem(
                          icon: Icon(Icons.photo_camera), title: Text("Test")),
                    ],
                  ),
                )
              ],
            )
          ],
        );
    

    这将用背景图像(底层)和底部导航栏填满整个屏幕(图像纯粹是微不足道的,但你明白了),其内容与end对齐的列内的底部导航栏。

    为了完成目的,我将在原始问题的 cmets 中粘贴解释。

    深入思考后,我意识到这不会带来同样的效果 结果符合预期,因为两个女孩的形象会在上面 导航栏。我建议使用带有两个女孩图像的堆栈 作为底层(堆栈的底部)和一个全屏列 MainAxisSize 设置为 MainAxisSize.max 和 MainAxisAlignment 设置为 MainAxisAlignment.end。我可以把它写在答案中,但我无法测试 现在,所以我更喜欢写评论。希望对你有帮助

    更新 以前的解决方案仍然有导航栏阴影。 屏幕(小部件)的这种构建方法没有,因为我用Row 实现了我自己的BottomNavigationBar

    @override
      Widget build(BuildContext context) {
        return Stack(
          children: <Widget>[
            Container(
              decoration: BoxDecoration(
                  image: DecorationImage(
                      fit: BoxFit.fill,
                      image: NetworkImage(
                          "https://media.idownloadblog.com/wp-content/uploads/2016/04/macinmac-portrat-splash.jpg"))),
            ),
            Column(
              mainAxisSize: MainAxisSize.max,
              mainAxisAlignment: MainAxisAlignment.end,
              children: <Widget>[
                Row(
                  mainAxisSize: MainAxisSize.max,
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: <Widget>[
                    GestureDetector(
                        onTap: () {
                          print("Tap!");
                        },
                        child: Icon(
                          Icons.photo_camera,
                          size: 50,
                        )),
                    GestureDetector(
                        onTap: () {
                          print("Tap!");
                        },
                        child: Icon(
                          Icons.photo_camera,
                          size: 50,
                        )),
                    GestureDetector(
                        onTap: () {
                          print("Tap!");
                        },
                        child: Icon(
                          Icons.photo_camera,
                          size: 50,
                        )),
                    GestureDetector(
                        onTap: () {
                          print("Tap!");
                        },
                        child: Icon(
                          Icons.photo_camera,
                          size: 50,
                        )),
                  ],
                )
              ],
            )
          ],
        );
    

    这是我手机的截图:

    奖金

    可以通过调用实现全屏

    SystemChrome.setEnabledSystemUIOverlays([]);
    

    来源:here

    【讨论】:

    • 非常感谢。拯救了我的一天。你能帮忙解决另一个问题吗?我希望 ListItem 占据全部可用高度和宽度,但它似乎不适用于 Expanded。
    • 哦,不,我不这么认为。我比较慢,没问题,我会逐渐接受一个赞成作为安慰奖:)
    • 让我为此创建另一个问题。
    • 哈哈对不起@magicleon94!你的方法在导航栏上是否还有高程阴影?
    • 不,不是。稍等,我也截图。
    【解决方案5】:

    在新版本的flutter(1.2.1)中有一个海拔参数,你可以把 海拔:0.0

    【讨论】:

      【解决方案6】:

      我的高级解决方案:

        @override
        Widget build(BuildContext context) {
          return Scaffold(
            body: Stack(
              children: <Widget>[
                SingleChildScrollView(
                  child: Center(
                    child: Column(
                      children: <Widget>[
                        child(),
                        child(),
                        child(),
                        child(),
                        child(),
                      ],
                    ),
                  ),
                ),
                Align(
                  alignment: Alignment.bottomCenter,
                  child: Opacity(opacity: showBottomBar ? 1 : 0, child: bottomBar()),
                )
              ],
            ),
          );
      

      这个想法是一个堆栈,下层有一个可滚动的视图,顶部有一个对齐的自定义底栏

      【讨论】:

        【解决方案7】:

        你可以做类似...

        不要忘记设置elevation: 0 并使用导入它 import 'package:flutter/services.dart';

        隐藏状态栏

        void main() {
          SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.bottom]);
          runApp(MaterialApp(
             home: MyApp()));
        }
        

        底部导航栏透明

        BottomNavigationBar(
          backgroundColor: Colors.black.withOpacity(0.1), //here set your transparent level
          elevation: 0,
        );
        

        这是完整的代码

        @override
        Widget build(BuildContext context) {
          return Scaffold(
            body: Stack(
              children: <Widget>[
                Container(
                 child: Image.network("https://picsum.photos/660/1420"),
                ),
                Align(
                    alignment: Alignment.bottomCenter,
                    child: BottomNavigationBar(
                      backgroundColor: Colors.black.withOpacity(0.1), //here set your transparent level
                      elevation: 0,
                      selectedItemColor:  Colors.blueAccent,
                      unselectedItemColor: Colors.white,
                      type: BottomNavigationBarType.fixed,
                      currentIndex: 0,
                      showSelectedLabels: false,
                      showUnselectedLabels: false,
                      items: [
                        BottomNavigationBarItem(
                            icon: Icon(Icons.notifications_none, size: 30), title: Text('Notifications')),
                        BottomNavigationBarItem(
                            icon: Icon(Icons.search, size: 30), title: Text('Search')),
                        BottomNavigationBarItem(
                            icon: Icon(Icons.perm_identity, size: 30), title: Text('User'))
                      ],
                    )),
              ],
            ),
          );
        }
        

        【讨论】:

        • 在 Scaffold 小部件内部添加缺少的 extendBody: true 以实现此效果。
        【解决方案8】:
        Scaffold(  
          floatingActionButton: _buildTransparentButton()
        )
        

        你可以试试floatingActionButton。

        【讨论】:

          【解决方案9】:

          找到透明BottomNavigationBar的解决方案。

          1. 使用快捷键Ctrl+B打开BottomNavigationBar的源代码。
          2. 滚动文件你会发现一个名为Widget build的方法。
          3. 您可以在上面找到Stack widget,您可以在其中找到材质小部件。
          4. 添加shadowColor:Colors.transparent

          现在你得到一个透明的BottomNavigationBar

          【讨论】:

          • 请不要修改flutter框架本身,否则升级时会出现问题。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-12-21
          • 1970-01-01
          • 2020-07-23
          • 1970-01-01
          • 2020-03-07
          相关资源
          最近更新 更多