Wigets学习之Material部件

作者:renzp94
时间:2021-06-28 11:18:38

Flutter 提供了一套 Material 部件,一般 Material 应用都是以MaterialApp这个部件开始的。

MaterialApp

  • title:标题,此标题是任务管理器中的标题
  • onGenerateTitle:动态设置标题,指定则使用返回的字符串,未指定则使用title
  • home:应用首页
  • initialRoute:初始路由
  • routes:路由列表
  • onGenerateRoute:动态路由构造函数
  • onGenerateInitialRoutes:如果提供了initialRoute,则作为初始路由的路由生成构造函数
  • onUnknownRoute:未找到指定的路由时跳转的路由
  • color:应用的主色
  • theme:浅色主题,可用Theme指定
  • darkTheme:深色主题
  • highContrastTheme:高对比浅色主题
  • highContrastDarkTheme:高对比深色主题
  • locale:多语言配置
  • debugShowMaterialGrid:是否显示调试网格,默认为false
  • showPerformanceOverlay:是否显示性能面板,默认为false
  • showSemanticsDebugger:是否显示报告可访问性的覆盖,默认为false
  • debugShowCheckedModeBanner:是否显示右侧顶部debug标签,开发环境默认为true
  • shortcuts:快捷键配置
  • actions:行为配置
import 'package:flutter/material.dart';

void main() {
  runApp(App());
}

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Material部件学习",
      home: Home(),
    );
  }
}

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Material部件'),
      ),
    );
  }
}

动态指定初始化路由

一般用于未登录时显示登录页,登录则显示首页

import 'package:flutter/material.dart';

void main() {
  runApp(App());
}

class App extends StatelessWidget {
  final bool isLogin = false;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '动态路由学习',
      initialRoute: '/',
      onGenerateInitialRoutes: (String name) {
        return [
          MaterialPageRoute(builder: (context) {
            if (isLogin) {
              return Page(title: '首页');
            } else {
              return Page(title: '登录');
            }
          })
        ];
      },
      routes: {
        '/': (BuildContext context) => Page(title: '首页'),
        '/login': (BuildContext context) => Page(title: '登录')
      },
    );
  }
}

class Page extends StatelessWidget {
  final String title;

  Page({Key? key, required this.title}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
    );
  }
}

Scaffold:Material风格布局

Scaffold布局提供了一些预留位置,比如:appBarbodyfloatingActionButtonbottomNavigationBar

  • appBar:顶部应用程序栏,通过AppBar指定
  • body:主体
  • backgroundColor:背景色
  • floatingActionButton:右底部悬停按钮
  • drawer:左侧抽屉,如果指定了,则在appBar左侧会出现一个菜单图标,点击之后可以在左侧打开抽屉
  • onDrawerChanged:抽屉显示改变事件,接受一个bool类型的参数,抽屉是否打开
  • endDrawer:右侧抽屉,如果指定了,则在appBar右侧会出现一个菜单图标,点击之后可以在右侧打开抽屉
  • drawerScrimColor:抽屉的遮罩颜色
  • drawerEdgeDragWidth:抽屉打开的默认宽度
  • bottomNavigationBar:底部tabbar,通过BottomNavigationBar指定
  • persistentFooterButtons:底部按钮组,在bottomNavigationBar上方显示
  • bottomSheet:底部区域,在persistentFooterButtons上方显示
  • resizeToAvoidBottomInsetbody和浮动小部件自动调整大小,避免键盘弹起遮挡,默认为true
  • primary:是否使用屏幕状态栏高度,如果为trueappBar的高度会扩展屏幕状态栏的高度,默认为true
  • drawerDragStartBehavior:设置抽屉拖动行为,DragStartBehavior.start: 检测拖动手势开始,DragStartBehavior.end:检测首次down事件开始,默认为DragStartBehavior.start
  • extendBody:是否扩展body,如果为true,则body则会充满除appBarbottomNavigationBar区域,默认为false
  • drawerEnableOpenDragGesture:是否可手势拖动打开左侧抽屉,默认为true
  • endDrawerEnableOpenDragGesture:是否可手势拖动打开右侧侧抽屉,默认为true
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(App());
}

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Material部件学习",
      home: Home(),
      theme: ThemeData(
          primaryColor: Colors.yellow,
          floatingActionButtonTheme: FloatingActionButtonThemeData(
              backgroundColor: Colors.yellow, foregroundColor: Colors.black)),
    );
  }
}

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Material部件'),
        ),
        body: Container(
          color: Colors.blue,
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () {},
          child: Icon(Icons.add),
        ),
        drawer: Container(
          width: 300,
          height: double.infinity,
          padding: EdgeInsets.all(24),
          color: Colors.white,
          child: Text('这是一个左侧抽屉'),
        ),
        onDrawerChanged: (bool isOpened) {
          print('左侧抽屉: $isOpened');
        },
        endDrawer: Container(
          width: 300,
          height: double.infinity,
          padding: EdgeInsets.all(24),
          color: Colors.white,
          child: Text('这是一个右侧抽屉'),
        ),
        onEndDrawerChanged: (bool isOpened) {
          print('右侧抽屉: $isOpened');
        },
        bottomSheet: Container(
          width: double.infinity,
          child: Text('这是bottomSheet区域'),
        ),
        persistentFooterButtons: [
          OutlinedButton(onPressed: null, child: Text('按钮1')),
          OutlinedButton(onPressed: null, child: Text('按钮2')),
          OutlinedButton(onPressed: null, child: Text('按钮3')),
          OutlinedButton(onPressed: null, child: Text('按钮4')),
        ],
        bottomNavigationBar: BottomNavigationBar(
          type: BottomNavigationBarType.fixed,
          items: [
            BottomNavigationBarItem(icon: Icon(Icons.home), label: "首页"),
            BottomNavigationBarItem(icon: Icon(Icons.camera), label: "圈子"),
            BottomNavigationBarItem(icon: Icon(Icons.weekend), label: "生活"),
            BottomNavigationBarItem(
                icon: Icon(Icons.shopping_bag), label: "返利优惠"),
            BottomNavigationBarItem(icon: Icon(Icons.person), label: "我的")
          ],
        ),
        backgroundColor: Colors.blue.shade50,
        drawerEdgeDragWidth: 20);
  }
}

AppBar

  • leading:应用程序栏左侧图标
  • leadingWidth:左侧宽度
  • automaticallyImplyLeading:是否尝试自动展示 leading 部件,如果leading没有指定,则此参数生效,为true时,如果指定了Scaffolddrawer则会leading会自动展示为一个菜单按钮,为false则不展示leading,除非指定leading
  • title:标题
  • centerTitle:标题是否居中,默认为false
  • titleSpacing:标题左右间距
  • titleTextStyle:标题样式
  • actions:右侧操作列表
  • flexibleSpace:绝对定位在屏幕状态栏和应用程序栏上,高度和应用程序栏高度相同
  • bottom:位于应用程序栏下的位置,一般用于放置tabBar
  • elevation:阴影
  • shadowColor:阴影颜色
  • backgroundColor:背景色
  • foregroundColor文本和图标默认颜色
  • iconTheme:图标主题
  • actionsIconTheme:操作列表图标主题
  • textTheme:文本主题
  • primary:与Scaffoldprimary一致
  • toolbarOpacity:应用程序栏透明度,默认为 1
  • bottomOpacitybottom透明度,默认为 1
  • toolbarHeight:应用程序栏高度
  • toolbarTextStyle:应用程序栏文本样式
import 'package:flutter/material.dart';

void main() {
  runApp(App());
}

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Material部件学习",
      home: Home(),
      theme: ThemeData(
          primaryColor: Colors.yellow,
          floatingActionButtonTheme: FloatingActionButtonThemeData(
              backgroundColor: Colors.yellow, foregroundColor: Colors.black)),
    );
  }
}

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        automaticallyImplyLeading: false,
        title: Text('Material部件'),
        titleSpacing: 0,
        actions: [
          IconButton(icon: Icon(Icons.search), onPressed: () {}),
          IconButton(icon: Icon(Icons.menu), onPressed: () {})
        ],
        bottom: PreferredSize(
          child: Text('bottom'),
          preferredSize: Size(30, 30),
        ),
      ),
      drawer: Container(
        color: Colors.white,
        height: double.infinity,
        width: 300,
        child: Text('asdsd'),
      ),
    );
  }
}

BottomNavigationBar

  • items:列表项(必填且 length>=2)
  • onTap:点击事件
  • currentIndex:当前激活项的索引,默认为 0
  • elevation:阴影
  • type:布局类型,默认为:BottomNavigationBarType.shifting(排列不开就隐藏),一般当超过三个之后需要将type指定为BottomNavigationBarType.fixed
  • fixedColor:当前激活项颜色,与selectedItemColor不能同时存在
  • backgroundColor:背景色
  • iconSize:图标大小,默认为 24
  • selectedItemColor:选中选项的颜色,与fixedColor不能同时存在
  • unselectedItemColor:未选中选项的颜色
  • selectedIconTheme:选中选项的图标主题
  • unselectedIconTheme:未选中选项的图标主题
  • selectedFontSize:选中选项文字大小,默认为 14
  • unselectedFontSize:未选中选项文字大小,默认为 12
  • selectedLabelStyle:选中项label样式
  • unselectedLabelStyle:未选中项label样式
  • showSelectedLabels:是否显示选中选项的label
  • showUnselectedLabels:是否显示未选中选项的label
import 'package:flutter/material.dart';

void main() {
  runApp(App());
}

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Material部件学习",
      home: Home(),
      theme: ThemeData(
          primaryColor: Colors.yellow,
          floatingActionButtonTheme: FloatingActionButtonThemeData(
              backgroundColor: Colors.yellow, foregroundColor: Colors.black)),
    );
  }
}

class Home extends StatefulWidget {
  Home({Key? key}) : super(key: key);

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

class _HomeState extends State<Home> {
  int _index = 0;

  static List<IconData> icons = [
    Icons.home,
    Icons.camera,
    Icons.shopping_bag,
    Icons.person
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Icon(
          icons[_index],
          size: 60,
        ),
      ),
      bottomNavigationBar: BottomNavigationBar(
        items: [
          BottomNavigationBarItem(icon: Icon(Icons.home), label: "首页"),
          BottomNavigationBarItem(icon: Icon(Icons.camera), label: "动态"),
          BottomNavigationBarItem(icon: Icon(Icons.shopping_bag), label: "购物车"),
          BottomNavigationBarItem(icon: Icon(Icons.person), label: "我的"),
        ],
        currentIndex: _index,
        onTap: (index) {
          setState(() {
            _index = index;
          });
        },
        type: BottomNavigationBarType.fixed,
      ),
    );
  }
}