zoukankan      html  css  js  c++  java
  • 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
    

      



     

  • 相关阅读:
    (转载)SAPI 包含sphelper.h编译错误解决方案
    C++11标准的智能指针、野指针、内存泄露的理解(日后还会补充,先浅谈自己的理解)
    504. Base 7(LeetCode)
    242. Valid Anagram(LeetCode)
    169. Majority Element(LeetCode)
    100. Same Tree(LeetCode)
    171. Excel Sheet Column Number(LeetCode)
    168. Excel Sheet Column Title(LeetCode)
    122.Best Time to Buy and Sell Stock II(LeetCode)
    404. Sum of Left Leaves(LeetCode)
  • 原文地址:https://www.cnblogs.com/pythonClub/p/10559489.html
Copyright © 2011-2022 走看看