Fiutter- 案例2 (Home页面)

前言

Home页面是通过BottomNavigationBar去进行切换的,当BottomNavigationBar选中第一个的时候则会打开我们的Home页面

Home页面

微信图片_20220604120715.jpg

创建Home页面

首先需要创建Home页面在BottomNavigationBar切换到第一个的时候展示,而且在实际使用中,我们不希望每次切换到HomePage都创建一个新的,而是需要它持久化,所以我们的Body部分需要使用到PageView

创建一个空的HomePage

class HomePage extends StatefulWidget {

  @override
  State<StatefulWidget> createState() {
    return HomePageState();
  }
}

class HomePageState extends State with SingleTickerProviderStateMixin {

  @override
  Widget build(BuildContext context) {
    return Text('Home');
  }

}

修改下之前创好的Mainpage

class MainPage extends StatefulWidget {
  final String title;
  @override
  _MainPageState createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  int currentIndex = 0;

  var _pageController = PageController();

  var pages = <Widget>[
    HomePage(),
    Text('1'),
    Text('2'),
    Text('3'),
    Text('4'),
  ];

  void onNavigationChanged(int index) {
    setState(() {
      currentIndex = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    // This method is rerun every time setState is called, for instance as done
    // by the _incrementCounter method above.
    //
    // The Flutter framework has been optimized to make rerunning build methods
    // fast, so that you can just rebuild anything that needs updating rather
    // than having to individually change instances of widgets.

    return Scaffold(
      body: PageView.builder(
        physics: NeverScrollableScrollPhysics(),
        itemBuilder: (context, index) => pages[index],
        controller: _pageController,
        itemCount: pages.length,
        onPageChanged: onNavigationChanged,
      ),
      bottomNavigationBar: BottomNavigationBar(
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(icon: Icon(Icons.home), label: '首页'),
          BottomNavigationBarItem(icon: Icon(Icons.book), label: '书影音'),
          BottomNavigationBarItem(icon: Icon(Icons.group), label: '小组'),
          BottomNavigationBarItem(icon: Icon(Icons.store), label: '市集'),
          BottomNavigationBarItem(icon: Icon(Icons.person), label: '我')
        ],
        currentIndex: currentIndex,
        unselectedItemColor: Colors.grey,
        selectedItemColor: Colors.green,
        type: BottomNavigationBarType.fixed,
        onTap: (index){
          _pageController.jumpToPage(index);
        },
      ),
    );
  }
}

其中currentIndex表示BottomNavigationBar当前切换到位置的一个状态

使用PageView.builder去构建一个PageView
physics: NeverScrollableScrollPhysics()表示不允许左右滑动
itemBuilder表示当前PageView需要根据Index显示什么内容,这里的index指的是PageView
itemCount表示页面的数量
onPageChanged 表示当页面改变的时候会回调的函数,我们设置了不能滑动,所以页面切换只能是手动的

BottomNavigationBar中的onTap我们通过PageController手动切换了PageView的页面

此时当BottomNavigationBar默认选中第一个的时候就会打开HomePage(),并且重复切换不会创建新的HomePage实例,这样就可以保存HomePage的状态

HomePage

AppBar
顶部是使用AppBar构成的,并且可以左右切换的动态,推荐也是AppBar的一部分,所以我们首先需要对AppBar进设置

class HomePageState extends State with SingleTickerProviderStateMixin,AutomaticKeepAliveClientMixin {
  TabController? _tabController;
  
  @override
  void initState() {
    super.initState();
    _tabController = TabController(length: 2, vsync: this);
  }

  @override
  void dispose() {
    _tabController?.dispose();
    super.dispose();
  }

  AppBar homePageAppBar() {
    return AppBar(
        backgroundColor: Colors.white,
        elevation: 1,
        leading: Icon(Icons.menu, color: Colors.green),
        actions: [
          Container(
            alignment: Alignment.center,
            child: Icon(Icons.mail_outline, color: Colors.green),
            padding: EdgeInsets.only(left: 16, right: 16),
          )
        ],
        centerTitle: true,
        titleSpacing: 0,
        title: GestureDetector(
          child: Container(
            height: 35,
            alignment: Alignment.center,
            decoration: BoxDecoration(
                borderRadius: BorderRadius.all(Radius.circular(10)),
                color: Color(0x12000000)),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Icon(
                  Icons.search,
                  color: Colors.black26,
                ),
                Text('绝命律师 第六季',
                    style: TextStyle(color: Colors.black26, fontSize: 15))
              ],
            ),
          ),
          onTap: () => {},
        ),
        bottom:   PreferredSize(
            preferredSize: const Size.fromHeight(45),
            child: Container(
                alignment: Alignment.centerLeft,
                child: TabBar(
                  isScrollable: true,
                  controller: _tabController,
                  labelColor: Colors.black,
                  indicatorColor: Colors.black,
                  indicatorSize: TabBarIndicatorSize.label,
                  labelStyle:
                  TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
                  unselectedLabelStyle:
                  TextStyle(fontSize: 20, fontWeight: FontWeight.normal),
                  labelPadding: EdgeInsets.only(left: 20, right: 20),
                  tabs: [Tab(text: '动态'), Tab(text: '推荐')],
                ))));
  }

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return Scaffold(
        appBar: homePageAppBar(),
        body: TabBarView(
          children: [Tab(text: '动态'), Tab(text: '推荐')],
          controller: _tabController,
        ));
  }

  @override
  bool get wantKeepAlive => true;
}

homePageAppBar函数是用来返回一个AppBar的对象,分别设置了这些主要属性

backgroundColor 背景颜色
elevation 阴影高度
leading 左边widget
actions 右边的widget
titleSpacing title左右的距离
centerTitle title是否居中
title title的widget

还有一个比较重要的bottm属性是用来设置TabBar的样式,我们一般也可以直接返回一个TabBar默认是直接横向撑开并且居中的,但是由于我们的TabBar是一个居左的样式所以做了个限定

Body
Body部分就属于TabBar的切换内容,所以在body部分直接使用了可以合TabBar联动的TabBarView即可,他们使用一个相同的Controller

欢迎关注Mike的简书

Android 知识整理

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,475评论 4 372
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,744评论 2 307
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,101评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,732评论 0 221
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,141评论 3 297
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,049评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,188评论 2 320
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,965评论 0 213
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,716评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,867评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,341评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,663评论 3 263
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,376评论 3 244
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,200评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,990评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,179评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,979评论 2 279

推荐阅读更多精彩内容