flutter手写一个底部导航栏

使用了一下flutter提供的导航栏,NavigationBar,不过感觉使用起来不是很方便。
譬如说:

  1. 不能直接使用图片资源,需要中间加几层转换把图片转化成icon
  2. 文本大小及颜色不太好控制
  3. 状态栏的上边来一个横线也没有相应的样式,等等。

因此想来想去还是自己写一个吧。
效果如下:

在这里插入图片描述
控件代码如下:

import 'package:flutter/material.dart';
import 'dart:developer' as developer;

class XXNaviIcon {
    
    
  XXNaviIcon(
      {
    
    required this.normalImage,
      required this.selectedImage,
      required this.title});

  final String selectedImage;
  final String normalImage;
  final String title;
}

class XXNaviBar extends StatefulWidget {
    
    
  const XXNaviBar({
    
    super.key, required this.icons, this.onDestinationSelected})
      : currentIndex = 0;

  final List<XXNaviIcon> icons;
  final ValueChanged<int>? onDestinationSelected;
  final int currentIndex;

  
  State<XXNaviBar> createState() => _XXNaviBarState();
}

class _XXNaviBarState extends State<XXNaviBar> {
    
    
  int currentIndex = 0;

  
  Widget build(BuildContext context) {
    
    
    return SafeArea(
        child: SizedBox(
      height: 48,
      child: Container(
        decoration: const BoxDecoration(
            border:
                Border(top: BorderSide(width: 0.5, color: Color(0xffbbbbbb)))),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            for (int i = 0; i < widget.icons.length; i++)
              Expanded(
                  child: GestureDetector(
                onTap: () => {
    
    
                  developer.log("tap $i"),
                  setState(() {
    
    
                    currentIndex = i;
                  }),
                  if (widget.onDestinationSelected != null)
                    {
    
    widget.onDestinationSelected!(i)}
                },
                child: Container(
                  color: Colors.white,
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Image.asset(
                        currentIndex == i
                            ? widget.icons[i].selectedImage
                            : widget.icons[i].normalImage,
                        height: 24,
                      ),
                      Text(
                        widget.icons[i].title,
                        style: const TextStyle(
                            fontSize: 10, fontWeight: FontWeight.bold),
                      ),
                    ],
                  ),
                ),
              ))
          ],
        ),
      ),
    ));
  }
}

使用方式如下:


  Widget build(BuildContext context) {
    
    
    return Scaffold(
      backgroundColor: Colors.white,
      bottomNavigationBar: XXNaviBar(
        onDestinationSelected: (value) => {
    
    
          developer.log("click tab $value"),
          if (currentPageIndex != value)
            {
    
    
              setState(() {
    
    
                currentPageIndex = value;
              })
            }
        },
        icons: [
          XXNaviIcon(
            normalImage: "assets/images/tabbar/home.png",
            selectedImage: "assets/images/tabbar/home-selected.png",
            title: "首页",
          ),
          XXNaviIcon(
            normalImage: "assets/images/tabbar/data.png",
            selectedImage: "assets/images/tabbar/data-selected.png",
            title: "数据",
          ),
          XXNaviIcon(
            normalImage: "assets/images/tabbar/mine.png",
            selectedImage: "assets/images/tabbar/mine-selected.png",
            title: "我的",
          ),
        ],
      ),
      body: <Widget>[
        Container(
          color: Colors.white,
          alignment: Alignment.center,
          child: const Text('Page 1'),
        ),
        Container(
          color: Colors.white,
          alignment: Alignment.center,
          child: const Text('Page 2'),
        ),
        Container(
          color: Colors.white,
          alignment: Alignment.center,
          child: const Text('Page 3'),
        ),
      ][currentPageIndex],
    );
  }

定制化可以根据自己的实际需求自行更改。

猜你喜欢

转载自blog.csdn.net/xo19882011/article/details/131493622