AppBar自定义顶部按钮图标、颜色

常见属性:

属性 描述
leading 在标题前面显示的一个控件,在首页通常显示应用的 logo;在其他界面通常显示为返回按钮
title 标题,通常显示为当前界面的标题文字,可以放组件
actions 通常使用 IconButton 来表示,可以放按钮组
bottom 通常放tabBar,标题下面显示一个 Tab 导航栏
backgroundColor 导航背景颜色
iconTheme 图标颜色
centerTitle 标题是否居中显示

Flutter AppBar结合TabBar实现顶部Tab切换

TabBar常见属性:

属性 描述
tabs 显示的标签内容,一般使用Tab对象,也可以是其他的Widget
controller TabController对象,控制tab切换和监听
isScrollable 是否可滚动
indicatorColor 指示器颜色
indicatorWeight 指示器高度
indicatorPadding 底部指示器的Padding
indicator 指示器decoration,例如边框等
indicatorSize 指示器大小计算方式,TabBarIndicatorSize.label 跟文字等宽,TabBarIndicatorSize.tab 跟每个tab等宽
labelColor 选中label颜色
labelStyle 选中label的Style
labelPadding 每个label的padding值
unselectedLabelColor 未选中label颜色
unselectedLabelStyle 未选中label的Style

Tabbar TabBarView实现类似头条顶部导航

混入SingleTickerProviderStateMixin

class _HomePageState extends State<HomePage> with
SingleTickerProviderStateMixin{}

定义TabController

late TabController _tabController;
void initState() {
    super.initState();
    _tabController = TabController(length: 8, vsync: this);
    _tabController.addListener(() {
        if (_tabController.animation!.value == _tabController.index) {
        print(_tabController.index); //获取点击或滑动页面的索引值
        }
    });
}

配置TabBar和TabBarView

import 'package:flutter/material.dart';
import 'package:flutter_application_1/user.dart';

import 'home.dart';
import 'category.dart';
import 'setting.dart';
import 'message.dart';

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

  @override
  State<TabsPage> createState() => _TabsPageState();
}

class _TabsPageState extends State<TabsPage> {
  int _currentIndex = 0;
  final List _pageList = [
    const HomePage(),
    const CategoryPage(),
    const MessagePage(),
    const SettingPage(),
    const UserPage(),
  ];
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: IconButton(
          icon: const Icon(Icons.menu),
          onPressed: (){
            print('menu');
          },
        ),
        title: const Text('Flutter App'),
        actions: [  
          IconButton(
            icon: const Icon(Icons.search),
            onPressed: (){
              print('search');
            },
          ),
          IconButton(
            icon: const Icon(Icons.settings),
            onPressed: (){
              print('settings');
            },
          ),
          ],
          backgroundColor: Colors.red,
      ),
      body: _pageList[_currentIndex],
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _currentIndex,
        type: BottomNavigationBarType.fixed, // 如果有4个以上的按钮,必须设置type 
        fixedColor: Colors.red, // 选中的颜色
        //iconSize: 35, // 图标大小
        onTap: (int index){
          print(index);
          setState(() {
            _currentIndex = index;
          });
        },
        items: const [
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            label: '首页',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.category),
            label: '分类',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.message),
            label: '消息',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.settings),
            label: '设置',
          ),
          // 我的
          BottomNavigationBarItem(
            icon: Icon(Icons.person),
            label: '我的',
          ),
        ],
      ),
      floatingActionButton: Container(
        width: 60,
        height: 60,
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(30),
          color: Colors.white,
        ),
        margin: const EdgeInsets.only(top: 4),
        padding: const EdgeInsets.all(4),
        child: FloatingActionButton(
          onPressed: (){
            setState(() {
              _currentIndex = 2;
            });
          },
          backgroundColor: _currentIndex == 2 ? Colors.red :Colors.blue,
          child: const Icon(Icons.add),
        ),
      ),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
    );
  }

}

grid

BottomNavigationBar 的页面中使用Tabbar 和 preferredSize组件

import 'package:flutter/material.dart';

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

  get list => null;

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin {
  late TabController _tabController;
  @override
  void initState() {
    super.initState();
    // 初始化
    _tabController = TabController(length: 19, vsync: this);
  }
  final List<String> list = [];
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: PreferredSize(
        preferredSize: const Size.fromHeight(40),
        child: AppBar(
          elevation: 1,
          title: SizedBox(
            height: 30,
            child: TabBar(
            controller: _tabController,
            indicatorColor: Colors.red,
            unselectedLabelColor: Colors.black,
            labelColor: Colors.red,
            indicatorSize: TabBarIndicatorSize.label,
            isScrollable: true,
            tabs: const [
              Tab(text: '热门'),
              Tab(text: '推荐'),
              Tab(text: '关注'),
              Tab(text: '收藏'),
              Tab(text: '视频'),
              Tab(text: '疫情'),
              Tab(text: '新闻'),
              Tab(text: '体育'),
              Tab(text: '娱乐'),
              Tab(text: '军事'),
              Tab(text: '科技'),
              Tab(text: '财经'),
              Tab(text: '汽车'),
              Tab(text: '房产'),
              Tab(text: '国际'),
              Tab(text: '时尚'),
              Tab(text: '旅游'),
              Tab(text: '历史'),
              Tab(text: '其他'),
            ],
          ),
          ),
          backgroundColor: Colors.white,
        )
      ),

      body: TabBarView(
        controller: _tabController,
        children: const [
          Center(child: Text('热门')),
          Center(child: Text('推荐')),
          Center(child: Text('关注')),
          Center(child: Text('收藏')),
          Center(child: Text('视频')),
          Center(child: Text('疫情')),
          Center(child: Text('新闻')),
          Center(child: Text('体育')),
          Center(child: Text('娱乐')),
          Center(child: Text('军事')),
          Center(child: Text('科技')),
          Center(child: Text('财经')),
          Center(child: Text('汽车')),
          Center(child: Text('房产')),
          Center(child: Text('国际')),
          Center(child: Text('时尚')),
          Center(child: Text('旅游')),
          Center(child: Text('历史')),
          Center(child: Text('其他')),
        ],
      )
    );
  }
}

grid

自定义KeepAliveWrapper 缓存页面

AutomaticKeepAliveClientMixin 可以快速的实现页面缓存功能,但是通过混入的方式实现不是很优 雅, 所以我们有必要对AutomaticKeepAliveClientMixin 混入进行封装

import 'package:flutter/material.dart';

class KeepAliveWrapper extends StatefulWidget {
  const KeepAliveWrapper(
      {Key? key, @required this.child, this.keepAlive = true})
      : super(key: key);
  final Widget? child;
  final bool keepAlive;
  @override
  State<KeepAliveWrapper> createState() => _KeepAliveWrapperState();
}

class _KeepAliveWrapperState extends State<KeepAliveWrapper>
    with AutomaticKeepAliveClientMixin {
  @override
  Widget build(BuildContext context) {
    return widget.child!;
  }

  @override
  bool get wantKeepAlive => widget.keepAlive;
  @override
  void didUpdateWidget(covariant KeepAliveWrapper oldWidget) {
    if (oldWidget.keepAlive != widget.keepAlive) {
// keepAlive 状态需要更新,实现在 AutomaticKeepAliveClientMixin 中
      updateKeepAlive();
    }
    super.didUpdateWidget(oldWidget);
  }
}

导入组件使用KeepAliveWrapper包裹需要缓存的页面

监听TabController改变事件

void initState() {
  super.initState();
  // 初始化
  _tabController = TabController(length: 19, vsync: this);
  // 监听_tabController的改变事件
  _tabController.addListener(() {
    if(_tabController.animation!.value == _tabController.index){
      print(_tabController.index); // 当前点击或者滑动的tab的下标
    }
  });
}

销毁事件

@override
void dispose() {
  _tabController.dispose();
  super.dispose();
}
import 'package:flutter/material.dart';
import 'package:flutter_application_1/tools/keepAliveWrapper.dart';

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

  get list => null;

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin {
  late TabController _tabController;
  @override
  void initState() {
    super.initState();
    // 初始化
    _tabController = TabController(length: 19, vsync: this);
    // 监听_tabController的改变事件
    _tabController.addListener(() {
      if(_tabController.animation!.value == _tabController.index){
        print(_tabController.index); // 当前点击或者滑动的tab的下标
      }
    });
  }

  // 销毁事件
  @override
  void dispose() {
    _tabController.dispose();
    super.dispose();
    print('销毁');
  }

  final List<String> list = [];
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: PreferredSize(
        preferredSize: const Size.fromHeight(40),
        child: AppBar(
          elevation: 1,
          title: SizedBox(
            height: 30,
            child: TabBar(
            controller: _tabController,
            indicatorColor: Colors.red,
            unselectedLabelColor: Colors.black,
            labelColor: Colors.red,
            indicatorSize: TabBarIndicatorSize.label,
            isScrollable: true,
            tabs: const [
              Tab(text: '热门'),
              Tab(text: '推荐'),
              Tab(text: '关注'),
              Tab(text: '收藏'),
              Tab(text: '视频'),
              Tab(text: '疫情'),
              Tab(text: '新闻'),
              Tab(text: '体育'),
              Tab(text: '娱乐'),
              Tab(text: '军事'),
              Tab(text: '科技'),
              Tab(text: '财经'),
              Tab(text: '汽车'),
              Tab(text: '房产'),
              Tab(text: '国际'),
              Tab(text: '时尚'),
              Tab(text: '旅游'),
              Tab(text: '历史'),
              Tab(text: '其他'),
            ],
          ),
          ),
          backgroundColor: Colors.white,
        )
      ),

      body: TabBarView(
        controller: _tabController,
        children: [
          KeepAliveWrapper(
            child: ListView(
            children: const[
              ListTile(
                title: Text('第一个tab1'),
              ),
              ListTile(
                title: Text('第一个tab2'),
              ),
              ListTile(
                title: Text('第一个tab3'),
              ),
              ListTile(
                title: Text('第一个tab4'),
              ),
              ListTile(
                title: Text('第一个tab5'),
              ),
              ListTile(
                title: Text('第一个tab6'),
              ),
              ListTile(
                title: Text('第一个tab7'),
              ),
              ListTile(
                title: Text('第一个tab8'),
              ),
              ListTile(
                title: Text('第一个tab9'),
              ),
              ListTile(
                title: Text('第一个tab10'),
              ),
              ListTile(
                title: Text('第一个tab11'),
              ),
              ListTile(
                title: Text('第一个tab12'),
              ),
              ListTile(
                title: Text('第一个tab13'),
              ),
              ListTile(
                title: Text('第一个tab14'),
              ),
              ListTile(
                title: Text('第一个tab15'),
              ),
              ListTile(
                title: Text('第一个tab16'),
              ),
              ListTile(
                title: Text('第一个tab17'),
              ),
              ListTile(
                title: Text('第一个tab18'),
              ),
              ListTile(
                title: Text('第一个tab19'),
              ),
            ],
          ),
          ),
          Center(child: Text('推荐')),
          Center(child: Text('关注')),
          Center(child: Text('收藏')),
          Center(child: Text('视频')),
          Center(child: Text('疫情')),
          Center(child: Text('新闻')),
          Center(child: Text('体育')),
          Center(child: Text('娱乐')),
          Center(child: Text('军事')),
          Center(child: Text('科技')),
          Center(child: Text('财经')),
          Center(child: Text('汽车')),
          Center(child: Text('房产')),
          Center(child: Text('国际')),
          Center(child: Text('时尚')),
          Center(child: Text('旅游')),
          Center(child: Text('历史')),
          Center(child: Text('其他')),
        ],
      )
    );
  }
}

MaterialApp 去掉debug图标

MaterialApp(
  debugShowCheckedModeBanner: false, //去掉debug图标
  home: TabsPage(),
);

results matching ""

    No results matching ""