【问题标题】:Displaying notification badge on BottomNavigationBar's Icon在底部导航栏的图标上显示通知徽章
【发布时间】:2017-07-17 23:22:06
【问题描述】:

当有新消息时,我想在 BottomNavigationBar 的 Icon 小部件的 右上角 显示通知徽章(彩色 大理石)已到达收件箱选项卡。它类似于https://developer.android.com/preview/features/notification-badges.html,但在我的情况下,它显示在应用内。

在现有图标上绘制叠加层以创建自定义图标类的任何提示?

【问题讨论】:

    标签: dart flutter


    【解决方案1】:

    计数徽章的另一种变体(使用 Stack of Icon 实现并包裹在容器文本中,当计数器增加时会拉伸):

    BottomNavigationBarItem(
      icon: new Stack(
        children: <Widget>[
          new Icon(Icons.notifications),
          new Positioned(
            right: 0,
            child: new Container(
              padding: EdgeInsets.all(1),
              decoration: new BoxDecoration(
                color: Colors.red,
                borderRadius: BorderRadius.circular(6),
              ),
              constraints: BoxConstraints(
                minWidth: 12,
                minHeight: 12,
              ),
              child: new Text(
                '$_counter',
                style: new TextStyle(
                  color: Colors.white,
                  fontSize: 8,
                ),
                textAlign: TextAlign.center,
              ),
            ),
          )
        ],
      ),
      title: Text('Notifications'),
    ),
    

    【讨论】:

    • 红圈大小如何调整?
    • 红圈是Container,所以是自动调整的,但是用正确的constraintsdecoration,它显示为圆圈。
    • 不工作,当我添加此代码时,它以红色显示代码
    • @Midhilaj 似乎您在其他地方有错误,因为此代码即使在 DartPad 中也有效 - dartpad.dev/65b65e2d7cdb8a8d934e1f1fb81650ad
    • @ych 如果在 Positioned 之前添加此行会更好一些。 if(_counter > 0)
    【解决方案2】:

    是的。这可以通过使用StackPositioned 小部件堆叠两个图标来完成。

          new BottomNavigationBarItem(
            title: new Text('Home'),
            icon: new Stack(
              children: <Widget>[
                new Icon(Icons.home),
                new Positioned(  // draw a red marble
                  top: 0.0,
                  right: 0.0,
                  child: new Icon(Icons.brightness_1, size: 8.0, 
                    color: Colors.redAccent),
                )
              ]
            ),
          )
    

    【讨论】:

    • 这涵盖了我的整个图标。该位置必须是负数,但这会切断圆圈
    • @Jones,在 Stack 中尝试 overflow: Overflow.visible 应该可以修复剪辑
    • 现在已弃用。您的替代解决方案是什么?
    【解决方案3】:

    屏幕截图(Null 安全)

    如果您还想处理onTap 一些飞溅,请使用此小部件,您可以根据需要进一步自定义:

    不需要依赖包,复制这个类即可

    class NamedIcon extends StatelessWidget {
      final IconData iconData;
      final String text;
      final VoidCallback? onTap;
      final int notificationCount;
    
      const NamedIcon({
        Key? key,
        this.onTap,
        required this.text,
        required this.iconData,
        this.notificationCount = 0,
      }) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return InkWell(
          onTap: onTap,
          child: Container(
            width: 72,
            padding: const EdgeInsets.symmetric(horizontal: 8),
            child: Stack(
              alignment: Alignment.center,
              children: [
                Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    Icon(iconData),
                    Text(text, overflow: TextOverflow.ellipsis),
                  ],
                ),
                Positioned(
                  top: 0,
                  right: 0,
                  child: Container(
                    padding: EdgeInsets.symmetric(horizontal: 6, vertical: 2),
                    decoration: BoxDecoration(shape: BoxShape.circle, color: Colors.red),
                    alignment: Alignment.center,
                    child: Text('$notificationCount'),
                  ),
                )
              ],
            ),
          ),
        );
      }
    }
    

    用法:

    Scaffold(
      appBar: AppBar(
        title: Text('AppBar'),
        actions: [
          NamedIcon(
            text: 'Inbox',
            iconData: Icons.notifications,
            notificationCount: 11,
            onTap: () {},
          ),
          NamedIcon(
            text: 'Mails',
            iconData: Icons.mail,
            notificationCount: 1,
            onTap: () {},
          ),
        ],
      ),
    )
    

    【讨论】:

      【解决方案4】:

      有一个不错的包[0],它使这变得像使用以下而不是图标一样简单:

      Badge(
        badgeContent: Text('3'),
        child: Icon(Icons.settings),
      )
      

      0:https://pub.dev/packages/badges

      【讨论】:

        【解决方案5】:
        new BottomNavigationBar(
              type: BottomNavigationBarType.fixed,
              fixedColor: const Color(0xFF2845E7),
              items: [
                new BottomNavigationBarItem(
                  icon: new Icon(
                    Icons.home,
                  ),
                  title: new Text(
                    "Home",
                  ),
                ),
                new BottomNavigationBarItem(
                    icon: new Icon(
                      Icons.call,
                    ),
                    title: new Text(
                      "Calls",
                    )),
                new BottomNavigationBarItem(
                    icon: new Icon(
                      Icons.camera_alt,
                    ),
                    title: new Text(
                      "Camera",
                    )),
                new BottomNavigationBarItem(
                    icon: new Stack(children: <Widget>[
                      new Icon(Icons.favorite),
                      new Positioned(
                          top: -1.0,
                          right: -1.0,
                          child: new Stack(
                            children: <Widget>[
                              new Icon(
                                Icons.brightness_1,
                                size: 12.0,
                                color: const Color(0xFF2845E7),
                              ),
                            ],
                          ))
                    ]),
                    title: new Text(
                      "Stories",
                    )),
                new BottomNavigationBarItem(
                    icon: new Icon(
                      Icons.account_circle,
                    ),
                    title: new Text(
                      "Contacts",
                    )),
              ],
              onTap: (){},
              currentIndex: 0,
            ),
        

        【讨论】:

          【解决方案6】:

          您还可以嵌套堆栈。例如,如果您想在 shopping_cart 图标上添加 item_count,您可以这样做:

          icon: new Stack(
                        children: <Widget>[
                          new Icon(Icons.shopping_cart),
                          new Positioned(
                            top: 1.0,
                            right: 0.0,
                            child: new Stack(
                              children: <Widget>[
                                new Icon(Icons.brightness_1,
                                    size: 18.0, color: Colors.green[800]),
                                new Positioned(
                                  top: 1.0,
                                  right: 4.0,
                                  child: new Text(item_count,
                                      style: new TextStyle(
                                          color: Colors.white,
                                          fontSize: 15.0,
                                          fontWeight: FontWeight.w500)),
                                )
                              ],
                            ),
                          )
                        ],
                      )
          

          【讨论】:

            【解决方案7】:

            我会使用StackIcon 上渲染弹珠,将弹珠包裹在PositionedAlignFractionallySizedBox 中以按照您想要的方式定位它。

            【讨论】:

              【解决方案8】:

              没有导航图标和铃铛图标的透明appBar:

              appBar: AppBar(
                  backgroundColor: Colors.transparent,
                  automaticallyImplyLeading: false,
                  title: Align(
                    alignment: Alignment.centerLeft,
                    child: Text('Find Your Favorite drink',
                      style: kTitle,
                    ),
                  ),
                  actions: [
                    Padding(
                      padding: const EdgeInsets.only(right: 12.0,top: 5,bottom: 5),
                      child: Container(
                        decoration: BoxDecoration(
                          color: Colors.white,
                          borderRadius: BorderRadius.circular(15),
                        ),
                        height: 20,
                        width: 45,
                        child: IconButton(
                          icon: Stack(
                              children: <Widget>[
                                new Icon(Icons.notifications_none_outlined,
                                  color: Color(0xFFFEA70B),
                                ),
                                new Positioned(  // draw a red marble
                                  top: 0.0,
                                  right: 0.0,
                                  child: new Icon(Icons.brightness_1, size: 8.0,
                                      color: Color(0xFFFF4545)),
                                )
                              ]
                          ),
                          onPressed: (){},
                        ),
                      ),
                    ),
                  ],
                ),
              

              【讨论】:

                【解决方案9】:
                        Stack(
                          children: <Widget>[
                            IconButton(
                              iconSize: 32,
                              splashColor: Colors.transparent,
                              highlightColor: Colors.transparent,
                              padding: EdgeInsets.zero,
                              constraints: BoxConstraints(),
                              icon: Icon(Icons.notifications,color: AshtarColors.dark_blue,),
                              onPressed: () {
                                log("notification");
                              },
                            ),
                            new Positioned(
                              top: 3,
                              right: 0,
                              child: new Container(
                                padding: EdgeInsets.all(1),
                                decoration: new BoxDecoration(
                                  color: Colors.red,
                                  borderRadius: BorderRadius.circular(6),
                                ),
                                constraints: BoxConstraints(
                                  minWidth: 15,
                                  minHeight: 15,
                                ),
                                child: new Text('11',
                                  style: new TextStyle(
                                    color: Colors.white,
                                    fontSize: 11,
                                  ),
                                  textAlign: TextAlign.center,
                                ),
                              ),
                            )
                          ],
                        )
                

                【讨论】:

                  猜你喜欢
                  • 2017-07-29
                  • 2017-09-29
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2018-07-04
                  • 2021-02-13
                  相关资源
                  最近更新 更多