2020-02-09 20:25:10 +08:00

12 KiB
Raw Permalink Blame History

flutter 学习笔记

组件的使用

  • Text文字组件
    • textAlign: TextAlign.start, // 文本对齐方式
    • textDirection: TextDirection.ltr // 文本方向
    • maxLines:1 // 最大行数
    • textScaleFactor: 1.5, // 文字缩放
    • overflow: TextOverflow.ellipsis, // 超出处理
    • style:
      • TextStyle组件
        TextStyle(
          color: Colors.blue,
          fontSize: 18.0,
          height: 1.2,  
          fontFamily: "Courier",
          background: new Paint()..color=Colors.yellow,
          decoration:TextDecoration.underline,
          decorationStyle: TextDecorationStyle.dashed
        ),
      
    • 文本接合,多个textSpan对文本进行修饰然后拼合在一起
      Text.rich(TextSpan(
        children: [
          TextSpan(
            text: "https://flutterchina.club",
            style: TextStyle(
              color: Colors.blue
            ),  
            recognizer: _tapRecognizer
          ),
          ...
        ]
      ))
    
  • 按钮
    • RaisedButton // 悬浮按钮
    • FlatButton // 扁平按钮
    • OutlineButton // 默认有边框
    • IconButton // 可点击的icon
      • icon: Icon(Icons.thumb_up),
    • 前三个都可以加.icon然后属性变成iconlabel
    • 自定义
      const FlatButton({
        ...  
        @required this.onPressed, //按钮点击回调
        this.textColor, //按钮文字颜色
        this.disabledTextColor, //按钮禁用时的文字颜色
        this.color, //按钮背景颜色
        this.disabledColor,//按钮禁用时的背景颜色
        this.highlightColor, //按钮按下时的背景颜色
        this.splashColor, //点击时,水波动画中水波的颜色
        this.colorBrightness,//按钮主题,默认是浅色主题 
        this.padding, //按钮的填充
        this.shape, //外形
        @required this.child, //按钮的内容
      })
    
  • 图片
    • pubspec.yaml配置
        assets:
          - images/avatar.png
      
    • 加载图片
        Image(
          image: AssetImage("images/avatar.png"),
          width: 100.0
        );
        Image.asset("images/avatar.png",
          width: 100.0,
        )
        Image(
          image: NetworkImage(
              "https://avatars2.githubusercontent.com/u/20411648?s=460&v=4"),
          width: 100.0,
        )
        Image.network(
          "https://avatars2.githubusercontent.com/u/20411648?s=460&v=4",
          width: 100.0,
        )
        const Image({
          ...
          this.width, //图片的宽
          this.height, //图片高度
          this.color, //图片的混合色值
          this.colorBlendMode, //混合模式
          this.fit,//缩放模式
          this.alignment = Alignment.center, //对齐方式
          this.repeat = ImageRepeat.noRepeat, //重复方式
          ...
        })
      
  • ICON
    • Icon(Icons.accessible,color: Colors.green,),
    • 使用自定义字体图标链接
  • Switch开关组件
    • value: true
    • onChanged
  • Checkbox多选组件
    • value: true
    • onChanged
  • Stack层叠组件
    • 定位相对于父元素
    • alignment: Alignment.center // 总体控制
    • alignment: Alignment(0,0) // float(-1~1) 0,0居中
    • children: <Widget>[]
      • Align组件
        • alignment: Alignment.center // 单独控制
        • alignment: Alignment(0,0) // float(-1~1) 0,0居中
        • child: // 需要定位的子组件
      • Positioned组件
        • left, bottom, top, right // int 默认为0
        • child: // 需要定位的子组件image
  • AspectRatio组件
    • 默认横向占满父组件
    • 可以用来控制图片
    • aspectTatio: 2.0/1.0 // 宽高比
    • child: // 子组件
  • Card组件
    • margin: EdgeInsets.all(10) // 外边距
    • child: // 子组件
  • ClipOval组件
    • 可以用来裁剪原型头像
    • child: // 子组件
  • CircleAvatar组件
    • 感觉可以自适应头像大小
    • backgroungImage: NetworkImage('src')
  • RaisedButton组件
    • child: // 子组件
    • textColor: Theme.of(context).accentColor, // 文字颜色
    • textColor: Colors.red, // 文字颜色
    • onPressed: (){} // 点击事件
  • Warp组件
    • 相对于父组件横向占满
    • 可以自动换行
    • spacing: 10, // 元素和元素之间的距离
    • runSpacing: 10 // 元素在纵轴之间的距离
    • alignment: WarpAlignment.srart // 水平对齐方式
    • runAlignment: WarpAlignment.spaceAround // 纵向对齐方式
    • direction: Axis.vertical // 纵向排列
  • SizedBox组件
    • height: 30,
    • width:10,
    • 空白盒子
  • StatefullWidget
    • setState((){}) 修改需要刷新的内容,类似小程序的setData
  • Scaffold组件
    • appBar组件
      • title: Text('text') // 标题
      • backgroundColor: Colors.red // 背景颜色
      • leading: IconButton(icon: Icon(Icons.menu), onPressed:(){}) // 左边加东西
      • actions: <Widget>[] // 右边加东西
      • centerTitle: true // 不论是不是ios都给居中显示
      • 菜单栏
          DefaultTabController(
            length : 2, // tab的个数
            child: Scafford(
              appBar: AppBar(
                title: Text('title'),
                bottom: TabBar(
                  tabs: <Widget>[
                    Tab(text:'1'),
                    Tab(text:'2'),
                    Tab(text:'3'),
                  ]
                )
              ),
              body: TabBarView(
                children: <Widget>[
                  Text('text1'),
                  Text('text2'),
                  Text('text3'),
                ]
              )
            )
          )
        
        • TabBar组件
          • indicatorColor: Colors.red,
          • isScrollable: true // 允许滑动
          • tabs: <Widget>[]
            • Tab组件
              • text:"text"
        • TabBarView组件
          • children: <Widget>[]
    • body
    • bottomNavigationBar组件
      • currentIndex: 0, // 当前选中的tab
      • onTap: (int index){} // 点击事件,默认参数是点击了第几个按钮
      • items: <BottomNavigationBarItem>[] // 按钮内容
        • BottomNavigationBarItem组件
          • icon: Icon(Icons.home), // 图标
          • title: Text('主页') // 文字
    • floatingActionButton浮动按钮组件
      • child:
      • onPressed: (){}
  • Navigator路由跳转组件
      // 路由跳转
      Navigator.of(context).push(
        MaterialPageRoute(
          builder: (context)=> FormPage(参数)
        )
      )
      // 返回上一界面
      Navigator.of(context).pop()
      // 替换掉当前界面
      Navigator.of(context).pushReplacementNamed('/home')
      // 重置路由
      Navigator.of(context).pushAndRemoveUntil(
        new MaterialPageRoute(
          builder: (context) => new Tabs(index: 1),
        ),
        (route) => route == null
      )
    
    • MaterialPageRoute
      • WidgetBuilder builder // 是一个WidgetBuilder类型的回调函数它的作用是构建路由页面的具体内容返回值是一个widget。我们通常要实现此回调返回新路由的实例。
      • RouteSettings settings // 包含路由的配置信息,如路由名称、是否初始路由(首页)。
      • bool maintainState = true, // 默认情况下当入栈一个新路由时原来的路由仍然会被保存在内存中如果想在路由没用的时候释放其所占用的所有资源可以设置maintainState为false。
      • bool fullscreenDialog = false, // 表示新的路由页面是否是一个全屏的模态对话框在iOS中如果fullscreenDialog为true新页面将会从屏幕底部滑入而不是水平方向
  • MaterialApp
    • debugShowCheckedModeBanner: false // 去除斜着的debug标识
    • routes
        routes: {
          '/form': (context) => FromPage(),
          '/search': (context) => SearchPage(),
        }
      
        Navigator.pushNamed(context, '/search')
      
        // 在跳转到的路由的build方法里写
        var args=ModalRoute.of(context).settings.arguments;
        // 就可以传输参数了
        Naviagtor.pushNamed(context, '/search', arguments:{"id": 123});
      
        // 或者是定义路由的时候进行传参,这样就可以正常的使用了
        routes: {
          "tip2": (context){
            return TipRoute(text: ModalRoute.of(context).settings.arguments);
          },
        }, 
      
    • initialRoute: '/' // 初始化加载的路由
    • 对于路由的固定写法
        // Route.dart
        import 'package:flutter/material.dart';
        import '../pages/Tabs.dart';
        import '../pages/Search.dart';
        import '../pages/Form.dart';
      
        final Map<String, Function> routes = {
          '/':(contxt,{arguments})=>Tabs(),
          '/search':(contxt,{arguments}) =>SearchPage(arguments: arguments),
          '/form': (context,{arguments}) =>FormPage(arguments: arguments),
        };
      
        // 这个东西实际上是一个路由生成钩子只有在没有找到指定路由的时候才会被调用当前没有设置route所有的路由都会经过这个钩子进行处理这里也可以当成路由守卫判断各种权限然后进行路由的导航
        var onGenerateRoute=(RouteSettings settings) {
          // 统一处理
          final String name = settings.name;   
          final Function pageContentBuilder = routes[name];        
      
          if (pageContentBuilder != null) {
            if (settings.arguments != null) {
              final Route route = MaterialPageRoute(
                builder: (context) =>
                  pageContentBuilder(context, arguments: settings.arguments));
              return route;
            } else {
              final Route route = MaterialPageRoute(
                builder: (context) =>
                  pageContentBuilder(context));
              return route;
            }
          }
        };
        // main.dart
        import 'package:flutter/material.dart';
        import 'routes/Routes.dart';
        void main() => runApp(MyApp());
      
        class MyApp extends StatelessWidget {  
          @override
          Widget build(BuildContext context) {
            return MaterialApp(
              // home:Tabs(),
              initialRoute: '/',      
              onGenerateRoute: onGenerateRoute
            );
          }
        }
        // 路由跳转
        Naviagtor.pushNamed(context, '/search', arguments:{"id": 123});
      
  • 资源管理 pubspec.yaml
    flutter:
      assets:
        - assets/my_icon.png
        - assets/background.png
    
    assets指定应包含在应用程序中的文件 每个asset都通过相对于pubspec.yaml文件所在的文件系统路径来标识自身的路径。asset的声明顺序是无关紧要的asset的实际目录可以是任意文件夹在本示例中是assets文件夹
  • 在Widget树中获取State对象
    • 方法一
      // 直接通过of静态方法来获取ScaffoldState 
      ScaffoldState _state=Scaffold.of(context); 
      _state.showSnackBar(
        SnackBar(
          content: Text("我是SnackBar"),
        ),
      );
    
    • 方法二
      //定义一个globalKey, 由于GlobalKey要保持全局唯一性我们使用静态变量存储
      static GlobalKey<ScaffoldState> _globalKey= GlobalKey();
      ...
      Scaffold(
          key: _globalKey , //设置key
          ...  
      )
      _globalKey.currentState.openDrawer()
    
    GlobalKey是Flutter提供的一种在整个APP中引用element的机制。如果一个widget设置了GlobalKey那么我们便可以通过globalKey.currentWidget获得该widget对象、globalKey.currentElement来获得widget对应的element对象如果当前widget是StatefulWidget则可以通过globalKey.currentState来获得该widget对应的state对象。