flutter基础名词和简单代码案例

字号+ 编辑: 国内TP粉 修订: 种花家 来源: 本站原创 2023-09-11 我要说两句(0)

flutter在慕课网上的一篇笔记。

StatefulWidget表示为:带状态会变化的组件

StatelessWidget表示为:无状态不变化的组件


Hello World

敲一个简单的Hello World界面:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget
{
  @override
  Widget build(BuildContext context)
  {
    return MaterialApp(
      title: 'Welcome to Flutter',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Hello World'),
        ),
        body: Center(
          child: Text('Hello World!'),
        ),
      ),
    );
  }
}

上述代码中,

MyApp是我们自定义的一个类, 继承StatelessWidget代表它是静态组件, 这个静态组件类内部已经有build(BuildContext context)这个方法, 需要重写, 所以用到了@override这种dart写法。

import引入到的material.dart是谷歌研发的材质样式包。

MatrialApp里的title属性: App的名称

Scaffold组件出现在MaterialApp组件中的home区域, 他代表一个脚手架。

appBar属性: 标题栏, 用到了AppBar组件, 组件中包含一个title属性。

body: 标题栏下方的身体区域, 后面的Center组件代表四方位居中组件,再在里面写代码接着填充东西。



文本组件Text

在flutter当中, 一切都是组件, TextWidget就是基本组件效果之一。

为了学习TextWidget, 我们在child: Text挂件里面接着填充更多的内容, 以展示Text内部调用style等众多方法的效果。

以下是案例:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget
{
  @override
  Widget build(BuildContext context)
  {
    return MaterialApp(
      title: 'TextWidget展示效果',
      home: Scaffold(
        appBar: AppBar(
          title: Text('我是文本挂件的标题'),
        ),
        body: Center(
          child: Text(
              '我是文本挂件的内容,内容包含一大堆如此这般,内容包含一大堆如此这般,内容包含一大堆如此这般,内容包含一大堆如此这般,内容包含一大堆如此这般,内容包含一大堆如此这般',
            textAlign: TextAlign.left,
            maxLines: 2,
            overflow: TextOverflow.fade,
            style: TextStyle(
              fontSize: 25.0,
              color: Color.fromARGB(255, 255, 150, 150),
              decoration: TextDecoration.underline,
              decorationStyle: TextDecorationStyle.solid,
            ),
          ),
        ),
      ),
    );
  }
}


上述代码涉及到了文本对齐, 最大行数, 溢出处理和细节样式控制这几个组件方法。

其中:

fontSize属性表示文字大小,

maxtLines属性代表最大行数,

overflow属性代表文字溢出处理方式, 用到TextOverflow对象,

fontSize属性对应的值是float小数点精确1位, 否则填写其他将导致报错。

color属性当中, Color对象里的fromARGB, A代表透明度。

docoration属性是文字修饰类型, 一般都是下划线, 用到了TextDecoration对象

decorationStyle属性是修饰的样式, 这里用实线, 用到了TextDecorationStyle对象里的solid


层组件Container

相当于html标签p中的div标签,

代码案例:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget
{
  @override
  Widget build(BuildContext context)
  {
    return MaterialApp(
      title: 'TextWidget展示效果',
      home: Scaffold(
        appBar: AppBar(
          title: Text('我是文本挂件的标题'),
        ),
        body: Center(
          child: Container(
            child: Text(
              '我是文本挂件的内容,内容包含一大堆如此这般,内容包含一大堆如此这般,内容包含一大堆如此这般,内容包含一大堆如此这般,内容包含一大堆如此这般,内容包含一大堆如此这般',
              textAlign: TextAlign.left,
              maxLines: 2,
              overflow: TextOverflow.fade,
              style: TextStyle(
                fontSize: 25.0,
                color: Color.fromARGB(255, 255, 150, 150),
                decoration: TextDecoration.underline,
                decorationStyle: TextDecorationStyle.solid,
              ),
            ),
            alignment: Alignment.center,
            width:400.0,
            height:300.0,
            color: Colors.lightBlue,
            padding: const EdgeInsets.fromLTRB(10.0,60.0,40.0,0.0),
            margin: const EdgeInsets.all(20.0),
          ),
        ),
      ),
    );
  }
}

上述代码中, 出现了alignment, width, height, color这几个属性, 其中alignment用到了Alignment组件

padding属性和css一样, 是child子模块和文本组件之间存在的内边距,

margin属性是child子模块和body组件之间存在的外边距


decoration属性(定义如何修饰)

这个decoration和css当中的text-decoration不一样, 是修饰这里的Container盒子模型的, 因为书写起来比css复杂, 所以单独拉出来记录一下。

用到decoration的语句就不要用color属性来定义盒子颜色了, 把color属性注释掉。

代码案例如下:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget
{
  @override
  Widget build(BuildContext context)
  {
    return MaterialApp(
      title: 'TextWidget展示效果',
      home: Scaffold(
        appBar: AppBar(
          title: Text('我是文本挂件的标题'),
        ),
        body: Center(
          child: Container(
            child: Text(
              '我是文本挂件的内容,内容包含一大堆如此这般,内容包含一大堆如此这般,内容包含一大堆如此这般,内容包含一大堆如此这般,内容包含一大堆如此这般,内容包含一大堆如此这般',
              textAlign: TextAlign.left,
              maxLines: 2,
              overflow: TextOverflow.fade,
              style: TextStyle(
                fontSize: 25.0,
                color: Color.fromARGB(255, 255, 150, 150),
                decoration: TextDecoration.underline,
                decorationStyle: TextDecorationStyle.solid,
              ),
            ),
            alignment: Alignment.topLeft,
            width:400.0,
            height:300.0,
//            color: Colors.lightBlue,
            padding: const EdgeInsets.fromLTRB(20.0,60.0,40.0,0.0),
            margin: const EdgeInsets.all(20.0),
            decoration: BoxDecoration(
              gradient: const LinearGradient(
                  colors: [
                    Colors.red,
                    Colors.greenAccent,
                    Colors.tealAccent
                  ]
              )
            ),
          ),
        ),
      ),
    );
  }
}

上述代码当中:

gradient属性, 定义渐变的意思

LinearGradient组件, 是线性渐变组件的意思。

colors属性后面多了个s复数, 里面传入数组, 再用Colors组件挨个代入元素


图片组件 Image

Image组件可以通过以下方式来加载:

Image.asset 本地加载, 会导致安装包过大,

Image.network 常用的通过网络读图,

Image.file 本地图库加载, 加载图库地址xxx, 用户拍完照, 把图片读进来,

Image.memory 透过内存加载, 不常用


以下是代码案例:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget
{
  @override
  Widget build(BuildContext context)
  {
    return MaterialApp(
      title: 'TextWidget展示效果',
      home: Scaffold(
        appBar: AppBar(
          title: Text('我是文本挂件的标题'),
        ),
        body: Center(
          child: Container(
            child: Image.network(
              'http://www.wkwkk.com/filepool/cover/cover/1804/180415200453_6863.jpg',
              scale: 2.5,
              color: Colors.greenAccent,
              colorBlendMode: BlendMode.colorBurn,
              fit: BoxFit.cover,
//              repeat: ImageRepeat.repeatY,
            ),
            color: Colors.lightBlue,
            width: 400.0,
            height: 300.0,
          ),
          ),
        ),
    );
  }
}

上述代码当中, 在图片组件里涉及到了以下属性:

scale属性, 伸缩比例, 这里要注意, 相对于传统的css写法, scale属性指定的值越大, 图片反而会越小。

repeat属性, 和css一样, 图片重复方式, 如果写到Container组件里, 是要报错的, 它是图片组件里的属性

fit属性, 填充方式, 此时scale属性指定的值失效, 使用BoxFit组件, 也就是盒子模型内填充组件的意思, 一般用到的是BoxFit.cover, 这样通过不改变宽高比例的方式把图片刚好覆盖到图片上层的Container容器里, 如果是BoxFit.contain, 则刚刚接触到最大宽或者最大高的边界, 图片就不会膨胀下去。

colorBlendMode属性, 这个blend顺便查了一下字典, 有交融混合调配的意思, 那设定这个属性的大概目的也就明白了, 指定了color属性之后, colorBlendMode属性的值用到了BlendModel组件, 也就是混合模式, 目前1.0版本有那么十多种可供选择,这里也说不清楚,自己上IDE上调整来看吧。


ListView和ListTile组件

这两个组件通常成对出现, ListView组件相当于html5概念中的ul标签, ListTile组件相当于html5概念中的li标签。查字典时看到单词tile翻译成砖、瓦片,此时代码工作者就是搬这个砖的。

代码案例如下:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget
{
  @override
  Widget build(BuildContext context)
  {
    return MaterialApp(
      title: 'flutter app test',
      home: Scaffold(
        appBar: AppBar(
          title: Text('ListView'),
        ),
        body: ListView(
          children: <Widget>[
            ListTile(
              leading: Icon(Icons.person),
              title: Text('人物1'),
            ),
            ListTile(
              leading: Icon(Icons.person),
              title: Text('人物2'),
            ),
            ListTile(
              leading: Icon(Icons.person),
              title: Text('人物3'),
            ),
          ],
        ),
        ),
    );
  }
}

上述代码中,涉及到了children: <Widget>[...]这种dart专用写法,习惯就好, 之后就在数组里依次写进各组件。


ListView组件内, 嵌套Image组件列表

就和html5书写一样, 我们想在ul里面写上一排图片, <li><img ... /></li>...<li><img ... /></li>如何做到的呢?

修改上边一部分代码片段, 改为如下:

body: ListView(
  children: <Widget>[
    Image.network('http://www.wkwkk.com/filepool/cover/img_17021914350735944.jpg'),
    Image.network('http://www.wkwkk.com/filepool/cover/img_17021914350735944.jpg'),
    Image.network('http://www.wkwkk.com/filepool/cover/img_17021914350735944.jpg'),
    Image.network('http://www.wkwkk.com/filepool/cover/img_17021914350735944.jpg'),
  ],
),

上述代码会实现竖向的图片列表, 有人会纠结于new不new这个Image组件, 无论如何写法,效果都雷同。


横向组件列表

ListView组件当中, 有scrollingDirection属性, 是定义滚动方向的, 其中:

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: 'flutter app test',
      home: Scaffold(
        appBar: AppBar(
          title: Text('ListView横向列表'),
        ),
        body: Center(
          child: Container(
            height: 200.0,
            child: ListView(
              scrollDirection: Axis.horizontal,
              children: <Widget>[
                Container(
                  width: 180.0,
                  color: Colors.green
                ),
                Container(
                    width: 180.0,
                    color: Colors.lightBlue,
                ),
                Container(
                    width: 180.0,
                    color: Colors.yellowAccent
                ),
                Container(
                    width: 180.0,
                    color: Colors.blueGrey
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

上述代码中, 使用几个Container加载色块, 加以横向排列来生成了预期效果。


ListView.builder动态列表建立和传参

以下是代码案例:

import 'package:flutter/material.dart';

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

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

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

  @override
  Widget build(BuildContext context)
  {
    return MaterialApp(
      title: 'flutter app test',
      home: Scaffold(
        appBar: AppBar(
          title: Text('ListView动态列表'),
        ),
        body: ListView.builder(
          itemCount: item.length,
          itemBuilder:(context, index){
            return new ListTile(
              title: new Text("{$item[index]}"),
            );
          }
        ),
      ),
    );
  }
}

上述代码当中ListView.builer方法即是生成动态列表方法。

在该方法内,

itemCount属性传入参数的长度, 即参数名.length

itemBuilder属性固定写入两个参数, context代表上下文, index代表List数组索引, 此时, 值作用域return所返回的是ListTile砖块, 简单写了一个$item套索引的方式来打印出每个List索引指向的值。


GridView组件

以下是代码案例:

import "package:flutter/material.dart";

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

class MyApp extends StatelessWidget
{
  @override
  Widget build(BuildContext context)
  {
    return MaterialApp(
      title: '电影海报测试',
      home: Scaffold(
        appBar: AppBar(
          title: Text("我是标题"),
        ),
        body: GridView.count(
          padding:const EdgeInsets.all(10.0),
          crossAxisSpacing: 10.0,
          crossAxisCount: 3,
          children: <Widget>[
            Text('It was mine'),
            Text('It was mine'),
            Text('It was mine'),
            Text('It was mine'),
            Text('It was mine'),
            Text('It was mine'),
            Text('It was mine'),
            Text('It was mine'),
            Text('It was mine'),
          ]
        )
      ),
    );
  }
}

上述代码当中GridView.count是其中一种写法,也可以直接写为GridView(...)这种方式。

crossAxisSpacing属性代表横向格子之间的间距, 可以理解成html的td左右间距,

crossAxisCount属性代表一行多少个元素,

另外还有一个mainAxisSpacing属性, 代表竖向(列所在)各个格子之间的间距, 可以理解成html的td上下间距。

这些都可以通过padding属性来定义格子的间距, 不过padding属性不允许直接传double类型值, 需要传类似EdgeInsets组件中的all方法, 如例子中那样。


接下来把用Text组件填充的部分做成图片:

import "package:flutter/material.dart";

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

class MyApp extends StatelessWidget
{
  @override
  Widget build(BuildContext context)
  {
    return MaterialApp(
      title: '电影海报测试',
      home: Scaffold(
        appBar: AppBar(
          title: Text("我是标题"),
        ),
        body: GridView.count(
          // padding:const EdgeInsets.all(10.0),
          crossAxisSpacing: 10.0,
          crossAxisCount: 3,
          mainAxisSpacing: 10.0,
          childAspectRatio: 1.2,
          children: <Widget>[
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
          ]
        )
      ),
    );
  }
}

上述代码中

childAspectRatio属性代表的是宽高比,1是正方形,值越大,越宽,反之图片范围越高。


GridView组件直接传值的写法(不使用count)

代码案例如下:

import "package:flutter/material.dart";

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

class MyApp extends StatelessWidget
{
  @override
  Widget build(BuildContext context)
  {
    return MaterialApp(
      title: '电影海报测试',
      home: Scaffold(
        appBar: AppBar(
          title: Text("我是标题"),
        ),
        body: GridView(
          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
          // padding:const EdgeInsets.all(10.0),
          crossAxisSpacing: 10.0,
          crossAxisCount: 3,
          mainAxisSpacing: 10.0,
          childAspectRatio: 1.2,
          ),
          children: <Widget>[
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
          ]
        )
      ),
    );
  }
}


阅完此文,您的感想如何?
  • 有用

    0

  • 没用

    0

  • 开心

    0

  • 愤怒

    0

  • 可怜

    0

1.如文章侵犯了您的版权,请发邮件通知本站,该文章将在24小时内删除;
2.本站标注原创的文章,转发时烦请注明来源;
3.交流群: PHP+JS聊天群

相关课文
  • Invalid prop custom validator check failed for prop navigationBarTextStyle

  • svg是什么文件格式?如何打开svg文件?

  • Cordova报错Could not find an installed version of Gradle either in Android Studio

  • 支付宝小程序不支持html语法富文本,在Uniapp上的解决方法

我要说说
网上宾友点评