学习Flutter的第二天(Scaffold)

2023-04-19  本文已影响0人  囧rg

2. Scaffold

2.1 AppBar

名称 功能
leading 标题前置控件。在首页通常显示应用程序的Logo,其它页面通常显示为返回按钮
title 页面标题。通常显示当前页面的标题文字,可以放组件
actions 标题后置控件。通常使用IconButton来表示,可以放按钮组
bottom 底部控件。通常用tabBar来表示放置Tab标签栏
backgroundColor 导航背景颜色
iconTheme 图标样式
textTheme 文字样式
centerTitle 标题是否居中显示
elevation 值是0.0 就是没有阴影
import 'package:flutter/material.dart';
import './pages/tabs.dart';

void main() {
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Flutter Demo",
      theme: ThemeData(primarySwatch: Colors.blue),
      home: Scaffold(
        appBar: AppBar(
          // 背景颜色
          backgroundColor: Colors.red,
          // 左侧按钮
          leading: IconButton(
              onPressed: () {
                print("左侧按钮");
              },
              icon: const Icon(Icons.menu)),
          // 右边按钮
          actions: [
            IconButton(
                onPressed: () {
                  print("setting");
                },
                icon: const Icon(Icons.settings)),
            IconButton(
                onPressed: () {
                  print("more");
                },
                icon: const Icon(Icons.more))
          ],
          title: const Text("Demo1"),
        ),
        body: const Text("sss"),
      ),
    );
  }
}

2.2 TabBar

TabBar是作为AppBar的一部分存在。参考文档 中提供了两种实现顶部TabLayout的方法,两者效果是一样的,但第二种功能更为丰富。具体为 TabBar + TabBarView两个weight结合。

名称 功能
tabs 标签组
controller 标签控制器
isScrollable 标签组是否可以滚动
indicatorColor 指示器的颜色
indicatorWeight 指示器高度
indicatorPadding 指示器的内边距
indicator 指标器装饰
indicatorSize 指示器的大小
labelColor 标签的颜色
labelStyle 标签的样式
labelPadding 标签的内边距
unselectedLabelColor 选中标签的颜色
unselectedLabelStyle 选中标签的样式

2.2.1 DefaultTabController

使用 DefaultTabController作为最外层控制器,联调 TabBar + TabBarView,这种方式简单方便,但致命缺点是拿不到当前选中tab的index。

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

  final String title;

  @override
  State<StatefulWidget> createState() => _FirstPageState();
}

/// DefaultTabController (TabBar + TabBarView) 使用 (内部还是TabController实现)
class _FirstPageState extends State<FirstPage> {
  final List<Tab> myTabs = <Tab>[
    Tab(text: '全部订单'),
    Tab(text: '已完成'),
    Tab(text: '未完成')
  ];

  @override
  Widget build(BuildContext context) {
    // 1. 使用 DefaultTabController 作为外层控制器
    return DefaultTabController(
      length: myTabs.length,// 定义tab数量
      child: Scaffold(
        appBar: AppBar(
          title: Text('FirstPage'),
          
          // 2. 使用 TabBar
          bottom: TabBar(
            tabs: myTabs // 定义TabWeight,若数量和定义不一致会报错
          ),
        ),
        
        // 3. 使用 TabBarView
        body: TabBarView(
            children: <Widget>[
        
              /// 全部订单
              Center(child: Text('全部订单')),
        
              /// 已完成订单
              Center(child: Text('已完成')),
        
              /// 未完成订单
              Center(child: Text('未完成'))
            ]),
      ),
    );
  }
}

2.2.2 TabController

实现SingleTickerProviderStateMixin,重写初始化和注销方法,利用控制器TabController管理和更多操作,其实第一种方法内部也是由TabController实现的。

// 1. 实现 SingleTickerProviderStateMixin 
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
  TabController _tabController;
  
  static const List<Tab> _homeTopTabList = <Tab>[
    Tab(text: '音乐', icon: Icon(Icons.music_note)),
    Tab(text: '体育', icon: Icon(Icons.directions_run)),
    Tab(text: '天气', icon: Icon(Icons.cloud_queue)),
    Tab(text: '科技', icon: Icon(Icons.toys))
  ];

  // 2. 初始化状态
  @override
  void initState() {
    super.initState();
    // TabController的滚动事件会触发一次监听, 点击事件会触发两次监听(一次是正常触发,一次是tab的动画触发)
    _tabController = TabController(length: _homeTopTabList.length, vsync: this);
    
    // 添加监听获取tab选中下标
    _tabController.addListener((){
      _currentTopTabIndex = _tabController.index;
    });
  }
  
  // 3. 注销状态
  @override
  void dispose() {
    _tabController.dispose();
    super.dispose();
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
          
          // 4. 添加TabBar
          bottom: TabBar(
            tabs: _homeTopTabList,
            controller: _tabController
          ),
        ),

        // 5. 添加TabBarView
        body: TabBarView(
          controller: _tabController,
          children: <Widget>[
            _tabMusic(context),
            _tabSport(context),
            _tabSport(context),
            _tabSport(context)
          ],
        ),
       );
  }

注:关于TabController 的监听有个坑 踩坑TabBar之TabController.addListener

2.1 bottomNavigationBar

BottomNavigationBarBottomNavigationBarItem 配合来共同展示Flutter里面的底部状态栏,底部状态栏是在移动端很重要的控件。

名称 功能
items 底部导航按钮集合
iconSize icon
currentIndex 默认选中第几个
onTap 选中变化回调函数
fixedColor 选中的颜色
type BottomNavigationBarType.fixed 或 BottomNavigationBarType.shifting

下面代码实现:点击底部的导航按钮,显示不同的页面

main.dart

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

void main() {
  runApp(const MyApp());
}

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

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

tabs.dart

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

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

  @override
  State<Tabs> createState() => _TabsState();
}

class _TabsState extends State<Tabs> {
  final List<Widget> _pages = const [Home(), Category(), Me()];

  int _currentIndex = 0;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Demo1"),
      ),
      body: _pages[_currentIndex],
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _currentIndex,
        onTap: (index) {
          setState(() {
            _currentIndex = index;
          });
        },
        items: const [
          BottomNavigationBarItem(icon: Icon(Icons.home), label: "首页"),
          BottomNavigationBarItem(icon: Icon(Icons.category), label: "分类"),
          BottomNavigationBarItem(icon: Icon(Icons.person), label: "我"),
        ],
        // 底部有4个,或者4个以上的时候才生效
        type: BottomNavigationBarType.fixed,
      ),
    );
  }
}

category.darthome.dartme.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("分类"),
    );
  }
}

2.2 floatingActionButton

用来实现悬浮按钮效果的

class ScffoldHomePage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return ScffoldHomePageState();
  }
}

class ScffoldHomePageState extends State<ScffoldHomePage> {

  ///当前选中的页面
  num index =0;

  @override
  Widget build(BuildContext context) {
    ///使用 Scaffold 组件来构建应用的基本页面
    /// 页面的架构
    return Scaffold(
      ///定义页面的标题
      appBar: AppBar(
        title: Text("这里是首页"),
      ),
      ///定义的页面的主体内容
      body:pageWidgetList[index],
      ///定义的悬浮按钮
      floatingActionButton: FloatingActionButton(
        child: Text("++"),
        ///点击响应事
        onPressed: () {
          print("点击了 FloatingActionButton");
        },
        ///长按提示
        tooltip: "点击了 tooltip s ",
        ///设置悬浮按钮的背景
        backgroundColor: Colors.red,
        ///获取焦点时显示的颜色
        focusColor: Colors.green,
        ///鼠标悬浮在按钮上时显示的颜色
        hoverColor: Colors.yellow,
        ///水波纹颜色
        splashColor: Colors.deepPurple,
        ///定义前景色 主要影响文字的颜色
        foregroundColor: Colors.black,
        ///配制阴影高度 未点击时
        elevation: 0.0,
        ///配制阴影高度 点击时
        highlightElevation: 20.0,
      ),
      ///用来控制  FloatingActionButton 的位置
      ///FloatingActionButtonLocation.endFloat 默认使用 浮动右下角
      ///FloatingActionButtonLocation.endDocked 右下角
      ///FloatingActionButtonLocation.endTop  右上角
      ///FloatingActionButtonLocation.startTop 左上角
      ///FloatingActionButtonLocation.centerFloat 底部中间浮动
      ///FloatingActionButtonLocation.centerDocked 底部中间不浮动
      floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
    );
  }
}

2.3 drawer

抽屉组件

import "package:flutter/material.dart";
 
 
class CategoryPage extends StatefulWidget {
    CategoryPage({Key key}) : super(key: key);
    _CategoryPageState createState() => _CategoryPageState();
}
 
class _CategoryPageState extends State<CategoryPage> {
    @override
    Widget build(BuildContext context) {
 
        return Scaffold(
            appBar: AppBar(
                title: Text("Flutter App"), 
            ),
            // 左侧抽屉
            drawer: Drawer(
                child: Text('左侧抽屉'), 
            ),
            // 右侧抽屉
            endDrawer: Drawer(
                child: Text('右侧抽屉'), 
            ), 
        );
    }
}
上一篇 下一篇

猜你喜欢

热点阅读