与用户进行交互,比如通过键盘输入内容、通过滑动屏幕移动滑块、点击时改变状态,数据更新状态等一些列用户的交互。这时我们应该选择使用StatefulWidget创建一个有状态控件。

如果仅依赖于对象本身的配置信息,仅仅是用于展示给定的信息。那我们应该选择使用StatelessWidget创建一个无状态控件。

StatelessWidget 和 StatefulWidget的区别

StatelessWidget是状态不可变的widget。初始状态设置以后就不可再变化。如果需要变化需要重新创建。StatefulWidget可以保存自己的状态。那问题是既然widget都是immutable的,怎么保存状态?其实Flutter是通过引入了State来保存状态。当State的状态改变时,能重新构建本节点以及孩子的Widget树来进行UI变化。注意:如果需要主动改变State的状态,需要通过setState()方法进行触发,单纯改变数据是不会引发UI改变的。



作者:王伟desire
链接:https://www.jianshu.com/p/9013e2f68e9f
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
1,Text组件包裹文字,Center组件
 //在主体的中间区域,添加一个hello world 的文本
        // body:Center(
        //   child:Text(
        //    'Hello JSPang  ,非常喜欢前端,并且愿意为此奋斗一生。我希望可以出1000集免费教程。',
        //    textAlign:TextAlign.left,
        //    maxLines: 1,
        //    overflow: TextOverflow.ellipsis,
        //    style: TextStyle(
        //      fontSize: 25.0,
        //      color: Color.fromARGB(255, 255, 150, 150),
        //      decoration: TextDecoration.underline,
 
        //      decorationStyle: TextDecorationStyle.solid

        //    ),
        //     ),
          
        // ),

2,Container(容器控件)在Flutter是经常使用的控件,它就相当于我们HTML里的<div>标签。

具有以下相关属性。

// body:Center(child: Container(
        //   child:new Text('zenganglan',
        //   style:TextStyle(fontSize:40.0),
        
        //   ),
        //   alignment: Alignment.topLeft,盒子里面文字内容的位置
        //   width:500.0,盒子宽度
        //   height:400.0,盒子高度
        //   // color:Colors.lightBlue,盒子背景颜色
        //   padding: const EdgeInsets.all(10.0),盒子内边距
        //   margin: const EdgeInsets.fromLTRB(10.0, 10.0, 10.0, 20.0),   盒子上下左右外边距  //
const EdgeInsets.all(10.0)
        //   decoration: new BoxDecoration(////

decoration是 container 的修饰器,主要的功能是设置背景和边框。


比如你需要给背景加入一个渐变,这时候需要使用BoxDecoration这个类,代码如下(需要注意的是如果你设置了decoration,就不要再设置color属性了,因为这样会冲突)

        //     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资源图片,这个我目前用的不是很多,所以没什么发言权。
 body:Center(
          child:Container(
            child:new Image.network(
              'http://blogimages.jspang.com/blogtouxiang1.jpg',
图片混合模式(colorBlendMode)和color属性配合使用,能让图片改变颜色,

 

               color: Colors.greenAccent, colorBlendMode: BlendMode.hardLight,
//fit属性可以控制图片的拉伸和挤压 fit: BoxFit.fitHeight,
// repeat: ImageRepeat.repeatX, scale: 1.0, ), width:300.0, height:200.0, color: Colors.lightBlue ), )

  • BoxFit.fill:全图显示,图片会被拉伸,并充满父容器。

  • BoxFit.contain:全图显示,显示原比例,可能会有空隙。

  • BoxFit.cover:显示可能拉伸,可能裁切,充满(图片要充满整个容器,还不变形)。

  • BoxFit.fitWidth:宽度充满(横向充满),显示可能拉伸,可能裁切。

  • BoxFit.fitHeight :高度充满(竖向充满),显示可能拉伸,可能裁切。

  • BoxFit.scaleDown:效果和contain差不多,但是此属性不允许显示超过源图片大小,可小不可大。

图片混合模式(colorBlendMode)和color属性配合使用,能让图片改变颜色,
 //repeat 重合
  • ImageRepeat.repeat : 横向和纵向都进行重复,直到铺满整个画布。

  • ImageRepeat.repeatX: 横向重复,纵向不重复。

  • ImageRepeat.repeatY:纵向重复,横向不重复。

 

4 竖向或者横向列表组件 ListView组件,如果高度宽度有限子元素过多就可形成滑动卡片类似前后滚动的效果

scrollDirection属性

ListView组件的scrollDirection属性只有两个值,一个是横向滚动,一个是纵向滚动。默认的就是垂直滚动,所以如果是垂直滚动,我们一般都不进行设置。

  • Axis.horizontal:横向滚动或者叫水平方向滚动。
  • Axis.vertical:纵向滚动或者叫垂直方向滚动。

 

 body: Center(
          child:Container(
            height: 200.0,
            child: new ListView(
scrollDirection:Axis.horizontal,
//<Widget>数组里可以加任何组件元素,比如 new Container , new Image new ListTitle children:<Widget>[ new Container( width:180.0, color:Colors.deepOrange ), new Container( width:170.0, color:Colors.deepOrangeAccent ), new Container( width:160.0, color:Colors.green ) ] ), ) ), // 分离ListView,万事皆组件 class MyList extends StatelessWidget{ @override Widget build(BuildContext context){ return ListView( scrollDirection:Axis.horizontal, children:<Widget>[ new Container( width:180.0, color:Colors.deepOrange ), new Container( width:170.0, color:Colors.deepOrangeAccent ), new Container( width:160.0, color:Colors.green ), ], ); } } body: Center( child:Container( height: 200.0, child: MyList() ) ),

 

 

5.动态数据传参list数据类型

import 'package:flutter/material.dart';
void main () => runApp(MyApp(
  items: new List<String>.generate(1000, (i)=> "Item $i")
));

class MyApp extends StatelessWidget{
这是一个构造函数,除了Key,我们增加了一个必传参数,这里的@required意思就必传。:super如果父类没有无名无参数的默认构造函数,则子类必须手动调用一个父类构造函数
  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(//动态列表进行生成ListView.builder
           itemCount:items.length,
itemBuilder:(context,index){
return new ListTile( title:new Text('${items[index]}'
), );
}
)
), ); } }

 

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

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

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

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

 

6 网格组件GridView

  • padding:表示内边距,这个小伙伴们应该很熟悉。
  • crossAxisSpacing:网格间的空当,相当于每个网格之间的间距。
  • crossAxisCount:网格的列数,相当于一行放置的网格数量。
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('我喜欢吃火锅')
            ],
          )
        ),
      );
  }
}