dart_darts - CSDN
dart 订阅
DART(Dynamic Advertising Reporting Targeting) “动态广告报告与目标定位”,是一种热解析和离子化技术。DART-MS(Direct analysis in real time mass spectrometry)实时直接分析质谱 展开全文
DART(Dynamic Advertising Reporting Targeting) “动态广告报告与目标定位”,是一种热解析和离子化技术。DART-MS(Direct analysis in real time mass spectrometry)实时直接分析质谱
信息
外文名
Direct Analysis in Real Time
类    型
是一种热解析和离子化技术
中文名
DART
中文全称
实时直接分析
DART基本信息
DoubleClick的核心技术,允许各网站及网络通过他们的中央服务器管理他们各自的广告服务及统计报告。依靠部署在全球的广告服务器及独特的分布式系统架构,DART系统提供的可升级性、可靠性及强大功能使该系统能够发布更多的广告。(DoubleClick公司主要从事网络广告管理软件开发与广告服务,对网络广告活动进行集中策划、执行、监控和追踪)新的结构化Web编程语言二、 实时直接分析(Direct Analysis in Real Time)简称DART,是一种热解析和离子化技术。DART操作简单,样品置放于DART源出口和一台LC-MS质谱仪的离子采样口,便可进行分析。适用于分析液、固、气态的各类型样品由美国J. Laramee和R. Cody(美JEOL公司)于2005年发明,现由IonSense公司商品化生产、制造和销售。获得2005年Pittcon大奖。DART已广泛应用于药物发现与开发(ADME)、食品药品安全控制与检测、司法鉴定、临床检验、材料分析、天然产品品质鉴定、及相关化学和生物化学等领域。相比于现行通用的液质联用(LC-MS)技术,DART-MS分析将不再需要繁杂的样品制备和耗时的色谱分离。作为一种“绿色”分析检测技术,DART-MS将不需要化学溶剂的消耗,急剧缩短样品分析周期,和极大地减少对固定资产及人员的投资。该技术在美欧等国的研究与应用已成燎原之势,并在著名大学(如Purdue,Rice,George Washington,U Maryland)、研究院(如Los Almos NL,NRCC Canada,US Army)、跨国制药公司(如Roche,Merck,Amgen,GSK,Pfizer,Eli Lilly)、国家执法部门(如FBI,FDA,EPA)等相继采用。
收起全文
精华内容
参与话题
  • Dart语言——45分钟快速入门(上)

    万次阅读 多人点赞 2020-06-09 20:52:34
    文章目录环境准备安装Dart SDK配置环境变量配置 VSCode 编辑器测试环境基础语法代码注释内置数据类型变量与常量定义变量定义常量内置类型的常用操作数值类型字符串布尔类型列表映射函数定义函数函数的参数命名可选...

    前言

    谷歌推出Flutter跨平台UI框架后,对移动端的开发又产生了新的影响,Flutter采用Dart语言开发,而Flutter为什么选择Dart语言作为唯一的开发语言呢?总的来说,其拥有如下优势

    • Dart可基于AOT(Ahead Of Time)编译,即编译成平台的本地代码,运行性能高。
    • Dart也可基于JIT(Just In Time)编译,编译快速,可热加载,使开发周期加倍提升(Flutter亚秒级有状态热重载)
    • Dart可以更轻松地创建以60fps运行的流畅动画和转场。Dart在没有锁的情况下进行对象分配和垃圾回收
    • Dart语法结合Java与JavaScript语法特点,几乎没有令人不适的怪异语法,使Java程序员倍感亲切,快速上手

    通常来说一门语言要么使用AOT编译,编译慢,开发效率低,或者使用JIT编译,在运行时编译,虽然可以热重载,但是执行效率低,而Dart在这两种之间做出了完美平衡,当开发时使用JIT编译,调试快,所见即所得,开发效率高,当发布时,使用AOT编译,编译成目标平台的本地代码,执行效率高。

    视频课程

    博主发布的相关视频课程

    Flutter全栈式开发之Dart 编程指南
    二维码

    Flutter 全栈式开发指南
    快速上手篇可试看

    环境准备

    安装Dart SDK

    官方下载地址
    共有三种SDK版本选择

    • Flutter
    • Web
    • Server

    本章仅作为Dart编程语法学习,这里建议安装Server版的SDK,然后选择Windows版本进行下载。

    配置环境变量

    在Windows上,通过点击下一步即可安装,安装完成后,需将dart-sdk下的的bin目录添加到系统Path环境变量中。这一步骤是通常的命令配置步骤。

    配置 VSCode 编辑器

    作为Dart语言的学习,不建议下载笨重的IDE,官方提供支持VSCode 编辑器插件,建议使用VSCode 学习。

    官网下载 VSCode编辑器,安装完成后,启动VSCode并在插件商店中搜索Dart进行插件安装。

    测试环境

    在VSCode中新建一个test.dart文件,编写如下代码

    void  main(){
        print("hello world!");
    }
    

    运行后成功在控制台输出hello world!

    基础语法

    代码注释

    Dart中的代码注释基本与Java语言相同

    // 单行注释
    
    /*
     * 多行注释
     */
    
    /**
     * 文档注释
     */
    
    /// 使用三个斜杠开头
    /// 这是Dart特有的文档注释
    

    内置数据类型

    在这里插入图片描述

    在Dart中,所有能够使用变量引用的都是对象,每个对象都是一个类的实例。数字、函数和 null 也都是对象。所有的对象都继承于Object类。

    要注意,没有初始化的变量默认值为 null。数值类型变量的默认值也是 null

    数值类型num有两个具体子类,分别为intdouble,其中int为整数值,范围是-2^532^53之间;double则是64位的双精度浮点数。

    变量与常量

    定义变量

    Dart中定义变量有两种方式,一种是静态类型语言常用的方式,显式指定变量类型,另一种则是动态语言的常用方式,不指定类型,由vm自动推断。

    // 1.通过显式指定类型来定义变量
    String name = "张三";
    num age = 18;
    
    // 2.使用关键字var,不指定类型
    var address = "深南大道";
    var id = 100;
    
    /* 使用var定义变量,即使未显式指定类型,一旦赋值后类型就被固定
     * 因此使用var定义的变量不能改变数据类型
     */
    var number = 19;
    // 以下代码错误,无法运行,number变量已确定为int类型
    number = "2019";
    

    如想动态改变变量的数据类型,应当使用dynamicObject来定义变量。

    // dynamic声明变量
    dynamic var1 = "hello";
    var1 = 19;
    print(var1);    // 19
    
    // Object声明变量
    Object var2 = 20;
    var2 = "Alice";
    print(var2);    // Alice
    

    建议在编写代码时,尽可能显式指定变量类型,这样可以提升代码可读性与调试的便利性。

    定义常量

    Dart中定义常量也有两种方式,一种使用final关键字,同Java中的用法, 一个 final 变量只能赋值一次;另一种是Dart的方式,使用const关键字定义。

    // 1.使用final关键字定义常量
    final height = 10;
    
    // 2.使用const关键字定义常量
    const pi = 3.14;
    

    需要注意,final定义的常量是运行时常量,而const常量则是编译时常量,也就是说final定义常量时,其值可以是一个变量,而const定义的常量,其值必须是一个字面常量值。

    final time = new DateTime.now(); // 正确
    const time = new DateTime.now(); // 错误
    
    
    const list = const[1,2,3];       // 正确
    const list = [1,2,3];            // 错误
    

    内置类型的常用操作

    数值类型

    // String 转 int
    var one = int.parse('1');
    
    // String 转 double
    var onePointOne = double.parse('1.1');
    
    // int 转 String
    String oneAsStr = 1.toString();
    
    // double 转 String
    String piAsStr = 3.14159.toStringAsFixed(2); // 保留两位 '3.14'
    
    // Dart也支持整数位操作,<<、 >>、&、|
    print((3 << 1) == 6);  // 0011 << 1 == 0110
    print((3 >> 1) == 1);  // 0011 >> 1 == 0001
    print((3 | 4)  == 7);  // 0011 | 0100 == 0111
    

    字符串

    值得一提的是,Dart中提供的字符串插值表达式使字符串格式化变得异常方便。

    // 1.Dart可以使用单引号或双引号来创建字符串
    var s1 = "hello";
    var s2 = 'world';
    
    // 2.类似Python,Dart可以使用三引号来创建包含多行的字符串
    var multiLine1 = """你可以像这样,创建一个
    包含了多行的字符串内容
    """;
    
    var multiLine2 = '''你也可以使用三个单引号,创建一个
    包含了多行的字符串内容
    ''';
    
    // 3.类似Python,还可以在字符串字面值的前面加上`r`来创建原始字符串,则该字符串中特殊字符可以不用转义
    var path = r'D:\workspace\code';
    
    // 4.Dart支持使用"+"操作符拼接字符串
    var greet = "hello" + " world";
    
    // 5.Dart提供了插值表达式"${}",也可以用于拼接字符串
    var name = "王五";
    var aStr = "hello,${name}";
    print(aStr);    // hello,王五
    
    // 当仅取变量值时,可以省略花括号
    var aStr2 = "hello,$name"; // hello,王五
    
    // 当拼接的是一个表达式时,则不能省略花括号
    var str1 = "link";
    var str2 = "click ${str1.toUpperCase()}";
    print(str2);   // click LINK
    
    // 6. 与Java不同,Dart使用"=="来比较字符串的内容
    print("hello" == "world");
    

    布尔类型

    Dart中的布尔类型用法同Java,仅有falsetrue两个值,不能使用0、非0或者null、非null来表达falsetrue。与Java不同的是,布尔类型的默认值为null

    bool flags;
    print(flags);    // null
    

    列表

    Dart中列表操作与JavaScript中的数组相似。

    // 创建列表
    var list = [1, 2, 3];
    // 下标从0开始。使用length可以访问list的长度
    print(list[0]);
    print(list.length);
    
    // 可以使用add添加元素
    list.add(5);
    
    // 可在list字面量前添加const关键字,定义一个不可改变的 列表(编译时常量)
    var constantList = const [1, 2, 3];
    constantList[1] = 1;     // 报错
    

    映射

    又称为关联数组,相当于Java中的HashMap

    // 1.通过字面量创建Map
    var gifts = {
      'first' : 'partridge',
      'second': 'turtledoves',
      'fifth' : 'golden rings'
    };
    
    // 2.使用Map类的构造函数创建对象
    var pic = new Map();
    // 往Map中添加键值对
    pic['first'] = 'partridge';
    pic['second'] = 'turtledoves';
    pic['fifth'] = 'golden rings';
    
    // 3.获取Map的长度
    print(pic.length);
    
    // 4.查找Map
    pirnt(pic["first"]);
    print(pic["four"]);    // 键不存在则返回 null
    

    函数

    在Dart中,函数(或方法) 也是对象,它的类型是 Function。 这意味着,函数可以赋值给变量,也可以当做其他函数的参数。

    定义函数

    Dart中定义函数,基本上与Java类似

    String greet(String name){
        return "hello,$name";
    }
    

    在Dart中,类型是可选,可以省略显式的类型,但仍然建议显式指定类型。

    greet(name){
        return "hello,$name";
    }
    

    要注意,函数也是对象,所有函数都有返回值。当没有指定返回值的时候,函数会返回null。当然,如果你强行使用void来修饰函数,则函数真的没有返回值,这种情况就另当别论了。

    函数的参数

    Dart中支持两种可选参数

    • 命名可选参数
    • 位置可选参数

    在Java中通常使用方法重载来实现同名方法的不同参数调用,Dart中则可以通过可选参数来实现相同效果。

    命名可选参数

    先来看一下命名参数,它使用花括号来定义参数列表

    // 定义一个函数,参数列表用花括号包裹
    enableFlags({bool bold, bool hidden}) {
        // do something
    }
    
    // 调用方式,传参时使用"参数名:值"的形式
    enableFlags(hidden:true,bold:false);
    

    如果在定义函数时,给参数列表中的参数设置默认值,则该参数就是可选的,函数调用时可以忽略该参数,使用默认的值。

    // 定义add函数
    add({int x, int y=1, int z=0}){
        print(x + y + z;
    }
    
    // 调用
    add(x:18);              // 19
    add(x:18, y:2, z:10);   // 30
    

    这里需要注意一下,SDK 1.21之前的版本中,命名参数不能使用=号来设置默认值,而SDK 1.21之后,只能使用=号来设置默认值。因此,请检查并升级SDK版本。

    位置可选参数

    位置可选参数使用中括号来定义参数列表,中括号中的参数是可选的

    // 定义add函数
    add(int x, [int y, int z]){
        int result = x;
        if (y !=  null){
            result = result + y;
        }
    
        if (z !=  null){
            result = result + z;
        }
        print(result);
    }
    
    // 调用
    add(18);           // 18
    add(18,12);        // 30
    add(18, 12, 15);   // 45
    

    位置可选参数设置默认值

    // 定义add函数
    add(int x, [int y=0, int z=0]){
        print(x +y+z);
    }
    

    最后需要注意一下命名可选参数位置可选参数的区别,前者中的参数与顺序无关,无需按顺序传参,且传参数时需使用冒号;后者与顺序相关,传参必须依照顺序。

    匿名函数

    大部分函数都有名字,但我们也可以创建没有名字的函数,称为匿名函数,也被称为lambda表达式或者闭包。

    // 定义匿名函数,并将其赋值给一个变量func,注意,函数体最后的花括号处必须有分号结束。
    var func = (x,y){
        return x + y;
    };
    
    print(func(10,11));    // 21
    

    注意,匿名函数与普通函数基本相同,也有参数列表,函数体,只是省去了函数名而已。

    箭头函数

    Dart中的箭头函数与JavaScript中的基本相同。当函数体中只包含一个语句时,我们就可以使用=>箭头语法进行缩写。注意,箭头函数仅仅只是一个简洁表达的语法糖。

    普通函数

    add(num x, num y){
        return x + y;
    }
    
    print(add(18,12));    // 30
    

    箭头函数

    // 与上面的普通函数完全等价
    add(num x, num y) => x + y;
    
    print(add(18,12));    // 30
    

    箭头函数省略了花括号的表达,箭头后面跟一个表达式,函数的返回值也就是这个表达式的值。另外,箭头函数也可以与匿名函数结合,形成匿名箭头函数。

    var func = (num x, num y) => x + y;
    

    运算符

    Dart语言中的运算符与Java中的绝大多数相同。

    算术运算符

    +-*/%同Java语言

    Dart中又多出了一个整除运算符~/,与普通除号的区别是将相除后的结果取整返回。

    类型判定运算符

    以下是Dart增加的类型相关的运算符。

    操作符 解释
    as 用于类型转换
    is 如果对象是指定的类型就返回 True
    is! 如果对象不是指定的类型返回 True

    obj 实现了 T 的接口时, obj is T 才是 true。类似于Java中的instanceof

    Dart中使用 as 操作符把对象转换为特定的类型,如无法转换则会抛出异常,因此在转换前最好使用is运算符进行检测。

    // 将p转换为Person类型再操作
    (p as Person).name = 'Bruce';
    

    条件表达式

    Dart中也支持三目表达式
    condition ? expr1 : expr2

    除此外,Dart还增加了非空条件判断符??
    expr1 ?? expr2
    上述运算表示,如果expr1的值不等于null,则返回其值; 否则执行表达式expr2并返回其结果。

    var str1 =  "Hello";
    var str2 =  "world";
    var result = str1 ?? str2.toUpperCase();
    

    级联运算符

    我们通常使用.操作符调用对象的方法,这在Dart中也是支持的,但是Dart另外增加了一种级联运算符..,用两个点表示。

    级联运算符可以在同一个对象上连续调用多个方法以及访问成员变量。 使用它可以避免创建临时变量, 写出更流畅的代码。

    假如类Person有三个方法,setNamesetAgesave,则可如下调用

    new Person()..setName("Bob")..setAge(20)..save();
    

    使用级联运算符调用方法,无需该方法返回对象本身即可连续的流式的调用该对象的其他方法。

    条件成员访问符

    在Java中很容易碰到恼人的空指针错误,因此在方法调用前需要进行对象的非空判断,这样的判断语句使代码变得冗长,可读性差,不整洁。Dart中则发明了一个新的运算符用于处理此类情况。

    条件成员访问符?.,它和.类似,但是运算符左边的对象不能为null,否则返回null,若对象不为null,则返回对象本身。

    // list1默认值为null
    List list1;
    print(list1?.length);  // null
    
    List list2 = [];
    print(list2?.length);  // 0
    

    分支与循环

    条件分支

    Dart中的条件分支基本与Java相同

    if条件分支

    if(i < 0){
      print('i < 0');
    }else if(i == 0){
      print('i = 0');
    } else {
      print('i > 0');
    }
    

    switch条件分支

    // 在switch的case中可以使用整数、字符串、枚举类型和编译时常量
    String command = 'OPEN';
    switch (command) {
      case 'CLOSED':
        break;
      case 'OPEN':
        break;
      default:
        print('Default');
    }
    

    循环语句

    基本循环

    Dart中的基本循环语句与Java相同

    // for循环
    for(int i = 0; i < 9; i++) {
      print(i);
    }
    
    // while循环
    while(true){
      //do something
    }
    
    // do-while循环
    do{
      //do something
    } while(true);
    

    特有循环

    var myList = ['Java','JavaScript','Dart'];
    
    // for...in...循环,类似Java中的增强for
    for (var it in myList ){
        print(it);
    }
    
    // forEach循环。其参数为一个Function对象,这里传入一个匿名函数
    myList.forEach((var it){
        print(it);
    });
    
    // 可以使用匿名箭头函数简写
    myList.forEach((it) => print(it));
    

    使用循环遍历Map

    var myMap = {
    'zhangsan':'201901',
    'lisi':'201902',
    'wangwu':'201902'
    };
    
    // forEach遍历Map
    myMap.forEach((k, v) =>  print("$k : $v"));
    
    // 根据键获取值来遍历。通过keys返回Map中所有键的集合
    for(var k in myMap.keys){
        print("$k : ${myMap[k]}");
    }
    

    下一篇 Dart语言——45分钟快速入门(下)

    关注我的公众号:编程之路从0到1

    编程之路从0到1

    展开全文
  • Dart基础教学

    2019-08-16 14:55:12
    本课程主要采取图文与代码讲解的形式,充分帮助学员理解Dart原理与加深对代码的认知力度。 在讲解代码的基础上也会稍带部分设计模式与代码编程技巧等知识,让学员在学习代码的同时更能掌握实际中的编程技巧。
  • 首页篇 上一篇博客讲解了该应用的基础结构,如底部导航栏等。基础结构篇 这篇博客将详细讲解美团首页的实现细节。首先看一下最终的效果图: 首先对首页进行拆解,将较为复杂的界面切成一个个小部件方便理解: ...

    首页篇

    Github项目地址:项目地址
    上一篇博客讲解了该应用的基础结构,如底部导航栏等。基础结构篇
    这篇博客将详细讲解美团首页的界面实现,在下一篇博客实现推荐卡片无限加载,带插入和移除动画的列表,弹出菜单等细节。

    效果图:

    首先对首页进行拆解,将较为复杂的界面切成一个个小部件方便理解:
    1. AppBar
    2. 三行由图片和标题组成的按纽栏
    3. 定时滚动的轮播图
    4. 推荐卡片

    AppBar

      ///主界面AppBar
      AppBar _buildHomeAppBar() {  //构建一个美团首页AppBar
        return AppBar(
          automaticallyImplyLeading: false,		//不自动显示一个返回按钮
          elevation: 0.0,		//关闭阴影高度
          backgroundColor: Colors.white,		//背景颜色设为白色
          flexibleSpace: SafeArea(
            适配刘海,自动避开刘海,IOS底部导航的非显示区域
            child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 8.0),
                  child: ClipOval(		//以圆形截取子控件
                    child: Image.asset("images/protrait.png",
                        width: 35.0, height: 35.0),
                  ),
                ),
                Container(
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: <Widget>[
                      Row(
                        mainAxisAlignment: MainAxisAlignment.center,
                        mainAxisSize: MainAxisSize.min,
                        children: <Widget>[
                          Text(
                            "三河",
                            style: TextStyle(color: Colors.black, fontSize: 15.0),
                          ),
                          Icon(
                            Icons.keyboard_arrow_down,
                            size: 15.0,
                          ),
                        ],
                      ),
                      Text(
                        "晴 20°",
                        style: TextStyle(fontSize: 10.0),
                      )
                    ],
                  ),
                  padding: const EdgeInsets.all(8.0),
                ),
                Expanded(		//占满剩余控件
                  child: GestureDetector(
                    onTap: () {		//以IOS风格动画导航到搜索界面
                      Navigator.of(context).push(CupertinoPageRoute(
                        builder: (context) => SearchPage()
                      ));
                    },
                    child: Container(
                      height: 45.0,
                      child: Card(
                        elevation: 0.0,
                        shape: RoundedRectangleBorder(	//设置形状为弧度10的圆角矩形
                            borderRadius: BorderRadius.all(Radius.circular(10.0))),
                        color: Colors.grey[200],
                        child: Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: <Widget>[
                            Icon(
                              Icons.search,
                              color: Colors.black87,
                              size: 20.0,
                            ),
                            Text(
                              "自助烤肉",
                              style: TextStyle(fontSize: 15.0, color: Colors.black87),
                            ),
                          ],
                        ),
                      ),
                    ),
                  ),
                ),
                IconButton(
                  iconSize: 30,
                  splashColor: Colors.transparent,	//水波纹特效颜色为透明
                  highlightColor: Colors.transparent,
                  padding: EdgeInsets.zero,		//设置各方向外边距为0
                  icon: Icon(
                    Icons.add,
                    color: Colors.black,
                  ),
                  onPressed: () {
                    Navigator.of(context)
                        .push(CupertinoPageRoute(builder: (context) {
                      return TextPage();
                    }));
                  },
                )
              ],
            ),
          ),
        );
      }
    

    为了演示我们先将显示的文本都写死,实际开发时从服务器端获取数据后加载进去即可。
    先看看AppBar的构造函数

    AppBar({
        Key key,		//同于在一个容器里出现多个同类对象时区分彼此的标记,大部分时候用不上
        this.leading,		//最左侧区域,通常放置返回按钮
        this.automaticallyImplyLeading = true,		//通过该属性控制是否自动添加返回按钮
        this.title,		//标题,安卓平台显示在左侧,IOS平台显示在中间
        this.actions,		//最右侧区域,通常用于放置菜单按钮等
        this.flexibleSpace,		//可伸缩的空闲区域
        this.bottom,		//底部区域,通常用于放置顶部导航栏
        this.elevation,		//阴影高度
        this.shape,		//形状
        this.backgroundColor,		//背景色
        this.brightness,
        this.iconTheme,		//按钮主题
        this.actionsIconTheme,
        this.textTheme,
        this.primary = true,
        this.centerTitle,		//是否将标题显示在中间
        this.titleSpacing = NavigationToolbar.kMiddleSpacing,
        this.toolbarOpacity = 1.0,
        this.bottomOpacity = 1.0,
      })
    

    在这里我们直接将一个Row控件放置在flexibleSpace区域,实现更为灵活的布局。Row控件的作用是将children属性里的多个控件按水平排列,通过mainAxisAlignmentcrossAxisAlignment 属性控制子控件在主轴和横轴方向上的对齐方式。与其相似的是Column控件(将子控件按垂直方向排列)。Row控件的主轴对应的是水平方向,横轴是垂直方向,Column控件与其相反。而将Row控件放置在flexibleSpace区域的原因是当leading, title, actions 这三个属性的任何一个不为空时,另外两个属性即使赋空值也会占用一定的空间。接下来我们逐个实现Row中的子控件。

    圆形头像框

    Padding(
      padding: const EdgeInsets.symmetric(horizontal: 8.0),
      child: ClipOval(
        child: Image.asset("images/protrait.png",
            width: 35.0, height: 35.0),
        ),
    ),
    

    Padding控件指定子控件在上下左右方向上的外边距,padding属性接收一个EdgeInsets对象。该对象有三种模式(这里将命名构造函数理解为构造该对象的一种模式),all, symmetric, only 。all模式接收一个double类型的参数,表示四个方向上的外边距都为这个值,symmetric模式控制水平方向和垂直方向,only指定单个方向。如

    EdgeInsets.only(bottom: 12, top: 10, left: 3)
    

    ClipOval控件使子控件显示在一个圆心区域,Image控件用于显示图片。有四种模式,assets用于从本地资源加载图片,network用于从网络加载图片,memory用于从内存加载图片,file用于从文件路径加载图片。从assets加载图片需要先在pubspec.yaml文件中声明依赖。

      assets:
        - images/test.png		//加载本地目录的images文件夹下的test.png
        - images/protrait.png
        - images/title/		//加载title文件夹下的所有资源(不包括其子文件夹)
    

    地点和天气标题

    Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            Text(
              "三河",
              style: TextStyle(color: Colors.black, fontSize: 15.0),
            ),
        	Icon(
          	  Icons.keyboard_arrow_down,
          	  size: 15.0,
        	),
      	  ],
    	),
        Text(
          "晴 20°",
          style: TextStyle(fontSize: 10.0),
        )
      ],
    ),
    

    这个标题由一个Column组成,第一个子控件是一个水平排列的文字和图标,第二个子控件是一个文字。Text控件的style属性接收一个TextStyle对象用于设置文字大小,颜色,加粗等。Icons是Material包里的一个图标工具类,提供了许多 Material Design 图标。

    搜索框

    Expanded(
      child: GestureDetector(
        onTap: () {
          Navigator.of(context).push(CupertinoPageRoute(
            builder: (context) => SearchPage()
          ));
        },
        child: Container(
          height: 45.0,
          child: Card(
            elevation: 0.0,
            shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.all(Radius.circular(10.0))),
            color: Colors.grey[200],
            child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Icon(
                  Icons.search,
                  color: Colors.black87,
                  size: 20.0,
                ),
                Text(
                  "自助烤肉",
                  style: TextStyle(fontSize: 15.0, color: Colors.black87),
                ),
              ],
            ),
          ),
        ),
      ),
    ),
    

    由于这个搜索框只是作为一个按钮来弹出搜索界面,所以只需绘制出一个搜索框的样式出来即可。通过Expaned控件可以使子控件填满父容器的剩余空间。GestureDetector可以捕获多种手势事件,这里我们只需要点击事件。用Container控件限制高度,Card控件绘制圆角边框及背景色,用Row控件在Card内部显示一个搜索图标和一个文字控件。

    在Flutter中,页面跳转通过 Navigator.of(context).push() 方法实现,该方法接收一个抽象类Route的对象。Route类的实现类主要有 MaterialPageRouteCupertinoPageRoute 。MaterialPageRoute在安卓平台的跳转动画为从下方进入,在IOS平台的跳转动画为从左侧进入。CupertinoPageRoute的跳转动画都为从左侧进入。

    加号按钮

    IconButton(
      iconSize: 30,
      splashColor: Colors.transparent,
      highlightColor: Colors.transparent,
      padding: EdgeInsets.zero,
      icon: Icon(
        Icons.add,
        color: Colors.black,
      ),
      onPressed: () {
        Navigator.of(context)
            .push(CupertinoPageRoute(builder: (context) {
          return TextPage();
        }));
      },
    )
    

    Flutter中可以通过GestureDetector使子控件可以响应多种手势,也有大量现成的Button类,常用的有 FlatButton,IconButton, RaisedButton等Material包下的Button,Cupertino包下的CupertinoButton。Material包中提供了许多符合谷歌 Material Design 的控件,而Cupertino包提供了许多IOS风格的控件,如之前用到的CupertinoTabBar等。Material包下的Button大多都提供了点击时的水波纹特效,splashColor属性便是控制水波纹特效颜色的,highlightColor属性控制被点击时按钮的颜色。
    至此美团首页的AppBar就搞定喽,关于弹出菜单,选择地点界面,搜索界面在后面的文章中解析。

    由图片和文字组成的按纽栏

    可以看到在首页界面中有三排由图片和文字组成的按钮栏,考虑到重用的问题我们先新建一个MyImageButton类继承自StatelessWidget。

    class MyImageButton extends StatelessWidget {
    
      MyImageButton({@required this.image, @required this.title, this.width, this.tip});
    
      final Widget image;
      final String title;
      final double width;
      final String tip;
    
      @override
      Widget build(BuildContext context) {
        return Container(
          width: width,
          child: Stack(
            children: <Widget>[
              Center(
                child: Column(
                  children: <Widget>[
                    SizedBox(height: 12,),
                    image,
                    SizedBox(
                      height: 5.0,
                    ),
                    Text(
                      title,
                      style: TextStyle(fontSize: 12.0),
                    )
                  ],
                ),
              ),
              Align(
                alignment: Alignment.topRight,
                child: tip != null ? MyTag(tag: tip, isEmphasize: true, radius: 15.0,) : null,
              ),
            ],
          ),
        );
      }
    }
    

    当控件在其生命周期中无需改变显示内容或无需在销毁时释放资源就选择继承StatelessWidget
    在Flutter中推荐在构造函数的参数列表中使用大括号包裹参数,使其成为可选参数,在必须的参数前面用@required标记。同时Flutter也支持类似于Java的构造函数形式。

    MyImageButton({@required this.image, @required this.title, this.width, this.tip});
    MyImageButton(this.image, this.title, this.width, this.tip);
    MyImageButton(this.image, this.title, {this.width, this.tip});
    MyImageButton(Widget image, String title, doublewidth, String tip){
      this.image = image;
      ...
    }
    

    StatelessWidget要求其属性全都为 final ,该类只有一个 build 方法需要覆盖,在 build 方法中返回一个Widget作为该类实例化时显示的内容。StatefulWidget的build方法会在其生命周期中多次被调用,而StatelessWidget的build方法只会在初次插入到Widget树时,父控件发生变化时,当InheritedWidget所依赖的数据发生变化时这三种情况下调用。InheritedWidget用于实现底层Widget访问高层Widget中的数据,通常用在主题类及状态管理框架中。

    MyImageButton所用到的大部分控件前面都已讲解过了,这里就不再赘述了。Stack控件也是Flutter里为数不多的具有多个子控件的控件(前面提到过的RowColumn,以及常用的ListView等)。Stack控件的效果是使子控件层叠排列,children属性中的Widget列表中越靠前的显示在越底层,通常配合Align控件使用。Align控件用于控制子控件在父容器中的对齐方式。SizedBox用于限定子控件的大小,也可以用于占据一片空白区域(因为其child属性是可选的)。

    使用Column控件将构造函数接收到的image和tile显示成一列,并且使用SizedBox在顶部和中间留白。外层嵌套的Stack控件是用于实现图片右上角的红色标签效果

    class MyTag extends StatelessWidget {
      MyTag({@required this.tag, this.isEmphasize = false, this.radius = 3.0});
    
      final String tag;
      final bool isEmphasize;
      final double radius;
    
      @override
      Widget build(BuildContext context) {
        return Container(
          decoration: BoxDecoration(
            border: Border.all(
                color: isEmphasize ? Colors.red : Colors.black, width: 0.5),
            color: isEmphasize ? Colors.red : Colors.white,
            borderRadius: BorderRadius.circular(radius),
          ),
          child: Padding(
            padding: const EdgeInsets.only(left: 3.0, right: 3.0, bottom: 1.0),
            child: Text(
              tag,
              style: TextStyle(
                  fontSize: 10.0, color: isEmphasize ? Colors.white : Colors.black),
            ),
          ),
        );
      }
    }
    

    这个标签控件用于实现标题栏右上角的红色标签与推荐卡片中的白色标签。Container除了之前介绍的控制高度,宽度,背景色,内外边距等作用外还有一个特别常用的属性便是decoration,该属性接受一个BoxDecoration对象,通过该对象可以控制边框和形状等属性。由于Container中的color属性是通过BoxDecoration实现的,所以当decoration的值不为空时背景色只能通过BoxDecoration中的color属性控制。

    通过border属性控制颜色和边框宽度,borderRadius属性控制圆角的弧度值便可绘制出圆角边框。

    最后将MyImageButton控件使用Row控件包裹起来便可实现标题栏。

    定时滚动的轮播图

    import 'dart:async';
    import 'package:flutter/material.dart';
    
    class SlidesShowWidget extends StatefulWidget {
    
      SlidesShowWidget({this.height = 100});
    
      final double height;
    
      @override
      _SlidesShowWidgetState createState() => _SlidesShowWidgetState();
    }
    
    class _SlidesShowWidgetState extends State<SlidesShowWidget>
        with SingleTickerProviderStateMixin {
      PageController _pageController = PageController();
      TabController _tabController;
      Timer _timer;
      int _index = 0;
    
      @override
      void initState() {
        _timer = Timer.periodic(Duration(seconds: 2), _handleTimeout);
        super.initState();
        _tabController = TabController(length: 3, vsync: this);
      }
    
      @override
      void dispose() {
        _tabController?.dispose();
        _pageController?.dispose();
        _timer?.cancel();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
    
        Widget _buildImage(String imageUrl) {
          return Card(
            color: Colors.transparent,
            elevation: 0.0,
            child: ClipRRect(
              borderRadius: BorderRadius.circular(15.0),
              child: Image.network(
                imageUrl,
                fit: BoxFit.fitWidth,
              ),
            ),
          );
        }
    
        return Container(
          height: widget.height,
          child: Stack(
            children: <Widget>[
              PageView(
                onPageChanged: _handlePageChanged,
                controller: _pageController,
                children: <Widget>[
                  _buildImage("http://5b0988e595225.cdn.sohucs.com/images/20171105/2e36a4b9c5764a5cb1b6a7ee84f85146.jpeg"),
                  _buildImage("https://b-ssl.duitang.com/uploads/item/201602/17/20160217155320_FUCuw.thumb.700_0.jpeg"),
                  _buildImage("http://img3.duitang.com/uploads/item/201505/27/20150527174204_aThSR.jpeg"),
                  _buildImage("http://5b0988e595225.cdn.sohucs.com/images/20171105/2e36a4b9c5764a5cb1b6a7ee84f85146.jpeg"),
                  _buildImage("https://b-ssl.duitang.com/uploads/item/201602/17/20160217155320_FUCuw.thumb.700_0.jpeg"),
                ],
              ),
              Align(
                alignment: Alignment.bottomCenter,
                child: Padding(
                  padding: const EdgeInsets.only(bottom: 10.0),
                  child: Opacity(
                    opacity: 0.5,
                    child: TabPageSelector(
                      indicatorSize: 10.0,
                      color: Colors.white,
                      selectedColor: Colors.blue,
                      controller: _tabController,
                    ),
                  ),
                ),
              )
            ],
          ),
        );
      }
    
      void _handleTimeout(Timer timer) {
        _index++;
        _pageController.animateToPage(_index % 3,
            duration: Duration(microseconds: 16), curve: Curves.fastOutSlowIn);
        _tabController.animateTo(_index % 3);
      }
    
      void _handlePageChanged(int value) {
        _index = value;
        if (value == 0) {
          _tabController.animateTo(_tabController.length - 1);
          _pageController.jumpToPage(5 - 2);
        } else if (value == 5 - 1) {
          _tabController.animateTo(0);
          _pageController.jumpToPage(1);
        } else {
          _tabController.animateTo(value - 1);
        }
      }
    }
    

    先简单介绍一下StatefulWidget,通常我们会覆盖的方法只有 intiStatedisposebuild 三个方法。initState方法在控件首次插入到控件树时调用,可以在里面初始化一些数据,dispose方法在控件被销毁时调用,通常在该方法内部释放资源。build方法在初次插入控件树时,setState方法调用时被调用(还有四种情况在此不在赘述,StatefulWidget控件的完整生命周期请参考官方文档)。大部分的控件此前都已经介绍过了,这里只简单介绍一下几个关键点。

    1. 将与界面相关联的数据存放在State类的属性中,当需要改变界面时调用setState方法,在setState方法内部改变对应属性的值,build方法会自动被调用,此时显示的界面也就随之改变了。

    2. ClipRRect控件用于使子控件呈现为圆角,Opacity控件用于调整子控件透明度。

    3. _tabController?.dispose(); 的意思是在_tabController对象不为空时调用该对象的dispose()方法,通常用在网络请求等异步操作时确保不会触发空对象异常。

    4. PageView控件内置了水平或垂直滚动操作,具体参考https://api.flutter.dev/flutter/widgets/PageView-class.html

    5. PageController用来控制与其绑定的PageView当前显示的Page,TabController用来控制与其绑定的TabPageSelector当前高亮的指示器。

    6. dart:async包里面存放着与异步相关的类,其中的Timer类可以帮助我们完成定时滚动。_timer = Timer.periodic(Duration(seconds: 2), _handleTimeout); 意思是每两秒中调用一次_handleTimeout函数。

    7. 通过在滚动列表的最前面添加一个与滚动列表最后一个控件相同的控件,在滚动列表的最后面添加一个与滚动列表第一个相同的控件实现无限滚动的列表。如 [蓝,红, 绿,蓝,红],当滚动到最后一个红时跳转到第一个红,当滚动到第一个蓝时跳转到第二个蓝处。

        void _handlePageChanged(int value) {
          _index = value;
          if (value == 0) {
            _tabController.animateTo(_tabController.length - 1);
            _pageController.jumpToPage(5 - 2);
          } else if (value == 5 - 1) {
            _tabController.animateTo(0);
            _pageController.jumpToPage(1);
          } else {
            _tabController.animateTo(value - 1);
          }
        } 
      
    8. 若自带的TabController不符合界面设计,也可以用几个Container绘制特定的形状颜色,通过PageController获取当前的显示的Page的索引改变对应Container的形状颜色即可。

    推荐卡片

    class ScenicCard extends StatelessWidget {
      ScenicCard(
          {@required this.price,
          @required this.title,
          @required this.imageUrls,
          @required this.score,
          @required this.address,
          this.onPress,
          this.tags = const <Widget>[]})
          : assert(imageUrls.length == 3);
    
      final Widget price;
      final List<Widget> tags;
      final String title;
      final List<String> imageUrls;
      final String score;
      final String address;
      final VoidCallback onPress;
    
      @override
      Widget build(BuildContext context) {
        final imageWidth = (MediaQuery.of(context).size.width - 60.0) / 3.0;
        final imageHeight = imageWidth - 20.0;
        final tagList = <Widget>[
          price,
        ];
    
        if (tags.length > 0) {
          tags.forEach((tag) {
            tagList.add(SizedBox(
              width: 5.0,
            ));
            tagList.add(tag);
          });
        }
    
        return Card(
          shape: const RoundedRectangleBorder(
            borderRadius: BorderRadius.all(Radius.circular(15.0)),
          ),
          elevation: 0.0,
          margin: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 5.0),
          color: Colors.white,
          child: Padding(
            padding: const EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: <Widget>[
                    //粗体标题
                    Text(
                      title,
                      style: CardTitleTextStyle,
                    ),
                    //卡片删除图标
                    Container(
                      height: 20,
                      width: 20,
                      child: IconButton(
                        padding: EdgeInsets.zero,
                        icon: Icon(
                          Icons.highlight_off,
                          size: 20.0,
                        ),
                        onPressed: onPress,
                      ),
                    ),
                  ],
                ),
                SizedBox(
                  height: 5,
                ),
                Row(
                  children: <Widget>[
                    Text(
                      score,
                      style: GradeTextStyle,
                    ),
                    Text(
                      address,
                      style: BehindGradeTextStyle,
                    )
                  ],
                ),
                SizedBox(
                  height: 7.0,
                ),
                Row(
                  children: tagList,
                ),
                SizedBox(
                  height: 7.0,
                ),
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: <Widget>[
                    _buildImage(imageWidth, imageHeight, imageUrls[0]),
                    _buildImage(imageWidth, imageHeight, imageUrls[1]),
                    _buildImage(imageWidth, imageHeight, imageUrls[2]),
                  ],
                ),
                SizedBox(
                  height: 15,
                )
              ],
            ),
          ),
        );
      }
    }
    

    推荐卡片的实现与前面提到的控件大同小异,在Card控件内放入一个Column控件,竖直排列四个水平行。第一行显示标题和关闭图片,主轴对齐方式为 MainAxisAlignment.spaceBetween (在控件中间均匀插入空白)。第二行显示评分与地区,第三行显示价格与标签,第四行显示三张图片。这里是以景区卡片举例,美食卡片与其差别很小,不再赘述。

    首页完整的源代码

    import 'package:flutter/material.dart';
    import 'package:flutter/cupertino.dart';
    import 'package:flutter_meituan/src/Route/searchPage.dart';
    import 'package:flutter_meituan/src/Route/testPage.dart';
    import 'package:flutter_meituan/src/Style/myTheme.dart';
    import 'package:flutter_meituan/src/Widget/commonWidget.dart';
    import 'package:flutter_meituan/src/Widget/slidesShow.dart';
    
    class HomePage extends StatefulWidget {
      @override
      _HomePageState createState() => _HomePageState();
    }
    
    class _HomePageState extends State<HomePage> {
      ///主界面AppBar
      AppBar _buildHomeAppBar() {
        return AppBar(
          automaticallyImplyLeading: false,
          elevation: 0.0,
          backgroundColor: Colors.white,
          flexibleSpace: SafeArea(
            //适配刘海
            child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 8.0),
                  child: ClipOval(
                    child: Image.asset("images/protrait.png",
                        width: 35.0, height: 35.0),
                  ),
                ),
                Container(
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: <Widget>[
                      Row(
                        mainAxisAlignment: MainAxisAlignment.center,
                        mainAxisSize: MainAxisSize.min,
                        children: <Widget>[
                          Text(
                            "三河",
                            style: TextStyle(color: Colors.black, fontSize: 15.0),
                          ),
                          Icon(
                            Icons.keyboard_arrow_down,
                            size: 15.0,
                          ),
                        ],
                      ),
                      Text(
                        "晴 20°",
                        style: TextStyle(fontSize: 10.0),
                      )
                    ],
                  ),
                  padding: const EdgeInsets.all(8.0),
                ),
                Expanded(
                  child: GestureDetector(
                    onTap: () {
                      Navigator.of(context).push(
                          CupertinoPageRoute(builder: (context) => SearchPage()));
                    },
                    child: Container(
                      height: 45.0,
                      child: Card(
                        elevation: 0.0,
                        shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.all(Radius.circular(10.0))),
                        color: Colors.grey[200],
                        child: Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: <Widget>[
                            Icon(
                              Icons.search,
                              color: Colors.black87,
                              size: 20.0,
                            ),
                            Text(
                              "自助烤肉",
                              style:
                                  TextStyle(fontSize: 15.0, color: Colors.black87),
                            ),
                          ],
                        ),
                      ),
                    ),
                  ),
                ),
                IconButton(
                  iconSize: 30,
                  splashColor: Colors.transparent,
                  highlightColor: Colors.transparent,
                  padding: EdgeInsets.zero,
                  icon: Icon(
                    Icons.add,
                    color: Colors.black,
                  ),
                  onPressed: () {
                    Navigator.of(context)
                        .push(CupertinoPageRoute(builder: (context) {
                      return TextPage();
                    }));
                  },
                ),
              ],
            ),
          ),
        );
      }
    
      Widget _buildMyButton(String title) {
        
        return GestureDetector(
          onTap: () => Navigator.of(context).pop(),
              child: Container(
            decoration: BoxDecoration(
              border: Border.all(color: Colors.black, width: 0.5),
              color: Colors.white,
              borderRadius: BorderRadius.circular(5),
            ),
            child: Padding(
              padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10),
              child: Center(
                child: Text(
                  title,
                  style: TextStyle(fontSize: 12.0, color: Colors.black),
                ),
              ),
            ),
          ),
        );
      }
    
      void _showDeleteDialog() {
        var dialog = SimpleDialog(
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)),
          titlePadding: EdgeInsets.only(top: 20),
          title: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text(
                "选择具体理由,会减少相关推荐呦",
                style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
              ),
              SizedBox(
                height: 20,
              ),
              Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  _buildMyButton("去过了"),
                  SizedBox(
                    width: 10,
                  ),
                  _buildMyButton("不感兴趣"),
                  SizedBox(
                    width: 10,
                  ),
                  _buildMyButton("价格不合适"),
                ],
              ),
              SizedBox(
                height: 15,
              ),
              Container(
                decoration: BoxDecoration(
                    color: CupertinoColors.lightBackgroundGray,
                    borderRadius: BorderRadius.only(
                        bottomLeft: Radius.circular(15),
                        bottomRight: Radius.circular(15))),
                child: Center(
                  child: FlatButton(
                    child: Text(
                      "不感兴趣",
                      style: TextStyle(fontSize: 12, color: Colors.teal),
                    ),
                    onPressed: () => Navigator.of(context).pop(),
                  ),
                ),
              )
            ],
          ),
        );
    
        showDialog(
          context: context,
          builder: (context) => dialog,
        );
      }
    
      @override
      Widget build(BuildContext context) {
        final screenWidth = MediaQuery.of(context).size.width;
    
        const title1 = <String>[
          "美食",
          "电影/演出",
          "酒店住宿",
          "休闲娱乐",
          "外卖",
        ];
        const url1 = <String>[
          "images/title/18.png",
          "images/title/17.png",
          "images/title/16.png",
          "images/title/19.png",
          "images/title/20.png",
        ];
        const title2 = <String>[
          "亲子",
          "健身/游泳",
          "周边游/旅游",
          "丽人/美发",
          "超市/生鲜",
        ];
        const url2 = <String>[
          "images/title/6.png",
          "images/title/7.png",
          "images/title/8.png",
          "images/title/9.png",
          "images/title/10.png",
        ];
        const title3 = <String>[
          "医疗/牙科",
          "生活服务",
          "景点/门票",
          "签到领现金",
          "更多",
        ];
        const url3 = <String>[
          "images/title/11.png",
          "images/title/12.png",
          "images/title/13.png",
          "images/title/14.png",
          "images/title/15.png",
        ];
    
        List<Widget> _buildTitle(
            List<String> strs, List<String> urls, double width) {
          List<Widget> titleList = <Widget>[];
          for (int i = 0; i < strs.length; i++) {
            titleList.add(MyImageButton(
                image: Image.asset(
                  urls[i],
                  width: width,
                  height: width,
                ),
                title: strs[i],
                width: (screenWidth - 30) / 5.0));
          }
          return titleList;
        }
    
        List<Widget> _buildBody() {
          return <Widget>[
            //第一行标题栏
            Container(
              padding: const EdgeInsets.only(
                  left: 15.0, right: 15.0, bottom: 5.0, top: 10.0),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: <Widget>[
                  MyImageButton(
                      image: Image.asset(
                        url1[0],
                        width: screenWidth / 7,
                        height: screenWidth / 7,
                      ),
                      title: title1[0],
                      width: (screenWidth - 30) / 5.0),
                  MyImageButton(
                      image: Image.asset(
                        url1[1],
                        width: screenWidth / 7,
                        height: screenWidth / 7,
                      ),
                      title: title1[1],
                      width: (screenWidth - 30) / 5.0),
                  MyImageButton(
                    image: Image.asset(
                      url1[2],
                      width: screenWidth / 7,
                      height: screenWidth / 7,
                    ),
                    title: title1[2],
                    width: (screenWidth - 30) / 5.0,
                    tip: "嗨抢",
                  ),
                  MyImageButton(
                      image: Image.asset(
                        url1[3],
                        width: screenWidth / 7,
                        height: screenWidth / 7,
                      ),
                      title: title1[3],
                      tip: "网咖",
                      width: (screenWidth - 30) / 5.0),
                  MyImageButton(
                      image: Image.asset(
                        url1[4],
                        width: screenWidth / 7,
                        height: screenWidth / 7,
                      ),
                      title: title1[4],
                      width: (screenWidth - 30) / 5.0),
                ],
              ),
            ),
            SizedBox(
              height: 20.0,
            ),
            //第二行标题栏
            Container(
              padding: const EdgeInsets.symmetric(horizontal: 10.0),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: _buildTitle(title2, url2, screenWidth / 14.0),
              ),
            ),
            SizedBox(
              height: 10.0,
            ),
            //第三行标题栏
            Container(
              padding: const EdgeInsets.symmetric(horizontal: 10.0),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: _buildTitle(title3, url3, screenWidth / 14.0),
              ),
            ),
            Container(
                padding: const EdgeInsets.only(
                    left: 10.0, right: 10.0, top: 30.0, bottom: 0.0),
                child: SlidesShowWidget(
                  height: 80,
                )),
            ScenicCard(
              onPress: _showDeleteDialog,
              price: PriceText("5"),
              score: "4.8分",
              address: " | 东城区",
              title: "故宫博物院(故宫) (5A)",
              tags: <Widget>[
                MyTag(tag: "网红地打卡"),
                MyTag(tag: "帝王宫殿"),
                MyTag(tag: "5A景点"),
              ],
              imageUrls: <String>[
                "http://p0.meituan.net/travel/83544ca4b38bbe0f7644982c3528defd117921.jpg@660w_500h_1e_1c",
                "http://p1.meituan.net/poi/e732ed2314a1a2619e6c3254fd2f1fd0112611.jpg",
                "http://p0.meituan.net/poi/e7d94c4d609e5dd4d71bcea6a5eb0c5e220371.jpg"
              ],
            ),
            BigPictureCateCard(
              onPress: _showDeleteDialog,
              title: "老北京涮肉 4 人餐",
              content: "套餐包括:羔羊肉,肥牛,香辣锅,鱼丸,炸灌肠,...",
              address: "南锣鼓巷",
              price: RichText(
                text: TextSpan(children: <TextSpan>[
                  TextSpan(
                      text: "¥",
                      style: TextStyle(fontSize: 10.0, color: Colors.red)),
                  TextSpan(
                      text: "139",
                      style: TextStyle(
                          fontSize: 15.0,
                          color: Colors.red,
                          fontWeight: FontWeight.bold)),
                  TextSpan(
                      text: "¥190",
                      style: TextStyle(
                          decoration: TextDecoration.lineThrough,
                          color: Colors.black,
                          fontSize: 10.0))
                ]),
              ),
              tags: <Widget>[
                MyTag(
                  tag: "5.7折",
                  isEmphasize: true,
                ),
                MyTag(tag: "销量火爆")
              ],
              imageUrls: <String>[
                "http://p1.meituan.net/deal/87d9fbf3dba19daf2becbca8c8daee74145248.jpg@428w_320h_1e_1c",
                "http://p0.meituan.net/deal/2d65c591c7b02f9ca9bc61f667262319220693.jpg@428w_320h_1e_1c",
                "http://p1.meituan.net/deal/4aea58490b74263d7170177fe3ab9f4c26990.jpg@428w_320h_1e_1c"
              ],
            ),
            ScenicCard(
              onPress: _showDeleteDialog,
              price: Text(
                "免费",
                style: TextStyle(
                    color: Colors.red, fontSize: 10.0, fontWeight: FontWeight.bold),
              ),
              score: "4.6分",
              address: " | 后海/什刹海",
              title: "后海",
              tags: <Widget>[MyTag(tag: "城市地标"), MyTag(tag: "陪爸妈")],
              imageUrls: <String>[
                "https://p1.meituan.net/hotel/828cc5794f92e40c5de5182cb1b30993316981.jpg@220w_125h_1e_1c",
                "http://p1.meituan.net/hoteltdc/998c2b9face5e48942e10b90bf42803a154752.jpg",
                "http://p0.meituan.net/hotel/aaa8a7aed2ce2fe43aea50d6616293b2119956.jpg"
              ],
            ),
          ];
        }
    
        return Scaffold(
          appBar: _buildHomeAppBar(),
          body: Container(
            decoration: GradientDecoration,
            child: ListView(
              children: _buildBody(),
            ),
          ),
        );
      }
    }
    
    

    ListView控件使控件列表中的控件水平或垂直显示,并且支持滚动。如果需要显示滚动轴,在外层嵌套一个Scrollbar即可。ListView作为Flutter最常用的滚动块推荐前往官方文档细致的学习一下:ListView

    下一篇文章将完善首页各个按钮的点击事件及滑动到底部时加载新数据等内容。

    展开全文
  • Dart入门

    2018-10-22 21:38:15
    剔除繁杂的理论,注重实践,讲解Dart的基本使用
  • dart语言程序设计

    2020-07-25 23:33:09
    这是一本讲述Dart语言程序设计的英文书,Dart语言将是javascript 络结语言。速度快效率高。
  • Dart语法

    千次阅读 2019-02-21 14:06:23
    变量 基本类型 bool done = true; int num = 2; double x = 3.14; final bool visible = false; final int amount = 100; final double y = 2.7;...const double z = 1.2...

    变量

    基本类型

    bool done = true;
    int num = 2;
    double x = 3.14;
    
    final bool visible = false;
    final int amount = 100;
    final double y = 2.7;
    
    const bool debug = true;
    const int sum = 42;
    const double z = 1.2;
    

    跟常用的其他语言不同,Dart 没有 byte、char 和 float,int、double 都是 64 位。final 跟 Java 里的 final 一样,表示一个运行时常量(在程序运行的时候赋值,赋值后值不再改变)。const 表示一个编译时常量,在程序编译的时候它的值就确定了。

    如果你觉得每次写变量类型太麻烦,你应该会喜欢 Dart 的类型推断功能:

    var done = true;
    var num = 2;
    var x = 3.14;
    
    final visible = false;
    final amount = 100;
    final y = 2.7;
    
    const debug = true;
    const sum = 42;
    const z = 1.2;
    

    Dart 里所有的东西都是对象,包括 int、函数。

    String

    var str = ' foo';
    var str2 = str.toUpperCase();
    var str3 = str.trim();
    assert(str == str2);
    assert(!identical(str, str2));
    

    Dart 里的 String 跟 Java 中的一样,是不可变对象;不同的是,检测两个 String 的内容是否一样事,我们使用 == 进行比较;如果要测试两个对象是否是同一个对象(indentity test),使用 identical 函数。

    List、Map 和 Set

    List

    // 使用构造函数创建对象
    // 跟 var list = new List<int>(); 一样
    var list = List<int>();
    list.add(1);
    list.add(2);
    
    // 通过字面量创建对象,list 的泛型参数可以从变量定义推断出来。
    // 推荐使用字面量方式创建对象
    var list2 = [1, 2];
    // 没有元素,显式指定泛型参数为 int
    var list3 = <int>[];
    list3.add(1);
    list3.add(2);
    
    var list4 = const[1, 2];
    // list4 指向的是一个常量,我们不能给它添加元素(不能修改它)
    list4.add(3);       // error
    // list4 本身不是一个常量,所以它可以指向另一个对象
    list4 = [4, 5];     // it's fine
    
    const list5 = [1, 2];
    // 相当于 const list5 = const[1, 2];
    list5.add(3);       // error
    
    // Dart 同样提供了 for-in 循环。
    // 因为语音设计时就考虑到了这个需求,in 在 Dart 里是一个关键字
    var list6 = [1, 3, 5, 7];
    for (var e in list6) {
      print(e);
    }
    

    在 Dart 2 里,创建对象时可以省略 new 关键字,也推荐省略 new。

    Set

    var set = Set<String>();
    set.add('foo');
    set.add('bar');
    assert(set.contains('foo'));
    

    我们只能通过 Set 的构造函数创建实例。

    Map

    var map = Map<String, int>();
    // 添加
    map['foo'] = 1;
    map['bar'] = 3;
    // 修改
    map['foo'] = 4;
    // 对应的 key 不存在时,返回 null
    if (map['foobar'] == null) {
      print('map does not contain foobar');
    }
    
    var map2 = const {
      'foo': 2,
      'bar': 4,
    };
    var map3 = <String, String>{};
    

    dynamic 和 Object

    前面我们说过,Dart 里所有东西都是对象。所有这些对象的父类就是 Object。

    Object o = 'string';
    o = 42;
    o.toString();   // 我们只能调用 Object 支持的方法
    
    dynamic obj = 'string';
    obj['foo'] = 4;  // 可以编译通过,但在运行时会抛出 NoSuchMethodError
    

    Object 和 dynamic 都使得我们可以接收任意类型的参数,但两者的区别非常的大。

    使用 Object 时,我们只是在说接受任意类型,我们需要的是一个 Object。类型系统会保证其类型安全。

    使用 dynamic 则是告诉编译器,我们知道自己在做什么,不用做类型检测。当我们调用一个不存在的方法时,会执行 noSuchMethod() 方法,默认情况下(在 Object 里实现)它会抛出 NoSuchMethodError。

    为了在运行时检测进行类型检测,Dart 提供了一个关键字 is:

    dynamic obj = <String, int>{};
    if (obj is Map<String, int>) {
      // 进过类型判断后,Dart 知道 obj 是一个 Map<String, int>,
      // 所以这里不用强制转换 obj 的类型,即使我们声明 obj 为 Object。
      obj['foo'] = 42;
    }
    
    // 虽然 Dart 也提供了 as 让我们进行类型的强制转换,但为了进来更安全
    // 的转换,更推荐使用 is
    var map = obj as Map<String, int>;
    

    语句

    var success = true;
    if (success) {
      print('done');
    } else {
      print('fail');
    }
    
    for (var i = 0; i < 5; ++i) {
      print(i);
    }
    
    var sum = 0;
    var j = 1;
    do {
      sum += j;
      ++j;
    } while (j < 5);
    
    while (sum-- > 0) {
      print(sum);
    }
    
    var type = 1;
    switch (type) {
      case 0:
        // ...
        break;
      case 1:
        // ..
        break;
      case 2:
        // ...
        break;
      default:
        // ...
        break;
    }
    

    常见的 if/else,do while,while 和 switch 在 Dart 里面都支持。switch 也支持 String 和 enum。

    函数

    最普通的函数看起来跟 Java 里的一样:

    int foo(int x) {
      return 0;
    }
    

    Dart 也支持可选参数:

    void main() {
      print(foo(2));
      print(foo(1, 2));
    }
    
    int foo(int x, [int y]) {
      // 是的,int 也可以是 null
      if (y != null) {
        return x + y;
      }
      return x;
    }
    
    // 结果:
    // 2
    // 3
    

    默认参数也是支持的:

    int foo(int x, [int y = 0]) {
      return x + y;
    }
    

    还能用具名参数(named parameters):

    void main() {
      print(foo(x: 1, y: 2));
      // 具名参数的顺序可以是任意的
      print(foo(y: 3, x: 4));
      // 所有的具名参数都是可选的,这个调用是合法的,但它会导致 foo() 在运行时抛异常
      print(foo());
    }
    
    int foo({int x, int y}) {
      return x + y;
    }
    

    具名参数也可以有默认参数:

    void main() {
      print(foo(x: 1, y: 2));
      print(foo());
    }
    
    int foo({int x = 0, int y = 0}) {
      return x + y;
    }
    

    如果想告诉用户某个具名参数是必须的,可以使用注解 @required:

    int foo({@required int x, @required int y}) {
      return x + y;
    }
    

    @required 是 meta 包里提供的 API,更多的信息读者可以查看 https://pub.dartlang.org/packages/meta。

    函数还可以在函数的内部定义:

    // typedef 在 Dart 里面用于定义函数类型的别名
    typedef Adder = int Function(int, int);
    
    Adder makeAdder(int extra) {
      int adder(int x, int y) {
        return x + y + extra;
      }
      return adder;
    }
    
    void main() {
      var adder = makeAdder(2);
      print(adder(1, 2));
    }
    
    // 结果:
    // 5
    

    像上面这样简单的函数,我们还可以使用 lambda:

    typedef Adder = int Function(int, int);
    
    Adder makeAdder(int extra) {
      return (int x, int y) {
        return x + y + extra;
      };
      // 如果只有一个语句,我们可以使用下面这种更为简洁的形式
      // return (int x, int y) => x + y + extra;
    }
    
    void main() {
      var adder = makeAdder(2);
      print(adder(1, 2));
    }
    

    Dart 里面不仅变量支持类型推断,lambda 的参数也支持自动推断。上面的代码还可以进一步简化为:

    typedef Adder = int Function(int, int);
    
    Adder makeAdder(int extra) {
      // 我们要返回的类型是 Adder,所以 Dart 知道 x, y 都是 int
      return (x, y) => x + y + extra;
    }
    
    void main() {
      var adder = makeAdder(2);
      print(adder(1, 2));
    }
    

    美中不足的是,Dart 不支持函数的重载。

    异常

    抛出异常:

    throw Exception('put your error message here');
    

    捕获异常:

    try {
      // ...
    // 捕获特定类型的异常
    } on FormatException catch (e) {
      // ...
    // 捕获特定类型的异常,但不需要这个对象
    } on Exception {
      // ..
    // 捕获所有异常
    } catch (e) {
      // ...
    } finally {
      // ...
    }
    

    跟 Java 不同的是,Dart 可以抛出任意类型的对象:

    throw 42;
    

    定义一个类:

    class Point2D {
      static const someConst = 2;
    
      int x;
      // 成员变量也可以是 final 的
      final int y;
    
      Point2D(int x, int y) {
        this.x = x;
        this.y = y;
      }
    }
    

    由于这种初始化方式很常见,Dart 提供了更简洁的方式:

    class point2d {
      int x;
      int y;
    
      point2d(this.x, this.y);
    }
    

    此外,还可以使用初始化列表(initializer list)对对象进行初始化:

    class Point2D {
      int x;
      int y;
    
      // 由于是在 initializer list 中,Dart 知道第一个 x 是 this.x,
      // 第二个 x 是构造函数的参数
      Point2D(int x, int y) : x = x, y = y {
        // ...
      }
    }
    

    initializer list 会在构造函数的函数体运行前执行。

    Dart 具有垃圾收集功能,对象的使用跟 Java 里几乎是一样的:

    main() {
      var point = Point2D(1, 2);
      point.x = 4;
      print(point);
    }
    
    class Point2D {
      int x;
      int y;
      Point2D(this.x, this.y);
    
      // 所有的类都继承自 Object,toString() 是 Object 中的方法
      @override
      String toString() {
        // 在字符串的内部可以通过 ${expression} 的方式插入值,如果
        // expression 是一个变量,可以省略花括号
        return "Point2D{x=$x, y=$y}";
      }
    }
    
    // 结果:
    // Point2D{x=4, y=2}
    

    Dart 使用 package 的概念来管理源码和可见性。它没有 public、private 之类的访问权限控制符,默认情况下,所有的符号都是公开的。如果我们不想某个变量对包的外部可见,可以使用下划线开头来给变量命名。

    class _Foo {
      // ...
    }
    
    class Bar {
      int _x;
    }
    

    下面我们使用 Dart 的访问控制,实现一个带偏移量的 Point:

    class OffsetPoint {
      int _x;
      int _y;
      int offset;
    
      OffsetPoint(int x, int y, int offset)
          : _x = x, _y = y, offset = offset {}
    
      // 定义一个 getter
      int get x => _x + offset;
      // getter 不能有参数,连括号都省掉了
      int get y {
        return _y + offset;
      }
      // 定义 setter
      void set x (int x) => _x = x;
      void set y (int y) => _y = y;
    
      @override
      String toString() {
        return "OffsetPoint{x=$x, y=$y}";
      }
    }
    
    main() {
      var point = OffsetPoint(1, 2, 10);
      // 使用 getter/setter 时,就像它是一个普通的成员变量
      print(point.x)
      print(point);
      point.x = 4;
      print(point);
    }
    
    // 结果:
    // 11
    // OffsetPoint{x=11, y=12}
    // OffsetPoint{x=14, y=12}
    

    在 Dart 里继承对象也很简单:

    class Point2D {
      int x;
      int y;
      Point2D(this.x, this.y);
    }
    
    class Point3D extends Point2D {
      int z;
      // 父类的构造函数只能在 initializer list 里调用
      Point3D(int x, int y, int z): z = z, super(x, y) {
      }
    }
    

    但是对象构造时它跟 Java、C++ 都不太一样:

    1. 先执行子类 initializer list,但只初始化自己的成员变量

    2. 初始化父类的成员变量

    3. 执行父类构造函数的函数体

    4. 执行之类构造函数的函数体

    基于这个初始化顺序,推荐是把 super() 放在 initializer list 的最后。此外,在 initializer list 里不能访问 this(也就是说,只能调用静态方法)。

    虽然 Dart 是单继承的,但它也提供了一定程度的多重继承支持:

    abstract class Bark {
      void bark() {
        print('woof');
      }
    }
    
    class Point3D extends Point2D with Bark {
      int z;
      // 父类的构造函数只能在 initializer list 里调用
      Point3D(int x, int y, int z): z = z, super(x, y) {
      }
    }
    
    // 没有其他类需要继承,所以直接 extends Bark 就可以了
    class Foo extends Bark {}
    
    void main() {
      var p = Point3D(1, 2, 3);
      p.bark();
    }
    

    Dart 把支持多重继承的类叫做 mixin。更详细的介绍,读者可以参考https://www.dartlang.org/articles/language/mixins。

    泛型

    class Pair<S, T> {
      S first;
      T second;
      Pair(this.first, this.second);
    }
    
    void main() {
      var p = Pair('hello', 2);
      print(p is Pair<String, int>);
      // is! 也是 Dart 的运算符,下面的语句跟 !(p is Pair<int, int>) 是一样的,
      // 但 is! 读起来跟像英语
      print(p is! Pair<int, int>);
      print(p is Pair);
    }
    
    // 结果:
    // true
    // true
    // true
    

    跟 Java 不同,Dart 的泛型参数类型在运行时是保留的。

    Future

    Dart 是单线程的,主线程由一个事件循环来执行(类似 Android 的主线程)。对于异步代码,我们通过 Future 来获取结果:

    import 'dart:io';
    
    void foo() {
      var file = File('path-to-your-file');
      file.exists()
          .then((exists) => print('file ${exists ? 'exists' : 'not exists'}'))
          .catchError((e) => print(e));
    }
    

    Dart 2 提供了 async 函数,用来简化这种编程范式。下面这段代码的效果跟上面是一样的:

    void foo() async {
      var file = File('path-to-your-file');
      try {
        var exists = await file.exists();
        print('file ${exists ? 'exists' : 'not exists'}');
      } catch (e) {
        print(e);
      }
    }
    

    但是要注意,上面两段代码并不是完全一样的:

    // import 语句用于导入一个包
    import 'dart:io';
    
    void main() {
      foo();
      bar();
    }
    
    void bar() {
      var file = File('path-to-your-file');
      file.exists()
          .then((exists) => print('bar: file ${exists ? 'exists' : 'not exists'}'))
          .catchError((e) => print(e));
      print('bar: after file.exists() returned');
    }
    
    void foo() async {
      var file = File('path-to-your-file');
      try {
        var exists = await file.exists();
        print('bar: file ${exists ? 'exists' : 'not exists'}');
        print('bar: after file.exists() returned');
      } catch (e) {
        print(e);
      }
    }
    
    // 一种可能的结果:
    // bar: after file.exists() returned
    // foo: file not exists
    // foo: after file.exists() returned
    // bar: file not exists
    

    这里的关键在于,bar 函数里面,file.exists() 执行完后,会马上执行下面的语句;而 foo 则会等待结果,然后才继续执行。关于 Future 的更多的细节,强烈建议读者阅读https://webdev.dartlang.org/articles/performance/event-loop。

    展开全文
  • Dart 基础教程(一)

    千次阅读 2018-12-07 19:55:45
    dart 基础笔记 dart基础 void main(){ print('li'); var a = 1;//可以多次赋予 print(a); final b = -2;//变量只能赋值一次 print(b); const c = 3;//常量也不能修改 int d = 4;//整型 print(d.isEven);...

    dart 基础笔记

    dart基础

    void main(){
      print('li');
      var a = 1;//可以多次赋予
      print(a);
      final b = -2;//变量只能赋值一次
      print(b);
      const c = 3;//常量也不能修改
    
      int d = 4;//整型
      print(d.isEven);// 是否偶数 返回true
      print(d.isOdd);// 是否奇数 返回false
      print(b.abs());//取绝对值
    
      double e = 5.6;//浮点型 ~/这个是取整 %取余数
      print(e.round());//四舍五入
      print(e.floor());//不大于的最大整数
      print(e.ceil());//不小于的最小整数
      print(e.toInt());//change to int
      print(e.toDouble());//like his name
    
      //插值 这里一个很像format 或者是 %s
      print("d + b is ${d+b}");
      print('b is $b');//如果只是传一个参数就不用花括号了
    
      //string a = 'aaa';也可以使用3引号,多行。字符串前面加r 转义。
      //常用属性 length isEmpty isNotEmpty
      String ss = 'hhh123666666999999';
      print(ss.length);
      print(ss.isEmpty);
    
      //contains()是否包含,返回布尔值 索引indexOf() 大小写toLowerCase() toUpperCase()
      //trim()截取前后空格split()分隔 substring()截取。相当与python[0:4]
      print(ss.contains('hh'));
      print(ss.substring(0,4));
    
      //list ,const 不可变list,add()增加元素,insert(插入下标,元素) remove() clear()
      // sort() indexOf()返回位置 length长度属性 sublist()截取
      // shuffle()打乱 forEach()传入一个方法
      var list1 = const [1,2,3, 'ddd'];
      print(list1.sublist(0,2));
      list1.forEach(print);//循环这个list 调用这个方法
    
      //字典,.key .value containsKey() containsValue()
      var doc = {"h1":"here", "h2":"you", "h3":"are"};
      print(doc.keys);
      print(doc.values);
      print(doc.containsKey('hi'));//true
      
    }
    

    list

    list.asMap()//转list为字典 key为0,1,2...

    //dynamic 动态类型 可以被赋予不同的值

    ++ --

    a = 1;

    print(a++)//先打印后加1

    print(++a)//先加1再打印

    ??=

    ??= 赋值,上图中 b??=10的意思是如果b有值,那么b仍然是那个它原本该有的值,如果b没有值,那么b将会被赋予=之后的值。


    条件表达式

    三目运算符

    //条件表达式
    // 三目运算符condition?expr1:expr2
    // ??运算符expr1 ?? expr2
    void main(){
      int a = 1;
      String s = a == 1 ? "aaa" : "bbb";
      print(s);//aaa //a == 1 ? 如果是true 
                     //返回expr1 反之返回 expr2
    
    
      String z;
      String b = "java";
      var c = z ?? b;
      print(c);//java 如果两个那个值中有一个没有定义的话 返回另外一个,
               // 如果都定义了的话,返回第一个。如果都没有定义的话 返回 null
    }
    

    if

    //条件表达式
    // if
    void main(){
      int a = 1;
      if(a > 0){
        print('1111');
      }else if(a == 0){
        print(-111);
      }else {
        print(000);
      }
    }
    
    

    循环

    for循环

    for

    void main() {
      var list1 = [1,2,3,4,5,6,7,8,9,10];
      for(int index = 0; index < list1.length; index ++){//初始条件 操作,index++也可以写在花括号里
        print(list1[index]);//输出1到10
      }
    }
    

    for in

    void main(){
      var list = [1,2,3];
      for (var item in list){
        if(item != 2){
          print(item);//1 3
        }
      }
    }
    
    //1 2 3 4
    

    while循环

    while

    void main() {
      int a = 0;
      while(a < 5){
        print(a++);
      }
    }
    
    //1 2 3 4
    

    do... while...

    void main(){
      var b = 1;
      do{
        print(b++);
      }while(b > 0 && b < 5);
    }
    
    //1 2 3 4
    

    break 和 continue

    break 终止循环

    void main(){
      var list = [1,2,3];
      for (var item in list){
        if(item == 3){
          break;
        }
        print(item);
      }
    }
    
    // 1 2
    

    提一下assert

    如果布尔条件为false,则使用assert语句来中断正常执行。

    void main() {
      var a = 1;
      assert(a != 3);
      print(a);//1
    }
    
    void main() {
      var a = 1;
      assert(a != 1);
      print(a);//没有执行
    }
    

    continue 跳出当前循环 继续循环

    void main(){
      var list = [1,2,3,4,5,6];
      for (var item in list){
        if(item == 2){
          continue;
        }
        print(item);
      }
    }
    
    //1 3 4 5 6 
    

    switch...case语句

    var command = 'OPEN';
    switch (command) {
      case 'CLOSED':
        executeClosed();
        break;
      case 'PENDING':
        executePending();
        break;
      case 'APPROVED':
        executeApproved();
        break;
      case 'DENIED':
        executeDenied();
        break;
      case 'OPEN':
        executeOpen();
        break;
      default://默认情况
        executeUnknown();
    }
    

    与标签调用 标签可以自定义 test

    展开全文
  • dart64位稳定版

    2020-07-21 10:01:09
    dart的Windows64位稳定版,安装时需要在线下载其他资源,可能会安装失败!!!
  • dart语法

    千次阅读 2019-06-29 19:44:34
    重温dart语法 文章目录@[toc]入门dddd 入门 1、入口方法两种定义方式 main(){ print('你好dart'); } //加void表示方法没有返回值 void main(){ print('你好dart'); } dddd ...
  • Dart2学习笔记

    万次阅读 2019-05-13 15:49:48
    基本Dart程序 先来一个基本的Dart程序: //比较简单的英语就不翻译了 // Define a function. printInteger(int aNumber) { print('The number is $aNumber.'); // Print to console. } //这里是主函数 This is ...
  • 推荐几款Dart在线编辑器

    千次阅读 2019-10-16 14:39:10
    DartPad DartPad国内特供版 try-dart
  • Dart语言于2011年10月10日由谷歌公司开发出的网络编程语言,Dart可以用作网页脚本、可以直接在Chromium浏览器中运行Dart程序,可靠的DartVm有助程序性能提升与安全。 Dart可以被转换为Java代码,也可以用来编写桌面...
  • 一丶 Dart介绍 Dart是由谷歌开发的计算机编程语言,它可以被用于web、服务器、移动应用 和物联网等领域的开发。 Dart诞生于2011年,号称要取代JavaScript。但是过去的几年中一直不温不火。直到Flutter的出现现在被...
  • Dart学习之方法函数

    万次阅读 2019-09-19 09:44:56
    上一篇我们了解了Dart的基本语法,本篇我们学习Dart的函数。 先说下我学习Dart函数的感受吧,我尝试用java语言的形式去学习Dart,但是令我意外的是,我刚迈出第一步Dart就把我踢出门外。什么意思呢?比如说,在Java...
  • Dart入门—开发环境

    万次阅读 2016-05-29 18:08:00
    在正文开始前,希望大家能看一下这段,我第一次听说Dart是在去年5月份,那段时间工作比较闲,在网上看到《Google 演示用 Dart 开发 Android 应用》,然后就开始去了解,而且认识了很多朋友,其中就有“河马”,他说...
  • Dart 调用C语言混合编程

    千次阅读 2019-05-17 21:07:29
    Dart 调用C语言 本篇博客研究Dart语言如何调用C语言代码混合编程,最后我们实现一个简单示例,在C语言中编写简单加解密函数,使用dart调用并传入字符串,返回加密结果,调用解密函数,恢复字符串内容。 环境准备 ...
  • 1、import 'dart:xxx'; 引入Dart标准库 2、import 'xxx/xxx.dart'; 引入绝对路径的Dart文件 3、import 'package:xxx/xxx.dart'; 引入Pub仓库中的第三方库 4、import 'package:项目名/xxx.dart'; 引入自定义的dart ...
  • Dart 2.1性能和可用性改进的通告

    千次阅读 2018-12-24 18:11:22
    译注:Dart2.0的文档已经翻译发布有半年之久了,2018年11月Dart2.1的stable版本也发布了。2.0版本的文档地址在https://www.kancloud.cn/@marswill 今天,我们宣布Dart 2.1的稳定发行版,这是Dart 2的升级版,它提供...
  • dart 开发】详细 dart 安装开发环境

    万次阅读 2018-09-23 08:29:01
    简介:Dart是谷歌开发的计算机编程语言,后来被Ecma (ECMA-408)认定为标准 [1] 。它被用于web、服务器、移动应用 [2] 和物联网等领域的开发。它是宽松开源许可证(修改的BSD证书)下的开源软件。详情介绍。 ======...
  • 下面开始Dart语法篇的第七篇类型系统和泛型,上一篇我们用了一篇Dart中可空和非空类型译文做了铺垫。实际上,Dart中的类型系统是不够严格,这当然和它的历史原因有关。在dart最开始诞生之初,它的定位是一门像...
1 2 3 4 5 ... 20
收藏数 26,483
精华内容 10,593
关键字:

dart