Flutter学习总结(十二、Flutter基本组件第二部分)

Flutter基本组件第二部分

一起从0开始学习Flutter!

上一篇我们了解了AppBar,FloatingActionButton,Text,BottomNavigationBar的基本使用,这篇将会介绍TabBar,TabBarView,Image

1.TabBar

也是我们经常使用的控件,在现在的APP中越来越多的信息需要展示的时候,tabbar的出现可以解决页面冗长无序的问题,可以根据内容的分类进行划分tab。

1const TabBar({ 2 Key key, 3 @required this.tabs,//参照下面详解 4 this.controller,//参照下面详解 5 this.isScrollable = false,//如果tab很多是否可以滚动显示,如果是False会平分宽度以全部显示,如果是True则会居中显示全部的tab 6 this.indicatorColor,//在选中的tab下方的指示器颜色 7 this.indicatorWeight = 2.0, //指示器的高度 8 this.indicatorPadding = EdgeInsets.zero,//指示器底部添加的padding 9 this.indicator,//设定指示器的样式,默认的为UnderlineTabIndicator,我们可以仿照它写自己想要的指示器的样式 10 this.indicatorSize,//参照下面详解 11 this.labelColor,//选中label的颜色 12 this.labelStyle,//选中label的样式,传入的是TextStyle 13 this.labelPadding,//可以给label加padding,padding的添加方式也是通过EdgeInsets类来添加。 14 this.unselectedLabelColor,//没有选中的label的颜色 15 this.unselectedLabelStyle,//没有选中的label的样式,传入的是TextStyle 16 this.dragStartBehavior = DragStartBehavior.start, 17 this.onTap,//点击事件响应,调用给返回点击的位置position 18 }) 19 20

tabs
需要添加的tab元素,也就是根据需要设定我们要显示的头部。会添加一组Tab信息,先看下单个的Tab。

1const Tab({ 2 Key key, 3 this.text,//想要显示的标题文字 4 this.icon,//可以自己添加Icon 5 this.child,//扩展的其他的想要添加的内容 6 }) 7 8

controller
我们需要传入TabController对象,根据名字也看得出来是控制Tab的一个控制器,看下如何创建该对象。

1TabController({ 2int initialIndex = 0,//初始化时默认选中的位置 3@required this.length, //Tab要显示的数量 4@required TickerProvider vsync //控制Tab和TabView的同步,我们可以直接让创建Controller的类继承或者with SingleTickerProviderStateMixin 5}) 6 7

创建一个controller_controller = TabController(vsync: this, length: tabs.length);这里的this也就是当前类对象,我们还需要让当前类继承自SingleTickerProviderStateMixin,我们可以这样写:class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin 还记得这个with关键字吧,如果忘记了可以回去看下Dart的类继承里面的介绍。
indicatorSize
指示器的宽度
TabBarIndicatorSize.tab 和tab整个的宽度一致
TabBarIndicatorSize.label 和tab上面文字的宽度一致

2.TabBarView

是和TabBar一起搭配使用的,可以根据选择的tab显示不同的页面。

1const TabBarView({ 2 Key key, 3 @required this.children, 4 this.controller, 5 this.physics, 6 this.dragStartBehavior = DragStartBehavior.start, 7 }) 8 9

children
也即是我们需要添加的TabBarView的布局页面,这里可以根据需要添加我们前面说到的容器等组件。给出一个简单的示例:

1TabBarView( 2 controller: _controller, 3 children: tabs.map( 4 (Tab tab) => Container( 5 child: Center( 6 child: Text(tab.text), 7 )), 8 ).toList()) 9 10

用到的是我们前面说到的map关键字,通过map我们将tab转为一个个的Center容器。然后直接将整个数组用来显示。
controller
同TabBar的Controller,一般将他们的Controller用一个变量来设置,来统一行为。
physics
控制tabBarView在滑动的操作,默认为ScrollPhysics,如果想要修改滑动操作可以仿照该类进行重写。
dragStartBehavior
拖动的滑动行为,在默认滑动的时候默认值为DragStartBehavior.start,自测的在修改为DragStartBehavior.down后也没有看到变化。

3.Image

Image可以是在我们日常使用中最频繁的了,也给我们提供了多种显示图片的方法,我们可以根据需要来进行图片的显示。先看下最基础的Image是需要我们如何做的:

1 const Image({ 2 Key key, 3 @required this.image,//需要自己实现的获取图片的方式。 4 this.frameBuilder,//参照下面详细解释 5 this.loadingBuilder,//参照下面详细解释 6 this.semanticLabel,//关于图片的描述,不重要 7 this.excludeFromSemantics = false, //排除image的语义,True则会忽略semanticLabel的内容 8 this.width,//设置显示的宽度 9 this.height,//设置显示的高度,需要注意的是如果宽高小于图片的宽高则会以最短边为基准等比例的裁剪,居中显示,如果宽高大于图片的宽高则图片不拉伸居中显示 10 this.color, //设置图片的前景色,图片的主色会根据设定变化 11 this.colorBlendMode,//图片的混合模式,一般与color配合使用 12 this.fit,//参照下面详细解释 13 this.alignment = Alignment.center,//对齐方式,前面列举了很多,不再赘述 14 this.repeat = ImageRepeat.noRepeat,//参照下面详细解释 15 this.centerSlice,//参照下面详细解释 16 this.matchTextDirection = false,//参照下面详细解释 17 this.gaplessPlayback = false,//图片的路径变化时是否保留显示原图片,True是保留,False则不会保留,重新加载的时候会空白一直等到图片完全加载完 18 this.filterQuality = FilterQuality.low,//图片的质量控制 19 }) 20 21

frameBuilder
可以给Image添加边框以及间距,也可以做出堆叠其他的控件的效果,列举一个添加边框的例子:

1frameBuilder: (BuildContext context, Widget child, int frame, 2 bool wasSynchronouslyLoaded) { 3 return Padding( 4 padding: EdgeInsets.only(left: 5, top: 5), 5 child: child, 6 ); 7 }, 8 9

loadingBuilder
在图片加载的时候,还没有加载完成之前的显示,当加载完成之后就会被image覆盖掉。注意是覆盖不是替换,如果加载的是一个透明或者半透的图则会显示出来loadingBuilder的组件。列举一个简单实用:

1loadingBuilder: (BuildContext context, Widget child, 2 ImageChunkEvent loadingProgress) { 3 return Container( 4 color: Colors.yellow, 5 child: child); 6 }, 7 8

fit
在如果宽高都大于图片的时候可以通过fit属性填充多出来的空间。
BoxFit.none 不设置
BoxFit.fill 宽高填满,会引起图片的拉伸
BoxFit.contain 以最大边为基准缩放图片,完全显示出图片,会有空白
BoxFit.cover 以最小边为基准缩放图片,填充满图片,会被裁切
BoxFit.fitWidth 图片比例不变,宽填充满,会有空白
BoxFit.fitHeight 图片比例不变,高填充满,会有空白
BoxFit.scaleDown 在不大于原图尺寸的时候会等比例缩小,大于图片尺寸则会原图尺寸根据alignment设置
repeat
对于没有填充满的区域是否以原图片重复添加的方式填充
ImageRepeat.repeat X轴和Y轴的空白空间都进行填充
ImageRepeat.repeatX X轴的空白空间进行填充
ImageRepeat.repeatY Y轴的空白空间进行填充
ImageRepeat.noRepeat 不进行填充
centerSlice
我们如果对一个图片的局部进行拉伸,则可以通过该属性进行设置,需要传入一个Rect的对象,我们可以根据需要创建该实例,举个简单的例子:

1centerSlice: Rect.fromLTRB(0,20,40,59), 2 3

用图片的宽为0-40,高为20-59的部分进行图片的拉伸,并填充满整个image。
matchTextDirection
控制图片的显示方向是否跟文字的显示方向一致,需要配合Directionality容器使用,Directionality容器可以控制子控件的显示方向,如果设置为false则不跟随Directionality设置的方向显示,True则会跟随一样显示。举个简单例子:

1 Directionality( 2 textDirection: TextDirection.rtl, 3 child: Image.network( 4 "https://img.jpg", 5 matchTextDirection: true, 6 ...}) 7 8

上面刚刚介绍的是图片的默认构造方法,这里使用的时候我们还需要自己来写一个加载方式,否则无法显示出来图片,但是Flutter已经帮我们创建了几种加载方式,我们只需要根据场景选择合适的加载方式即可。

方式一:

1Image.asset() 2 3

在工程的根目录下创建assets/images目录,将要显示的本地图片放到该目录下。
在根目录下的pubspec.yaml文件中添加assets的引用:

1flutter: 2 uses-material-design: true 3 assets: 4 - assets/images/ 5 6

这样我们才可以在程序中引用到该图片。在使用中与基本的Image会有下面几点不同:

1Image.asset( 2 String name, { 3 AssetBundle bundle,//设定要读取的资源Bundle,如果不设置则会从rootBundle里获取 4 String package,//在取别的library的资源时候需要添加包名 5 int cacheWidth,//指定的缓存的宽 6 int cacheHeight,//指定的缓存的高 7 ... 8 }) 9 10

方式二:

1Image.network(); 2 3

从网络上获取图片,需要注意添加网络权限,在android的manifest文件中添加:

1 <uses-permission android:name="android.permission.INTERNET"/> 2 3

将图片的地址直接传入即可,其他参数与assets没有区别。

方式三:

1Image.file(); 2 3

需要传入一个File对象,File对象的需要我们导入IO包,import 'dart:io' show File;
File的创建也很简单,我们只需要传入文件的路径即可创建成功。其他参数与assets没有区别。

方式四:

1Image.memory(); 2 3

从内存中的bytes集合中获取,将其传入参数中进行显示,其他参数与assets没有区别。

基本上我们通过这两篇的学习可以写一个简单的小demo跑起来了,还是需要多加练习,单看这些属性有些无法理解的很透彻还是需要都实现一遍来看看效果的。

接下来我们学习Flutter基础组件第三部分

代码交流 2021