• Flutter从零到∞学习笔记


    • 有状态widget:StatefulWidget和无状态widget:StatelessWidget 前者不需要实现Widget build(BuildContext context)。

      具体的选择取决于widget是否需要管理一些状态

    • 在Dart语言中使用下划线前缀标识符,会强制其变成私有的。

    • Icons.favorite Icons类里面有很多默认图标

    • isOdd 是否奇数 2.isOdd -> false 1.isOdd -> true

    • pushSaved “”开头的自动转成私有(方法和变量)

    • 导航栏添加按钮和事件

         @override
    
        Widget build(BuildContext context) {
    
          return new Scaffold(
    
            appBar: new AppBar(
    
              title: new Text('Startup Name Generator'),
    
              actions: <Widget>[
    
                // AppBar 添加一个按钮 样式为list 事件是_pushSaved
    
                new IconButton(icon: new Icon(Icons.list), onPressed: _pushSaved)
    
              ],
    
            ),
    
            body: _buildSuggestions(),
    
          );
    
        }
    
        // tooltip 长时间按下的提示文字
    
        IconButton(icon: new Icon(Icons.search), tooltip: 'Search', onPressed: null) 
    

      

    1. 界面跳转方法
        Navigator.of(context).push(
    
          new MaterialPageRoute(
    
              builder: (context) {
    
              },
    
          ),
    
        );
    

      

    1. 一行函数写法
        // 多行
    
        void main() {
    
          runApp(
    
              new Center(
    
                child: new Text(
    
                  'Hello, world!',
    
                  textDirection: TextDirection.ltr,
    
                ),
    
              )
    
          )
    
        }
    
        // 一行
    
        void main() => runApp(new MyApp());
    

      

    1. // Material 是UI呈现的“一张纸”

    2. 请确保在pubspec.yaml文件中,将flutter的值设置为:uses-material-design: true。这允许我们可以使用一组预定义Material icons。

    3. Row(横向排列)和Column(纵向排列)

        child: new Row(
    
          children: <Widget>[
    
            new ...,
    
            new ...,
    
            new ...,
    
          ],
    
        )
    

      

        child: new Column(
    
          children: <Widget>[
    
            new ...,
    
            new ...,
    
            new ...,
    
          ],
    
        ),
    

      

    1. cached_network_image 图片占位和淡入淡出

    2. push

        Navigator.push(
    
          context,
    
          new MaterialPageRoute(builder: (context) => new 新界面),
    
        );
    
        // 如果需要传值:
    
        新界面({Key key, @required this.接收字段的名字}) : super(key: key);
    
        pop
    
        Navigator.pop(context);
    

      

    1. dio网络请求 https://github.com/flutterchina/dio

    2. import 'dart:convert'; // package将响应内容转化为一个json Map

    3. // 使用fromJson工厂函数,将json Map 转化为一个Post对象

    new Post.fromJson(json);
    

      

    1. future参数是一个异步的网络请求

    2. import 'dart:io'; // 添加请求的headers

    3. // 长连接

    import 'package:web_socket_channel/io.dart';
    
    import 'package:multi_server_socket/multi_server_socket.dart';
    

      

    1. // 网络请求
    Future<Post> fetchPost() async {
    
      final response = await http.get('[http://jsonplaceholder.typicode.com/posts/1](http://jsonplaceholder.typicode.com/posts/1)');
    
      final responseJson = json.decode(response.body);
    
      return new Post.fromJson(responseJson);
    
    }
    
    // 请求添加headers
    
    /*
    
    Future<Post> fetchPost() async {
    
      final response = await http.get(
    
        '[https://jsonplaceholder.typicode.com/posts/1](https://jsonplaceholder.typicode.com/posts/1)',
    
        headers: {HttpHeaders.AUTHORIZATION: "Basic your_api_token_here"},
    
      );
    
      final json = jsonDecode(response.body);
    
      return new Post.fromJson(json);
    
    }
    
    */
    
    new FutureBuilder<Post>(
    
      future: fetchPost(),
    
      builder: (context, snapshot) {
    
        return new CircularProgressIndicator();
    
      }
    
    )
    

      

    1. 长连接
    // 连接长连接
    
    IOWebSocketChannel.connect('[ws://echo](ws://echo/).[websocket.org](http://websocket.org/)’)
    
    // 接收消息
    
    new StreamBuilder(
    
        stream: widget.channel.stream,
    
        builder: (context, snapshot) {
    
          return new Padding(
    
            child: new Text(snapshot.hasData ? '${snapshot.data}' : ''),
    
              padding: const EdgeInsets.symmetric(vertical: 20.0)
    
          );
    
        }
    
    )
    
    // 发送消息
    
    widget.channel.sink.add(_textController.text);
    
    // 关闭长连接
    
    widget.channel.sink.close();
    

      

    1. 在Flutter中添加资源和图片

    https://flutterchina.club/assets-and-images/

    1. 标准widget:
    Container
    
    添加 padding, margins, borders, background color, 或将其他装饰添加到widget.
    
    GridView
    
    将 widgets 排列为可滚动的网格.
    
    ListView
    
    将widget排列为可滚动列表
    
    Stack
    
    将widget重叠在另一个widget之上.
    
    Material Components:
    
    Card
    
    将相关内容放到带圆角和投影的盒子中。
    
    ListTile
    
    将最多3行文字,以及可选的行前和和行尾的图标排成一行
    

      

    1. pubspec.yaml中添加字体 注意缩进对齐 注意缩进对齐 注意缩进对齐
    -asset 路径是与pubspec.yaml平级的文件路径
    
    flutter:
    
      # Include the Material Design fonts.
    
      uses-material-design: true
    
      fonts:
    
        - family: Rock Salt
    
          fonts:
    
            # [https://fonts.google.com/specimen/Rock+Salt](https://fonts.google.com/specimen/Rock+Salt)
    
          - asset: fonts/Arial-Unicode.ttf
    
        - family: VT323
    
          fonts:
    
            # [https://fonts.google.com/specimen/VT323](https://fonts.google.com/specimen/VT323)
    
            - asset: fonts/Arial-Unicode.ttf
    
        - family: Ewert
    
          fonts:
    
            # [https://fonts.google.com/specimen/Ewert](https://fonts.google.com/specimen/Ewert)
    
            - asset: fonts/Ewert-Regular.ttf
    

      

    1. 比如一个关闭按钮在
    new Row(mainAxisAlignment: MainAxisAlignment.end, children: <Widget>[
    
      new FlatButton(onPressed: () {
    
      }, child: Icon(Icons.close))
    
    ],);
    

      

    1. 分割线
    new Divider(color: Colors.lightBlue,) 


    1. 自定义Icon
    new Image.asset(“图片路径",  20.0, height: 20.0,)


    1. 按钮宽高
    001、
    
    new Padding(padding: new EdgeInsets.fromLTRB(48.0, 20.0, 48.0, 20.0),
    
      child: new Row(
    
        children: <Widget>[
    
          new Expanded(child:
    
            new RaisedButton(onPressed: (){
    
            },
    
              //设置控件的高度
    
              child: new Padding(padding: new EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),
    
                child: new Text("登录",
    
                  style: TextStyle(color: Colors.white)
    
                ),
    
              ),
    
              color: Colors.brown,
    
            ),
    
          ),
    
        ],
    
      ),
    
    ),
    
    002、
    
    new Container(
    
       MediaQuery.of(context).size.width - 48 * 2 ,
    
      padding: new EdgeInsets.only(top: 40.0),
    
      child: new RaisedButton(onPressed: (){
    
      },
    
        //设置控件的高度
    
        child: new Padding(padding: new EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),
    
          child: new Text("登录",
    
              style: TextStyle(color: Colors.white)
    
          ),
    
        ),
    
        color: Colors.brown,
    
      ),
    
    ),
    
    003、
    
    Widget _bigButton(String text, double lSpace, double rSpace) {
    
      return new Container(
    
         MediaQuery.of(context).size.width - lSpace - rSpace,
    
        height: 48.0,
    
        margin: new EdgeInsets.only(left: lSpace, right: rSpace),
    
        color: Colors.white54,
    
        padding: new EdgeInsets.only(top: 0.0),
    
        child: new RaisedButton(onPressed: (){
    
          print(text);
    
        },
    
          child: new Padding(padding: new EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 0.0),
    
            child: new Text(text,
    
                style: TextStyle(color: Colors.white)
    
            ),
    
          ),
    
          color: Colors.brown,
    
        ),
    
      );
    
    }
    

      

    1. 设备尺寸
    MediaQuery.of(context).size.width
    

      

    1. 设备像素密度
    MediaQuery.of(context).devicePixelRatio
    

      

    1. 状态栏高度
    MediaQuery.of(context).padding.top
    

      

    1. 担心键盘挡住控件,可以使用 SingleChildScrollView,将SingleChildScrollView当做容器。

    2. 一个超级简单界面

    import 'package:flutter/material.dart';
    
    class RegisterPage extends StatelessWidget {
    
      @override
    
      Widget build(BuildContext context) {
    
        return new Scaffold(
    
          backgroundColor: Colors.black,
    
          body: new RegisterWidget(),
    
        );
    
      }
    
    }
    
    class RegisterWidget extends StatefulWidget {
    
      RegisterWidgetState createState() => RegisterWidgetState();
    
    }
    
    class RegisterWidgetState extends State<RegisterWidget> {
    
      @override
    
      Widget build(BuildContext context) {
    
        return new Text("RegisterPage", style: TextStyle(color: Colors.white),);
    
      }
    
    }
    

      

    1. Flutter 按钮总结
    · InkWell   // 纯文字按钮
    
    · OutLineButton   // 边框按钮
    
    · IconButton  // icon按钮
    
    · 
    

      

    1. import 'package:flutter/services.dart';
    TextField
    
    inputFormatters: <TextInputFormatter> [
    
      WhitelistingTextInputFormatter.digitsOnly,
    
    ],
    

      

     37 . 验证码按钮

    new Positioned(
    
        child: new Container(
    
           80.0,
    
          height: 27.0,
    
          alignment: Alignment.center,
    
          decoration: new BoxDecoration(
    
            border: new Border.all(
    
              color: Colors.white,
    
               1.0,
    
            ),
    
            borderRadius: new BorderRadius.circular(4.0),
    
          ),
    
          child: InkWell(
    
            child: _mText(_verifyStr, 12.0),
    
            onTap: () {
    
            },
    
          ),
    
        )
    
    ),
    

      

    1. 倒计时方法
    @override
    
    void dispose() {
    
      super.dispose();
    
      _cancelTimer();
    
    }
    
    _startTimer() {
    
      if (_verifyStr == '重新发送' || _verifyStr == '获取验证码') {
    
        _seconds = 5;
    
        _timer = new Timer.periodic(new Duration(seconds: 1), (timer) {
    
          if (_seconds == 0) {
    
            _cancelTimer();
    
            return;
    
          }
    
          _seconds--;
    
          _verifyStr = '$_seconds(s)';
    
          setState(() {});
    
          if (_seconds == 0) {
    
            _verifyStr = '重新发送';
    
          }
    
        });
    
      }
    
    }
    
    _cancelTimer() {
    
      _timer?.cancel();
    
    }
    

      

    1. 富文本拼接: 协议
    Widget _protocolWidget() {
    
      return new Container(
    
        child: new Row(
    
          children: <Widget>[
    
            new GestureDetector(
    
              onTap: () {
    
                print("选择");
    
              },
    
              child: Icon(Icons.add_alert, color: Colors.white),
    
            ),
    
            new Text.rich(
    
                new TextSpan(
    
                    text: '我已阅读并同意',
    
                    style: new TextStyle(
    
                      fontSize: 12.0,
    
                      color: Colors.grey[500],
    
                      fontWeight: FontWeight.w400,
    
                    ),
    
                    children: [
    
                      new TextSpan(
    
                        recognizer: new TapGestureRecognizer()
    
                          ..onTap = () {
    
                            print("《燎原用户服务协议》");
    
                          },
    
                        text: "《燎原用户服务协议》",
    
                        style: new TextStyle(
    
                          fontSize: 14.0,
    
                          color: Color(0XFFB57A36),
    
                          fontWeight: FontWeight.w400,
    
                        ),
    
                      )
    
                    ]
    
                )
    
            ),
    
          ],
    
        )
    
      );
    
    }
    

      

    1. 阴影、圆角
    new Card(
    
      elevation: 4.0,
    
      shape: new RoundedRectangleBorder(
    
        borderRadius: BorderRadius.only(
    
          topLeft: Radius.circular(16.0),
    
          topRight: Radius.circular(16.0),
    
          bottomLeft: Radius.circular(12.0),
    
          bottomRight: Radius.circular(2.0),
    
        )
    
      ),
    
      child: new IconButton(icon: Icon(Icons.add), onPressed: () {
    
      }),
    
    )
    

      

    1. YYTabbarWidget
    import 'package:flutter/material.dart';
    
    // with AutomaticKeepAliveClientMixin
    
    class YYTabbarWidget extends StatefulWidget {
    
      List<Widget> tabItems = [];
    
      Widget title;
    
      List<Widget> tabViews = [];
    
      PageController pageController;
    
      final ValueChanged<int> onPageChanged;
    
      final Widget drawer;
    
      YYTabbarWidget({Key key,
    
        this.drawer,
    
        this.tabItems,
    
        this.title,
    
        this.tabViews,
    
        this.pageController,
    
        this.onPageChanged,
    
      }) : super(key: key);
    
      _YYTabbarWidgetState createState() => _YYTabbarWidgetState(drawer, title, tabItems, tabViews, pageController, onPageChanged);
    
    }
    
    class _YYTabbarWidgetState extends State<YYTabbarWidget> with SingleTickerProviderStateMixin {
    
      final Widget _title;
    
      final List<Widget> _tabViews;
    
      final List<Widget> _tabItems;
    
      final ValueChanged<int> _onPageChanged;
    
      final Widget _drawer;
    
      _YYTabbarWidgetState(
    
          this._drawer,
    
          this._title,
    
          this._tabItems,
    
          this._tabViews,
    
          this._pageController,
    
          this._onPageChanged,
    
          ) : super();
    
      TabController _tabController;
    
      PageController _pageController;
    
      @override
    
      void initState() {
    
        super.initState();
    
        _tabController = new TabController(length: _tabItems.length, vsync: this);
    
      }
    
      @override
    
      void dispose() {
    
        _tabController.dispose();
    
        super.dispose();
    
      }
    
      _renderTab() {
    
        print(_tabItems);
    
        List<Widget> list = new List();
    
        for (int i = 0; i < _tabItems.length; i++) {
    
          list.add(new FlatButton(onPressed: () {
    
            print(i);
    
            _pageController.jumpTo(MediaQuery
    
                .of(context)
    
                .size
    
                .width * i);
    
          }, child: _tabItems[I],
    
          )
    
          );
    
        }
    
        return list;
    
      }
    
      @override
    
      Widget build(BuildContext context) {
    
        return new Scaffold(
    
          drawer: _drawer,
    
          appBar: new AppBar(
    
            title: _title,
    
          ),
    
          body: new PageView(
    
            controller: _pageController,
    
            children: _tabViews,
    
            onPageChanged: (index) {
    
              _tabController.animateTo(index);
    
              _onPageChanged?.call(index);
    
            },
    
        ),
    
          bottomNavigationBar: new Material(
    
            color: Colors.white,
    
            child: new TabBar(
    
              indicatorPadding: new EdgeInsets.only(top: 0.0),
    
              controller: _tabController,
    
              tabs: _renderTab(),
    
              indicatorColor: Colors.red,
    
            ),
    
          ),
    
        );
    
      }
    
    }
    

      

    1. ListView 添加刷新,当数量少的时候不能滚动
    physics: new AlwaysScrollableScrollPhysics(), // 让ListView一直可以滚动
    

      

    1. tabView切换 子界面都会调用initState
    解决:AutomaticKeepAliveClientMixin
    
    class HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin {
    
        @override
    
        bool get wantKeepAlive => true;
    
    }
    

      

    1. 路有跳转
    ///不带参数的路由表跳转
    
    Navigator.pushNamed(context,routeName);
    
    ///跳转新页面并且替换,比如登录页跳转主页
    
    Navigator.pushReplacementNamed(context,routeName);
    
    ///跳转到新的路由,并且关闭给定路由的之前的所有页面
    
    Navigator.pushNamedAndRemoveUntil(context,'/calendar',ModalRoute.withName('/'));
    
    ///带参数的路由跳转,并且监听返回
    
    Navigator.push(context,newMaterialPageRoute(builder:(context)=>newNotifyPage())).then((res){
    
          ///获取返回处理
    
        });
    

      

    1. flutter lib
    cupertino_icons: ^0.1.2  #icon
    
    flutter_spinkit: "^2.1.0"  # load more loading  import 'package:flutter_spinkit/flutter_spinkit.dart';
    
    dio: x.x.x  #无网络请求  import 'package:dio/dio.dart';
    

      

    1. dio网络请求示例
    _dioRequest() async {
    
      Dio dio = new Dio();
    
      Response response;
    
      try {
    
        String url;
    
        var params; // 请求参数
    
        Options options; // 配置:超时,请求头,请求类型等
    
        response = await dio.request(url, data: params, options: options);
    
      } on DioError catch(e) {
    
        // 请求出错时,返回一个DioError对象
    
      }
    
    }
    

      

    1. build_runner的使用
    1、在根目录运行
    
    2、一次性创建.g.dart文件 使用build 此时目录内不能有.g.dart文件
    
    3、watch是监听 有model类的文件创建 自动创建.g.dart文件
    
    flutter packages pub run build_runner build
    
    flutter packages pub run build_runner watch
    

      



     

  • 相关阅读:
    Jmeter+ant+jenkin接口自动化发邮件
    BadBoy 参数化录制,并导入JMeter
    Jmeter 移动端录制
    Pytest 操作
    Pytest框架简介与安装
    Fiddler iOS抓包
    Fiddler Android APP 抓包
    random的使用
    scanner的使用与匿名对象的使用
    标准的类,API的初步使用
  • 原文地址:https://www.cnblogs.com/pythonClub/p/10559489.html
Copyright © 2020-2023  润新知