LOADING

MiniKano的小窝


 

Flutter实现仿闲鱼底部导航栏效果

Flutter实现仿闲鱼底部导航栏效果

实现原理

底部导航栏使用bottomNavigationBar组件
底部导航栏子元素使用BottomNavigationBarItem组件
突起按钮的实现方式是使用 floatingActionButton组件 + floatingActionButtonLocation 居中样式(centerDocked)

简单来说就是基于底部导航栏组件的基础上再增加一个浮动的按钮,覆盖到导航栏组件上,和中间的按钮重合在一起,最后取消掉被覆盖的按钮的点击水波纹效果。

代码演示

main.dart

import 'package:flutter/material.dart';
import './pages/tabs.dart';

void main(List<String> args) {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Test",
      theme: ThemeData(
        primarySwatch: Colors.red,
      ),
      home: const Tabs(),
    );
  }
}

pages/tabs.dart

import 'package:flutter/material.dart';
import './tabs/category.dart';
import './tabs/home.dart';
import './tabs/setting.dart';

class Tabs extends StatefulWidget {
  const Tabs({super.key});
  @override
  State<Tabs> createState() => _TabsState();
}

class _TabsState extends State<Tabs> {
  final List<Widget> _pages = const [HomePage(), Category(), Setting()];
  int _selected = 0;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Test"),
      ),
      //底部导航栏
      bottomNavigationBar: Theme(
        //阻止点击飞溅效果(需要套一个Theme组件)
        data: ThemeData(
          splashColor: Colors.transparent,
          highlightColor: Colors.transparent,
        ),
        child: BottomNavigationBar(
          //当前选中位置
          currentIndex: _selected,
          iconSize: 35, //菜单大小
          fixedColor: Colors.red, //选中的颜色
          unselectedItemColor: Colors.grey,
          selectedFontSize: 12.0,
          //4个以上菜单选项需要配置为固定
          type: BottomNavigationBarType.fixed,
          //侦听器
          onTap: (index) {
            //需要setState
            setState(() {
              _selected = index;
            });
          },
          items: const [
            BottomNavigationBarItem(icon: Icon(Icons.home), label: "主页"),
            BottomNavigationBarItem(icon: Icon(Icons.category), label: "分类"),
            BottomNavigationBarItem(
              icon: Icon(Icons.add),
              label: "添加",
              backgroundColor: Colors.red,
            ),
            BottomNavigationBarItem(icon: Icon(Icons.message), label: "消息"),
            BottomNavigationBarItem(icon: Icon(Icons.settings), label: "设置"),
          ],
        ),
      ),
      // 仿闲鱼的凸起按钮
      floatingActionButton: Container(
        width: 60,
        height: 60,
        padding: const EdgeInsets.all(5),
        transform: Matrix4.translationValues(0, 14, 0),
        decoration: BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.circular(30),
        ),
        child: FloatingActionButton(
          // 选中了变红色,不选中是灰色
          backgroundColor: _selected == 2 ? Colors.red : Colors.blue,
          onPressed: () {
            setState(() {
              _selected = 2;
            });
          },
          child: const Icon(Icons.add),
        ),
      ),
      // 调整floatingActionButton的位置
      floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
      //最简单的方法
      // body: _pages[_selected],

      //也可以用indexedStack
      body: IndexedStack(
        alignment: Alignment.center,
        index: _selected,
        children: _pages,
      ),
    );
  }
}

pages/tabs/home.dart
pages/tabs/category.dart
pages/tabs/add.dart
pages/tabs/setting.dart

import 'package:flutter/material.dart';

class Category extends StatefulWidget {
  const Category({super.key});

  @override
  State<Category> createState() => _CategoryState();
}

class _CategoryState extends State<Category> {
  @override
  Widget build(BuildContext context) {
    return const Center(
      child: Text("xx"),
    );
  }
}
点赞

发表回复

电子邮件地址不会被公开。必填项已用 * 标注