Flutter 自定义底部导航分栏

image.png

自定义tabItem

import 'package:flutter/material.dart';

class GJTabItem extends StatefulWidget{

    //正常的图片
    final String iconNormal;
    //选中图片
    final String iconSelect;
    //正常文字颜色
    final Color titleColorNormal;
    //选中文字颜色
    final Color titleColorSelect;
    //文字
    final String title;
    //点击事件
    final GestureTapCallback onTap;
    //是否选中
    final bool selected;
  //初始化,传值
  const GJTabItem({Key key, this.iconNormal, this.iconSelect, this.titleColorNormal, this.titleColorSelect, this.title, this.onTap, this.selected}) : super(key: key);



  @override
  State createState() {
    // TODO: implement createState
    return GJTabItemState();
  }
}

class GJTabItemState extends State{
  @override
  Widget build(BuildContext context) {
    // TODO: implement build 布局
    return Expanded(

      child: GestureDetector(
        onTap: this.widget.onTap,
        child: Column(
          children: [
            new Image(image: new AssetImage(this.widget.selected?this.widget.iconSelect:this.widget.iconNormal), height: 30, width: 30,),
            new Text(this.widget.title, style: TextStyle(color: this.widget.selected ? this.widget.titleColorSelect: this.widget.titleColorNormal, fontSize: 14))
          ],
        )
      )
    );
  }

}

自定义tabBar

import 'package:flutter/material.dart';
import 'package:qum_huanzhe/routers/main/tabItem.dart';

class GJTabBar extends StatefulWidget {
  //标题数组
  final List titles;
  //为选中的图片数组
  final List iconNormals;
  //选中图片组
  final List iconSelects;
  //正常文字颜色
  final Color normalColor;
  //选中文字颜色
  final Color selectColor;
  //角标数字, 未画, 可以自己定义
  final int badgeNumber;
  //选中下标
  final int selectIndex;
  //点击事件selectIndex回调
  final callBack;
  const GJTabBar({
    Key key,
    @required this.titles,
    @required this.iconNormals,
    @required this.iconSelects,
    @required this.normalColor,
    @required this.selectColor,
    this.badgeNumber,
    @required this.selectIndex,
    @required this.callBack
  }) : assert(titles.length == iconSelects.length),
       assert(iconSelects.length == iconNormals.length),
        super(key: key);

  @override
  State createState() {
    // TODO: implement createState
    return GJTabBarState();
  }
}

class GJTabBarState extends State{
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return  tabItems();
  }

  Widget tabItems(){

    return Row(
      children: this.widget.titles.asMap().keys.map((index) => GJTabItem(
        iconNormal: this.widget.iconNormals[index],
        iconSelect: this.widget.iconSelects[index],
        title: this.widget.titles[index],
        titleColorNormal: this.widget.normalColor,
        titleColorSelect: this.widget.selectColor,
        selected: this.widget.selectIndex == index,
        onTap: (){
          buttonTap(index);
        },
      )).toList(),
    );
  }
  
  void buttonTap(index){
//    this.widget.index = index;
    widget.callBack(index);
  }
}

自定义tabPage:

import 'package:flutter/material.dart';
import 'package:qum_huanzhe/routers/home/homePage.dart';
import 'package:qum_huanzhe/routers/family/family.dart';
import 'package:qum_huanzhe/routers/shop/shop.dart';
import 'package:qum_huanzhe/routers/mine/mine.dart';
import 'package:qum_huanzhe/routers/main/tabBar.dart';
import 'package:qum_huanzhe/utitls/hexColor.dart';

class MainPage extends StatefulWidget {

  final String title;

  MainPage({Key key, this.title}): super(key: key);

  //页面
  final List viewPages = [
    HomePage(), FamilyPage(), ShopPage(), MinePage()
  ];
  //正常图片
  final List iconsNormal = [
    'assets/tab/normal/home_tab.png',
    'assets/tab/normal/family_tab.png',
    'assets/tab/normal/shop_tab.png',
    'assets/tab/normal/mine_tab.png'
  ];
  //选中图片
  final List iconsSelect = [
    'assets/tab/select/home_tab.png',
    'assets/tab/select/family_tab.png',
    'assets/tab/select/shop_tab.png',
    'assets/tab/select/mine_tab.png'
  ];
  //标题
  final List titles = [
    '首页',
    '家庭组',
    '商店',
    '我的'
  ];
  //正常文字颜色
  final Color normalColor = HexColor("#666666");
  //选中文字颜色
  final Color selectColor = HexColor("#7C5DC7");
  //默认选中, 可以在做成动态外界传进来
  var selectIndex = 0;
  @override
  MainPageState createState() {
    // TODO: implement createState
    return MainPageState();
  }

}


class MainPageState extends State with SingleTickerProviderStateMixin {

  PageController pageController;
  @override
  void initState() {
    // TODO: implement initState
    pageController = new PageController(initialPage: 0);
  }

  @override
  void dispose() {
    // TODO: implement dispose
    pageController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {

    //iphoneX 刘海屏
    final double topPadding = MediaQuery.of(context).padding.top;
    final double bottomPadding = MediaQuery.of(context).padding.bottom;
    // TODO: implement build
    return new Scaffold(
      body: PageView(
        physics: NeverScrollableScrollPhysics(), //不让滑动
        children: widget.viewPages,
        controller: pageController,
        onPageChanged: (index){
          
        },
      ),
      bottomNavigationBar: new Container(
          color: HexColor("#ffffff"),
          height: 49+bottomPadding,
          padding: EdgeInsets.fromLTRB(0, 2, 0, 0),
          child:  bottomTabs()
      ),


    );
  }

  Widget bottomTabs(){
    return GJTabBar(
      titles: this.widget.titles,
      iconNormals: this.widget.iconsNormal,
      iconSelects: this.widget.iconsSelect,
      normalColor: this.widget.normalColor,
      selectColor: this.widget.selectColor,
      selectIndex: this.widget.selectIndex,
      callBack: (value)=> change(value)
    );
  }

  change(val){
    print(val);
    setState(() {
      this.widget.selectIndex = val;
        pageController.jumpToPage(val);
    });
  }
}

页面initState多次触发问题

实现 AutomaticKeepAliveClientMixin
重写
@override
bool get wantKeepAlive => true;

import 'package:flutter/material.dart';

class HomePage extends StatefulWidget {
  HomePage({Key key, this.title}) : super(key: key);

  // This widget is the home page of your application. It is stateful, meaning
  // that it has a State object (defined below) that contains fields that affect
  // how it looks.

  // This class is the configuration for the state. It holds the values (in this
  // case the title) provided by the parent (in this case the App widget) and
  // used by the build method of the State. Fields in a Widget subclass are
  // always marked "final".

  final String title;

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

class HomePageState extends State with AutomaticKeepAliveClientMixin{
  int _counter = 0;
  @override
  bool get wantKeepAlive => true;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    print('initStateHome');
  }
  void _incrementCounter() {
    setState(() {

    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // ignore: argument_type_not_assignable
      appBar: new AppBar(title: new Text("home")),
      body: new Center(
        child: new Text('homePage')
      ),
    );
  }
}

你可能感兴趣的:(Flutter 自定义底部导航分栏)