Dart语法Function函数

Dart是面向对象的语言,即使是函数也是对象,并且属于Function类型的对象

  • ps:学习Dart语法时你要记住一条,Dart里一切皆对象,包括数字和函数…….
  • 这意味着函数可以分配给变量或作为参数传递给其他函数。当然你也可以像JavaScript一样,调用一个函数
    1. void main() =>runApp(MyApp());
    2. //void main()=>{return runApp(MyApp())}

    函数体里只有一行代码,可以直接使用=>来省略{};如果不止一行,请使用大括号

StatefulWidget和StatelessWidget

  • StatefulWidget 具有可变状态的窗口部件,也就是你在使用应用的时候就可以随时变化,比如我们常见的进度条,随着进度不断变化
  • StatelessWidget 不可变状态窗口部件,也就是你在使用时不可以改变,比如固定的文字(写上后就在那里了,死也不会变了)

1. Text Widget文本组件的使用

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Text widget',
      home: Scaffold(
        appBar: AppBar(title: Text('一缕清风',textAlign: TextAlign.center,),),
        body: Center(
          child: Text(
          '一缕清风 ,非常喜欢前端,并且愿意为此奋斗一生。我希望可以出1000集免费教程。',
          textAlign: TextAlign.left,
          overflow: TextOverflow.ellipsis,
          maxLines: 1,
          style: TextStyle(
            fontSize: 25.0,
            color: Color.fromARGB(255, 255, 150, 150),
            decoration: TextDecoration.underline,
            decorationStyle: TextDecorationStyle.solid,
          ),
        )),
      ),
    );
  }
}

Screenshot_1583473382 (1).png

TextAlign属性

textAlign 属性就是文本的对齐方式

  • center: 文本以居中形式对齐
  • left: 左对齐,经常使用,让文本居左进行对齐,效果和start一样
  • right: 右对齐,使用频率也不算高
  • start: 以开始位置进行对齐,类似于左对齐
  • end: 以为本结尾处进行对齐,不常用。有点类似右对齐

TextOverflow属性

overflow 是用来设置文本溢出时

  • clip:直接切断,剩下的文字就没有了,感觉不太友好,体验性不好
  • ellipsis: 在后边显示省略号,体验性较好,这个在工作中经常使用
  • fade: 溢出的部分会进行一个渐变消失的效果,当然是上线的渐变,不是左右的哦

maxLines属性

类型:number
设置最多显示的行数,比如我们现在只显示1行,类似一个新闻列表的题目

文本换行

一些场景下直接设置 maxLines

Text(
  "广州市黄埔区开发大道将军山路段黄埔工程机械园东区六号广州市黄埔区开发大道将军山路段黄埔工程机械园东区六号广州市黄埔区开发大道将军山路段黄埔工程机械园东区六号广州市黄埔区开发大道将军山路段黄埔工程机械园东区六号广州市黄埔区开发大道将军山路段黄埔工程机械园东区六号",
  maxLines: 4,
  style: TextStyle(
    color: Color.fromRGBO(77, 99, 104, 1),
  ),
),

但是直接设置maxLines 发现有些场景会无效,这时候可以考虑使用 Flexible 或者 Expanded 组件。用方如下:
这两个组件都需要作为row或者column的子组件使用,如主轴空间不够用,则会自动扩充至次轴,实现自动换行。

  • Expanded 组件 会尽可能的充满分布在Row, Column, 或 Flex的主轴方向上;
  • Flexible 组件 也是为小部件提供空间的,但是不会要求子空间填满可用空间。
    new Row(
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      children: [
      Text(
          '地址:',
          style: TextStyle(fontSize: 18),
      ),
      Flexible(
          child: Text(
          "广州市黄埔区开发大道将军山路段黄埔工程机械园东区六号",
          style: TextStyle(fontSize: 18),
          ),
      )
      ],
    )
    

2. Container容器控件的使用

Container(容器控件)在Flutter是经常使用的控件,它就相当于我们HTML里的 <div>标签,每个页面或者说每个视图都离不开它。那这节课我们就来学习一下

其实容器的作用就是方便我们进行布局的,Flutter这点也作的很好,我们先来看容器属性中的

import 'package:flutter/material.dart';
void main () => runApp(MyApp());

//const可以省略
class MyApp extends StatelessWidget{
  @override
  Widget build(BuildContext context ){
      return MaterialApp(
        title:'Text widget',
        home:Scaffold(
          body:Center(
          child:Container(
            child:new Text('Hello 一缕清风',style: TextStyle(fontSize: 40.0),),
            alignment: Alignment.center,
            width:500.0,
            height:400.0,
            padding:const EdgeInsets.fromLTRB(10.0,30.0,0.0,0.0),
            margin: const EdgeInsets.all(10.0),
            decoration:new BoxDecoration(
              gradient:const LinearGradient(
                colors:[Colors.lightBlue,Colors.greenAccent,Colors.purple]
              ),
              border:Border.all(width:2.0,color:Colors.red)
            ),
          ),
          ),
        ),
      );
  }
}

Screenshot_1583473531.png

Alignment

这个属性针对的是Container内child的对齐方式,也就是容器子内容的对齐方式,并不是容器本身的对齐方式
这时候可以看见,我们的文本已经居中显示在手机屏幕上了。当然它的对齐方式还有如下 9 种:

  • topLeft:顶部左侧对齐
  • topCenter:顶部居中对齐
  • topRight: 顶部居左对齐
  • center:纵横双向居中对齐
  • centerLeft:纵向居中横向居左对齐
  • centerRight:纵向居中横向居右对齐
  • bottomCenter: 下部居中对齐
  • botomLeft: 下部左对齐
  • bottomRight:下部右对齐

设置宽、高和颜色属性

设置宽、高,只要在属性名称后面加入浮点型数字
颜色color对应Colors类

child:Container(
  width:500.0,
  height:400.0,
  color: Colors.lightBlue,
),

padding属性

padding的属性就是一个内边距,它和你使用的前端技术CSS里的padding表现形式一样
指的是ContainerEdgeInsets(边缘) 和 child内容的距离

EdgeInsets.all()

child:Container(
  padding:const EdgeInsets.all(10.0), 设置Container的内边距是10,左右上下全部为10
),

EdgeInsets.fromLTRB()

//EdgeInsets.fromLTRB(value1,value2,value3,value4) 
//LTRB分别代表左、上、右、下 ,设置上边距为30,左边距为10
padding:const EdgeInsets.fromLTRB(10.0,30.0,0.0,0.0),

EdgeInsets.symmetric()

padding: EdgeInsets.symmetric(vertical: 20.w),
margin: EdgeInsets.symmetric(horizontal: 20.w),

margin属性

margin是外边距,只的是container和外部元素的距离,用法和padding相似

//现在要把container的外边距设置为10个单位,代码如下
child:Container(
  child:new Text('Hello JSPang',style: TextStyle(fontSize: 40.0),),
  padding:const EdgeInsets.fromLTRB(10.0,30.0,0.0,0.0),
  margin: const EdgeInsets.all(10.0),
),

decoration属性

decoration是 container 的修饰器,主要的功能是设置背景和边框,这时候需要使用 BoxDecoration 这个对象

child:Container(
  decoration:new BoxDecoration(
    gradient:const LinearGradient(
      colors:[Colors.lightBlue,Colors.greenAccent,Colors.purple]
    )
  ),
),

⚠️注意: 设置了decoration,就不要再设置color属性了,因为这样会冲突,比如你需要给背景加入一个渐变,代码如下

设置边框可以在decoration里设置border属性,比如你现在要设置一个红色边框,宽度为2。代码如下:

child:Container(
  decoration:new BoxDecoration(
    gradient:const LinearGradient(
      colors:[Colors.lightBlue,Colors.greenAccent,Colors.purple]
    ),
    border:Border.all(width:2.0,color:Colors.red)
  ),
),

3. Image图片组件的使用

俗话说的好一图顶千言,所以图片的运用在程序制作里至关重要,加入图片的几种方式:

  • Image.asset 加载项目资源目录中的图片,用的是相对路径,加入图片后会增大打包的包体体积
  • Image.network 加载网络资源图片,意思就是你需要加入一段http://xxxx.xxx的这样的网络路径地址。
  • Image.file 加载本地图片,就是加载本地文件中的图片,这个是一个绝对路径,跟包体无关
  • Image.memory 加载Uint8List资源图片,这个我目前用的不是很多,所以没什么发言权

使用静态资源

如果想配置项目资源文件,就需要使用 pubspec.yaml 文件 文件,需要把资源文件在这里声明。

比如在项目根目录下新建了一个images文件夹,文件夹下面放了一个图片,图片的名称叫做blogtouxiang.jpg,那我们在pubspec.yaml文件里就要写如下代码进行声明。

assets:
    - images/blogtouxiang.jpg

有了声明后,我们就可以直接在项目中引用这个文件了。这里使用最简单的代码结构,只用了一张图片

import 'package:flutter/material.dart';
void main()=>runApp(MyApp());
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Image.asset('images/blogtouxiang.jpg'),
    );
  }
}

加载网络资源图片

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Text widget',
      home: Scaffold(
        body: Center(
          child: Container(
            child: new Image.network(
              'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1583483736656&di=11b4cf762d51de5edc10be4bd6565829&imgtype=0&src=http%3A%2F%2F5b0988e595225.cdn.sohucs.com%2Fimages%2F20190529%2F2eea860af1dd41b286e8dc03ed4deeea.jpeg',
              scale: 1.0,
              fit: BoxFit.cover,
            ),
            width: 300.0,
            height: 200.0,
            color: Colors.lightBlue,
          ),
        ),
      ),
    );
  }
}
//这时候就可以看到图片被加入进来了,当然我们还顺便设置了容器的宽和高

Screenshot_1583473684.png

scale属性

缩放大小,类型:float

fit属性的设置

fit属性可以控制图片的拉伸和挤压,这些都是根据图片的父级容器来的

  • BoxFit.fill: 全图显示,图片会被拉伸,并充满父容器。
  • BoxFit.contain: 全图显示,显示原比例,可能会有空隙。
  • BoxFit.cover:显示可能拉伸,可能裁切,充满(图片要充满整个容器,还不变形)。
  • BoxFit.fitWidth:宽度充满(横向充满),显示可能拉伸,可能裁切。
  • BoxFit.fitHeight :高度充满(竖向充满),显示可能拉伸,可能裁切。
  • BoxFit.scaleDown:效果和contain差不多,但是此属性不允许显示超过源图片大小,可小不可大。

图片的混合模式

图片混合模式(colorBlendMode)和color属性配合使用,能让图片改变颜色,里边的模式非常的多,产生的效果也是非常丰富的。在这里作几个简单的例子,让大家看一下效果,剩下的留给小伙伴自己探索。

child:new Image.network(
  'http://jspang.com/static/myimg/blogtouxiang.jpg',
    color: Colors.greenAccent,
    colorBlendMode: BlendMode.darken,
),
  • color:是要混合的颜色,如果你只设置color是没有意义的。
  • colorBlendMode: 是混合模式,相当于我们如何混合

repeat图片重复

  • ImageRepeat.repeat : 横向和纵向都进行重复,直到铺满整个画布
  • ImageRepeat.repeatX: 横向重复,纵向不重复
  • ImageRepeat.repeatY:纵向重复,横向不重复
    child:new Image.network(
    'http://jspang.com/static/myimg/blogtouxiang.jpg',
     repeat: ImageRepeat.repeat,
    ),
    
    Screenshot_1583473929.png

4. ListView属性的使用

纵向列表

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Text widget',
      home: Scaffold(
          appBar: AppBar(
            title: Text(
              'ListView',
              textAlign: TextAlign.right,
            ),
          ),
          body: ListView(
            children: <Widget>[
              new ListTile(
                  leading: new Icon(Icons.access_time),
                  title: new Text('access_time')),
              new ListTile(
                  leading: new Icon(Icons.account_balance),
                  title: new Text('account_balance')),
            ],
          )),
    );
  }
}

Screenshot_1583473999.png

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Text widget',
      home: Scaffold(
          appBar: AppBar(
            title: Text(
              'ListView',
              textAlign: TextAlign.right,
            ),
          ),
          body: ListView(children: <Widget>[
            new Image.network(
                'http://jspang.com/static/upload/20181111/G-wj-ZQuocWlYOHM6MT2Hbh5.jpg'),
            new Image.network(
                'http://jspang.com/static/upload/20181109/1bHNoNGpZjyriCNcvqdKo3s6.jpg'),
            new Image.network(
                'http://jspang.com/static/myimg/typescript_banner.jpg'),
            new Image.network('http://jspang.com/static/myimg/smile-vue.jpg')
          ])),
    );
  }
}

横向列表

import 'package:flutter/material.dart';
void main () => runApp(MyApp());

class MyApp extends StatelessWidget{
  @override
  Widget build(BuildContext context ){
      return MaterialApp(
        title:'Text widget',
        home:Scaffold(
          body:Center(
          child:Container(
            height:200.0,
            child:new ListView(
              scrollDirection: Axis.horizontal,
              children: <Widget>[
                new Container(
                  width:180.0,
                  color: Colors.lightBlue,
                ), new Container(
                  width:180.0,
                  color: Colors.amber,
                ), new Container(
                  width:180.0,
                  color: Colors.deepOrange,
                ),new Container(
                  width:180.0,
                  color: Colors.deepPurpleAccent,
                ),
              ],
            )
          ),
          ),
        ),
      );
  }
}

Screenshot_1583474081 (1).png

scrollDirection属性

ListView组件的scrollDirection属性只有两个值

Axis

  • Axis.horizontal:横向滚动或者叫水平方向滚动
  • Axis.vertical:(默认)纵向滚动或者叫垂直方向滚动

代码优化

import 'package:flutter/material.dart';
void main () => runApp(MyApp());

class MyApp extends StatelessWidget{
  @override
  Widget build(BuildContext context ){
      return MaterialApp(
        title:'ListView widget',
        home:Scaffold(
          body:Center(
          child:Container(
            height:200.0,
            child:MyList()
            ),
          ),
        ),
      );
  }
}


class MyList extends StatelessWidget{
  @override
  Widget build(BuildContext context){
    return ListView(
        scrollDirection: Axis.horizontal,
        children: <Widget>[
          new Container(
            width:180.0,
            color: Colors.lightBlue,
          ), new Container(
            width:180.0,
            color: Colors.amber,
          ), new Container(
            width:180.0,
            color: Colors.deepOrange,
          ),new Container(
            width:180.0,
            color: Colors.deepPurpleAccent,
          ),
        ],
    );
  }
}

5. 动态列表的使用

List类型的使用

List是Dart的集合类型之一,其实你可以把它简单理解为数组(反正我是这么认为的),其他语言也都有这个类型。它的声明有几种方式:

  • var myList = List(): 非固定长度的声明
  • var myList = List(2): 固定长度的声明
  • var myList= List(): 固定类型的声明方式
  • var myList = [1,2,3]: 对List直接赋值

那我们这里使用的是一个List传递,然后直接用List中的 generate 方法进行生产List里的元素。最后的结果是生产了一个带值的List变量。代码如下:

void main () => runApp(MyApp(
  items: new List<String>.generate(1000, (i)=> "Item $i")
));

⚠️说明: 在 main函数 的 runApp方法 中调用了MyApp类,再给 MyApp类 的传递了一个items参数,并使 generate 生成器对items进行赋值
generate 方法传递两个参数,第一个参数是生成的个数,第二个是方法

对象接受参数

我们已经传递了参数,那MyApp这个类是需要接收的

MyApp({Key key, @required this.items}):super(key:key);

这是一个构造函数,除了Key,我们增加了一个必传参数,这里的@required意思就必传。:super如果父类没有无名无参数的默认构造函数,则子类必须手动调用一个父类构造函数

动态列表 ListView.builder()

接受了值之后,就可以直接调用动态列表进行生成了。具体代码如下:

import 'package:flutter/material.dart';

void main() =>
    runApp(MyApp(items: new List<String>.generate(1000, (i) => "Item $i")));

class MyApp extends StatelessWidget {
  final List<String> items;

  //构造器需要接收参数
  MyApp({Key key, @required this.items}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'ListView widget',
      home: Scaffold(
          body: new ListView.builder(
              itemCount: items.length,
              itemBuilder: (context, index) {
                return new ListTile(
                  title: new Text('${items[index]}'),
                );
              })),
    );
  }
}

6. GridView网格列表组件

列表组件已经学会了,那还有一种常用的列表,叫做网格列表。网格列表经常用来显示多张图片,比如我们经常使用的手机里的相册功能,大部分形式都是网格列表

简单例子演示

我们先不做一个相册的应用,而是使用文字,作一个最简单的网格列表,目的是先熟悉一下GridView的基本语法,代码如下,视频中会进行详细讲解:

import 'package:flutter/material.dart';
void main () => runApp(MyApp());
class MyApp extends StatelessWidget{
  @override
  Widget build(BuildContext context ){
      return MaterialApp(
        title:'ListView widget',
        home:Scaffold(
          body:GridView.count(
            padding:const EdgeInsets.all(20.0),
            crossAxisSpacing: 10.0,
            crossAxisCount: 3,
            children: <Widget>[
              const Text('I am Jspang'),
              const Text('I love Web'),
              const Text('jspang.com'),
              const Text('我喜欢玩游戏'),
              const Text('我喜欢看书'),
              const Text('我喜欢吃火锅')
            ],
          )
        ),
      );
  }
}

我们在body属性中加入了网格组件,然后给了一些常用属性:

  • padding 表示内边距,这个小伙伴们应该很熟悉。
  • crossAxisSpacing 网格间的空当,相当于每个网格之间的间距。
  • crossAxisCount 网格的列数,相当于一行放置的网格数量。

    图片网格列表

    加入文字作网格列表总是怪怪的,也不是很直观,我们利用图片来作一些网格列表。当然我们用一种更原生的方法,现在官方已经不鼓励使用这种方法了,但是为了你碰到时,不至于不知道怎么回事,所以我们作一下这种形式,但主要是为了作图片布局

import 'package:flutter/material.dart';

// import 'dart:math' as math;
void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        debugShowCheckedModeBanner: false,
        title: 'SliverGridDelegateWithFixedCrossAxisCount',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: Scaffold(
          appBar:
              AppBar(title: Text("SliverGridDelegateWithFixedCrossAxisCount")),
          body: SliverGridDelegateWithFixedCrossAxisCountPage(),
        ));
  }
}

class SliverGridDelegateWithFixedCrossAxisCountPage extends StatelessWidget {
  const SliverGridDelegateWithFixedCrossAxisCountPage({Key key})
      : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Container(
        child: GridView(
            gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: 2,
                mainAxisSpacing: 2.0,
                crossAxisSpacing: 2.0,
                childAspectRatio: 0.7),
            children: <Widget>[
          new Image.network(
              'http://img5.mtime.cn/mt/2018/10/22/104316.77318635_180X260X4.jpg',
              fit: BoxFit.cover),
          new Image.network(
              'http://img5.mtime.cn/mt/2018/10/10/112514.30587089_180X260X4.jpg',
              fit: BoxFit.cover),
          new Image.network(
              'http://img5.mtime.cn/mt/2018/11/13/093605.61422332_180X260X4.jpg',
              fit: BoxFit.cover),
          new Image.network(
              'http://img5.mtime.cn/mt/2018/11/07/092515.55805319_180X260X4.jpg',
              fit: BoxFit.cover),
          new Image.network(
              'http://img5.mtime.cn/mt/2018/11/21/090246.16772408_135X190X4.jpg',
              fit: BoxFit.cover),
          new Image.network(
              'http://img5.mtime.cn/mt/2018/11/17/162028.94879602_135X190X4.jpg',
              fit: BoxFit.cover),
          new Image.network(
              'http://img5.mtime.cn/mt/2018/11/19/165350.52237320_135X190X4.jpg',
              fit: BoxFit.cover),
          new Image.network(
              'http://img5.mtime.cn/mt/2018/11/16/115256.24365160_180X260X4.jpg',
              fit: BoxFit.cover),
          new Image.network(
              'http://img5.mtime.cn/mt/2018/11/20/141608.71613590_135X190X4.jpg',
              fit: BoxFit.cover),
        ]));
  }
}
  • childAspectRatio:宽高比,这个值的意思是宽是高的多少倍