Flutter学习之认知基础组件

this.fontWeight,//绘制文本时的字体粗细
this.fontStyle,//字体变体
this.letterSpacing,//水平字母之间的空间间隔(逻辑像素为单位),可以负值
this.wordSpacing,//单词之间添加的空间间隔(逻辑像素为单位),可以负值
this.textBaseline,//对齐文本的水平线
this.height,//文本行与行的高度,作为字体代销的倍数
this.locale,//用于选择区域定字形的语言环境
this.foreground,//文本的前景色,不能与color共同设置
this.background,//文本背景色
this.shadows,//Flutter Decoration背景设定(边框,圆角,阴影,渐变等)
this.decoration,//绘制文本装饰,添加上下划线,删除线
this.decorationColor,//文本装饰的颜色
this.decorationStyle,//文本装饰的样式,控制画虚线,点,波浪线
this.debugLabel,
String fontFamily,//使用字体的名称
String package,
})

5.RichText

这是显示丰富样式的文本,这什么意思呢?Text只能显示一种样式的文字,如果想在一段文字中显示多种样式,就好像Android里面的SpannableString,就需要使用RichText,直接上例子:

//富文本样式
class RichWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return RichText(
text: TextSpan(
text: ‘This is RichText’,
style: new TextStyle(
//false的时候不显示
inherit: true,
//字体大小
fontSize: 16,
//黑色
color: Colors.black
),
children: [
new TextSpan(
text: ‘Android艺术探索’,
style: new TextStyle(
color: Colors.redAccent,
//字体粗细
fontWeight: FontWeight.bold,
),

),

new TextSpan(text: ‘第一行代码’),
new TextSpan(
text: ‘Android进阶之光’,
style: new TextStyle(
color: Colors.indigo,
//字体样式
fontSize: 20,
),
)
],
)
);
}
}

//屏幕中间改为富文本widget
//主体
body: new Center(
//Text在屏幕中央显示一个文本 改为自定义样式
//child: new CustomTextStyle(‘This is a Text’),
//富文本
child:new RichWidget()
),

效果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

6.TextField

下面看看文本输入框,文本输入框平时会经常用到:

body: new Center(
//Text在屏幕中央显示一个文本 改为自定义样式
//child: new CustomTextStyle(‘This is a Text’),
//富文本
//child:new RichWidget()
//文本输入框
child:new TextFieldWidget()
),

//文本输入框
class TextFieldWidget extends StatelessWidget{
@override
Widget build(BuildContext context){
return TextField();
}
}

上面例子只能输入文本内容,如果想要获取输入框内容,就要添加一个controller,通过这个controller添加通知来获取TextField的值,我们一般点击按钮或者需要跟后台交互就要读取controller.text的值:

class MyHomePage extends StatelessWidget {
//获取TextEditingController
final editController = TextEditingController();
//IconButton
new IconButton(
//图标
icon: new Icon(Icons.add_a_photo),
//提示
tooltip: ‘Add photo’,
//点击事件
onPressed: () {
//输出
print(‘text inputted: ${editController.text}’);
//Toast
Fluttertoast.showToast(
msg:‘text inputted: ${editController.text}’,
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIos: 1,
);
},
),

//主体
body: new Center(
//Text在屏幕中央显示一个文本 改为自定义样式
//child: new CustomTextStyle(‘This is a Text’),

//富文本
//child:new RichWidget()

//文本输入框 以构造函数传递controller
child:new TextFieldWidget(editController)
),
}
//文本输入框
class TextFieldWidget extends StatelessWidget{

final controller;
//构造函数传值
TextFieldWidget(this.controller);
@override
Widget build(BuildContext context){
return TextField(
controller: controller,
);
}
}

注意上面用到了ToastToast库这里很简单需要两步:

  1. pubspec.yaml添加依赖库fluttertoast: ^2.1.1
  2. 导入import 'package:fluttertoast/fluttertoast.dart';

重新运行即可,热重载可能会出现异常。运行在iOS模拟器需要装brewCocoaPods,有问题运行flutter doctor,它真是如名字一样,就是帮你诊断有没有错误信息,会显示具体信息。效果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

下面改一下样式:

return TextField(
controller: controller,
//最大长度,右下角会显示一个输入数量的字符串
maxLength: 26,
//最大行数
maxLines: 1,
//是否自动更正
autocorrect: true,
//是否自动对焦
autofocus: true,
//设置密码 true:是密码 false:不是秘密
obscureText: true,
//文本对齐样式
textAlign: TextAlign.center,

);

效果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

7.Image

Image很好理解就是在界面上区域显示一张图片,而这张图片的来源可以是:本地,网络,资源图片等。下面一一演示一下:

7.1.项目图片资源

首先新建一个资源目录:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

pubspec.yaml中配置图片路径,来识别应用程序所需的assets:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

class MyHomePage extends StatelessWidget {
//主体
body: new Center(

//图片加载
child:new ImageWidget()
),
}
//图片
class ImageWidget extends StatelessWidget{
@override
Widget build(BuildContext context){
//项目资源图片 方式一
return Image(
image: new AssetImage(‘images/Image_fluttericon.jpeg’),
);
//项目资源图片 方式二
// return Image.asset(‘images/Image_fluttericon.jpeg’);
}
}

效果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

7.2.网络图片加载

下面进行网络图片加载,也是很简单:

class MyHomePage extends StatelessWidget {
//图片路径
String image_url = “https://ws1.sinaimg.cn/large/0065oQSqgy1fze94uew3jj30qo10cdka.jpg”;
//主体
body: new Center(

//图片加载
child:new ImageWidget(image_url)
),
}
//图片
class ImageWidget extends StatelessWidget{
String image_url;
ImageWidget(this.image_url);
@override
Widget build(BuildContext context){
return Image.network(image_url);
}
}

效果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

下面用一个库来加载和缓存网络图像,也可以与占位符和错误小部件一起使用,在pubspec.yaml添加依赖cached_network_image: ^0.4.1+1,在Dart文件导入这个库import 'package:cached_network_image/cached_network_image.dart';

//图片
class ImageWidget extends StatelessWidget{

String image_url;
ImageWidget(this.image_url);
@override
Widget build(BuildContext context){
return new CachedNetworkImage(
imageUrl: image_url,
//占位符
placeholder: new CircularProgressIndicator(),
//加载错误时显示的图片
errorWidget: new Icon(Icons.error),
//宽高
width:200,
height: 200,
);
}
}

当图片还没加载出来的时候会显示占位符,当如果加载出错会显示errorWidget的图片。

7.3.声明分辨率相关的图片

另外Flutter可以为当前设备添加合适其分辨率的图像,其实对于Android原生来说,就是在不同分辨率目录下放置不同分辨率的图片,只不过flutter并不是创建drawable-xxdpi文件,而是创建以下文件夹:

…/logo.png
…/Mx/logo.png
…/Nx/logo.png

其中M和N是数字标识符,对应于其中包含的图像分辨率,它们指定不同素设备像比例的图片,主资源默认对应于1.0倍的分辨率图片。看下面例子:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在设备像素比率为1.8的设备上,images/2.0x/logo.png 将被选择。对于2.7的设备像素比率,images/3.0x/logo.png将被选择。如果未在Image控件上指定渲染图像的宽度和高度,以便它将占用与主资源相同的屏幕空间量(并不是相同的物理像素),只是分辨率更高。 也就是说,如果images/logo.png是72px乘72px,那么images/3.0x/logo.png应该是216px乘216px; 但如果未指定宽度和高度,它们都将渲染为72像素×72像素(以逻辑像素为单位)。pubspec.yaml中asset部分中的每一项都应与实际文件相对应,但主资源项除外。当主资源缺少某个资源时,会按分辨率从低到的顺序去选择,也就是说1.0x中没有的话会在2.0x中找,2.0x中还没有的话就在3.0x中找。

return Image(
// 系统会根据分辨率自动选择不同大小的图片
image: AssetImage(‘images/logo.png’),
// …
),

8.FlatButton

Flutter预先定义了一些按钮控件,如FlatButtonRaisedButtonOutlineButtonIconButton

  1. FlatButton:扁平化按钮,继承自MaterialButton
  2. RaisedButton:凸起按钮,继承自MaterialButton
  3. OutlineButton:带边框按钮,继承自MaterialButton
  4. IconButton:图标按钮,继承自StatelessWidget

下面看看FlatButton,其他的只是样式稍微不一样,大致用法一样。

//按钮
class FlatButtonWidget extends StatelessWidget{

@override
Widget build(BuildContext context){
return FlatButton(
onPressed: (){
Fluttertoast.showToast(
msg:‘你点击了FlatButton’,
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIos: 1,
);
},
child: Text(‘FlatButton’),
color: Colors.blue,//按钮背景色
textColor: Colors.white,//文字的颜色
onHighlightChanged: (bool b){//水波纹变化回调

},
disabledColor: Colors.black,//按钮禁用时的显示的颜色
disabledTextColor: Colors.black38,//按钮被禁用的时候文字显示的颜色
splashColor: Colors.white,//水波纹的颜色
);

}
}

上面也设置了一些属性,效果图如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

四、Flutter布局

Flutter中拥有30多种预定义的布局widget,常用的有ContainerPaddingCenterFlexRowColumListViewGridView。用一个表格列出它们的特性和使用。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

下面一一介绍简单用法:

1.Container

一个拥有绘制、定位、调整大小的widget,示意图如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

下面直接上例子:

class MyHomePage extends StatelessWidget {

body:new ContainWidget(),

}
//Container布局
class ContainWidget extends StatelessWidget{

@override
Widget build(BuildContext context){
return Container(
child:Text(“My name is Knight”),
color: Colors.indigo,
width:200,//宽
height:200,//高
margin:EdgeInsets.fromLTRB(5,5,5,5),//设置外边距
padding:EdgeInsets.all(30),//内边距
);
}
}

下面设置边框,添加圆角:

//Container布局
class ContainWidget extends StatelessWidget{

@override
Widget build(BuildContext context){
return Container(

padding:EdgeInsets.all(30),//内边距
decoration: BoxDecoration(//设置边框
//背景色
color:Colors.redAccent,
//圆角
borderRadius: BorderRadius.circular(6),
),
);
}
}

运行效果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.Padding

一个Widget,会给其子Widget添加指定的填充,示意图如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

class MyHomePage extends StatelessWidget {

body: new PaddingWidget(),

}
//Padding布局
class PaddingWidget extends StatelessWidget{

@override
Widget build(BuildContext context){
return Padding(
//设置左上右下内边距为4,10,6,8
padding:EdgeInsets.fromLTRB(4, 10, 6, 8),
child: Text(‘My name is Knight’),
);
}
}

效果图如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

下面实现Container嵌套Padding:

//Container嵌套Padding
class ContainPaddWidget extends StatelessWidget{
@override
Widget build(BuildContext context){
return Container(
width:200,//宽
height:200,//高
child: Padding(
padding:EdgeInsets.fromLTRB(4, 10, 6, 8),
child: Text(“My name is Knight”),
),
decoration: BoxDecoration(//设置边框
//背景色
color:Colors.redAccent,
//圆角
borderRadius: BorderRadius.circular(6),
),
);
}
}

效果图如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3.Center

将其子widget居中显示在自身内部的widget,示意图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

//Center
class CenterWidget extends StatelessWidget{

@override
Widget build(BuildContext context){
return Container(
width:200,//宽
height:200,//高
child: Center(
child: Text(“My name is Knight”),
),
decoration: BoxDecoration(//设置边框
//背景色
color:Colors.redAccent,
//圆角
borderRadius: BorderRadius.circular(6),
),
);
}
}

运行效果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Center作为Container的孩子,Text所以在布局的中间。

4.Stack

可以允许其子Widget简单的堆叠在一起,层叠布局,示意图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

下面直接上代码,把之前的布局全部用上试试:

class MyHomePage extends StatelessWidget {

body:new Center(
child:new StackWidget()
),

}
//层叠布局
class StackWidget extends StatelessWidget{

@override
Widget build(BuildContext context){
return Stack(
children: [
new Image.network(‘https://ws1.sinaimg.cn/large/0065oQSqgy1fze94uew3jj30qo10cdka.jpg’,
width:300.0,//宽
height:300.0,//高
),
new Opacity(
opacity: 0.6,//不透明度
child:new Container(
width:100.0,
height:100.0,
color:Colors.redAccent,
),
),
new Opacity(
opacity: 0.6,
child:new Container(
width: 200.0,
height:200.0,
color:Colors.indigo,
),
),
],
);
}
}

运行效果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

可以看到控件都按Stack左上角对齐,叠在一起,下面改一下显示位置:

//层叠布局
class StackWidget extends StatelessWidget{

@override
Widget build(BuildContext context){
return Stack(
//Aliginment的范围是[-1,1],中心是[0,0].注释有写
//和Android一样,左移的取值是往1取,右移是往-1取
//这里注意,它是取stack里范围最大的布局为基准,下面是以Container为//基准对齐
alignment: new Alignment(-0.6, -0.6),

);
}
}

运行效果图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

5.Colum

在垂直方向上排列子Widget,示意图如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

直接上代码:

class MyHomePage extends StatelessWidget {

body:new ColumnWidget(),

}
//Column布局
class ColumnWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
children: [
Container(
color:Colors.blue,
width: 50,
height: 50,
),
Container(
color:Colors.black,
width:50,
height:50,
),
Container(
color:Colors.green,
width:50,
height:50,
),
],
);
}
}

运行效果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

下面简单设置一下排列方式属性:

return Column(
//设置垂直方向的对齐方式
mainAxisAlignment: MainAxisAlignment.spaceEvenly,

);

运行效果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

垂直方向(主轴上)属性:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. MainAxisAlignment.start这是默认值:垂直方向顶部对齐
  2. MainAxisAlignment.end:垂直方向底部对齐
  3. MainAxisAlignment.center:垂直方向居中对齐
  4. MainAxisAlignment.spaceBetween:垂直方向平分剩余空间
  5. MainAxisAlignment.spaceAround:放置控件后,剩余空间平分成n份,n是子widget的数量,然后把其中一份空间分成2份,放在第一个child的前面,和最后一个child的后面,也就是子widget的之前之后之间均匀分割空闲的一半空间
  6. MainAxisAlignment.spaceEvenly:放置控件后,把剩余空间平分n+1份,然后平分所有的空间,在子widget之前之后之间均匀的分割空闲的空间

下面列一下水平方向(交叉轴)的属性:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. CrossAxisAlignment.center这是默认值,水平居中
  2. CrossAxisAlignment.end:水平方向右侧对齐
  3. CrossAxisAlignment.start:水平方向左侧对齐
  4. CrossAxisAlignment.stretch:水平方向拉伸子child填充满布局
  5. CrossAxisAlignment.baseline:和textBaseline一起使用

6.Row

在水平方向上排列子widget的列表,示意图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

直接上代码:

class MyHomePage extends StatelessWidget {

body:new RowWidget(),

}
//Row
class RowWidget extends StatelessWidget{
@override
Widget build(BuildContext context){
return Row(
children: [
Container(
color:Colors.blue,
width: 50.0,
height:50.0,
),
Container(
color:Colors.black,
width:50.0,
height:50.0,
),
Container(
color:Colors.green,
width:50.0,
height:50.0,
),
],
);
}
}

效果图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

下面简单设置一些属性,和Column没多大差别:

return Row(
//把剩余空间平分n+1份,然后平分所有的空间
mainAxisAlignment: MainAxisAlignment.spaceEvenly,

);

效果图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

水平方向上(主轴上)属性:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. MainAxisAlignment.start这是默认值,水平方向顶部对齐
  2. MainAxisAlignment.center:水平方向居中对齐
  3. MainAxisAlignment.end:水平方向底部对齐
  4. MainAxisAlignment.spaceBetween:水平方向上平分剩余空间
  5. MainAxisAlignment.spaceAround:放置控件后,剩余空间平分成n份,n是子widget的数量,然后把其中一份空间分成2份,放在第一个child的前面,和最后一个child的后面,也就是子widget的之前之后之间均匀分割空闲的一半空间
  6. MainAxisAlignment.spaceEvenly:放置控件后,把剩余空间平分n+1份,然后平分所有的空间,在子widget之前之后之间均匀的分割空闲的空间 而交叉轴(垂直方向)的属性:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. CrossAxisAlignment.center这是默认,垂直居中
  2. CrossAxisAlignment.end:垂直方向右侧对齐
  3. CrossAxisAlignment.start:垂直方向左侧对齐
  4. CrossAxisAlignment.stretch:垂直方向拉伸子child填充满布局
  5. CrossAxisAlignment.baseline:和textBaseline一起使用

7.Expanded

Expanded组件可以使RowColumnFiex等子组件在其主轴上方向展开并填充可用的空间,这里注意:Expanded组件必须用在RowColumnFiex内,并且从Expanded到封装它的RowColumnFlex的路径必须只包括StatelessWidgets或者StatefulWidgets(不能是其他类型的组件,像RenderObjectWidget,它是渲染对象,不再改变尺寸,因此Expanded不能放进RenderObjectWidget),示意图如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

class MyHomePage extends StatelessWidget {

body:new RowWidget(),

}
class RowWidget extends StatelessWidget{
@override
Widget build(BuildContext context){
return Row(
children: [
new RaisedButton(
onPressed: (){

},
color:Colors.green,
child:new Text(‘绿色按钮1’)
),
new Expanded(
child:new RaisedButton(
onPressed: (){

},
color:Colors.yellow,
child:new Text(‘黄色按钮2’)
),
),
new RaisedButton(
onPressed:(){

},
color:Colors.red,
child:new Text(‘黑色按钮3’)),
],
);
}
}

运行效果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

class MyHomePage extends StatelessWidget {

body:new RowWidget(),

}
class RowWidget extends StatelessWidget{
@override
Widget build(BuildContext context){
return Row(
children: [
Expanded(
child:Container(
color:Colors.green,
padding:EdgeInsets.all(8),
height: 40.0,
),
flex:1,
),
Expanded(
child:Container(
color:Colors.yellow,
padding:EdgeInsets.all(8),
height: 40.0,
),
flex:2,
),
Expanded(
child:Container(
color:Colors.red,
padding:EdgeInsets.all(8),
height: 40.0,
),
),
],
);
}
}

上面代码设置了flex,将一行的宽度分成四等分,第一、三child占1/4的区域,第二个child占1/2区域。 效果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

8.ListView

我相信这个布局在平时开发会经常用到,这是可滚动的列表控件,ListView是最常用的滚动widget,它在滚动方向上一个接一个地显示它的孩子。在纵轴上,孩子没被要求填充ListView,并且内置ListTitle,示意图如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

class MyHomePage extends StatelessWidget {

body: new ListViewWidget(
new List.generate(1000,(i){
return ‘Item &i’;
}),
),

}
//ListView
class ListViewWidget extends StatelessWidget {
final List items;
ListViewWidget(this.items);
@override
Widget build(BuildContext context) {
return new ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return new ListTile(
title: new Text(‘This is $index’),
);
},
);
}
}

效果图如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

下面设置水平的ListView:

class MyHomePage extends StatelessWidget {

body: new ListViewWidget(
new List.generate(1000, (i) {
return ‘Item &i’;
}),
),

}
Widget build(BuildContext context) {
return new ListView.builder(
itemCount: items.length,
//设置水平方向
scrollDirection:Axis.horizontal,
//竖直时:确定每一个item的高度
//水平时:确定每一个item的宽度 得要设置 不然不显示
itemExtent: 110.0,
itemBuilder: (context, index) {
return new ListTile(
title: new Text(‘This is $index’),
);
},
);

效果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

9.GridView

GridView是一个网格布局的列组件。GridView继承至CustomScrollView,示意图如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

直接竖直上例子:

//GridView
class GridViewWidget extends StatelessWidget{

@override
Widget build(BuildContext context){
return new GridView.count(
crossAxisCount: 3, //3列
children: List.generate(40,
(i){
return Card(
child: Center(
child:Text(‘This is $i’),
),
);
})
);
}
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

下面上水平例子:

return new GridView.count(
//3行
crossAxisCount: 3,
//设置水平
scrollDirection: Axis.horizontal,
children: List.generate(40, (i) {
return Card(
child: Center(
child: Text(‘This is $i’),
),
);
}),
);

效果图如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

10.TabBar

移动开发中tab切换是一个很常用的功能,那么Flutter有没有提供这个Widget呢?答案是有的,Flutter通过Material库提供了很方便的API来使用tab切换。

10.1.创建TabController

TabBarViewTabBar都有一个TabController的参数,TabbarViewTabBar就是由TabController来控制同步,点击某个Tab后,要同步显示对应的TabBarView,创建TabController有两种方式:

  1. 使用系统自带的DefaultTabController,在Scaffold套一层DefaultTabController,这种方式TabBarView会自动查找这个tabController
  2. 自己定义一个TabController,实现SingleTickerProviderStateMixin

下面就列一下第一种方式:

@override
Widget build(BuildContext context) {
return new DefaultTabController();
}

10.2.构建Tab数据

final List myTabs = [
new Tab(text: ‘Android’),
new Tab(text: ‘IOS’),
new Tab(text: ‘Flutter’),
new Tab(text: ‘RN’),
new Tab(text: ‘Java’),
new Tab(text: ‘C’),
new Tab(text: ‘C++’),
new Tab(text: ‘Go’),
];

10.3.创建TabBar

TabBar在哪里都可以创建,在AppBar里有一个bottom参数可以接受TabBar,就放在AppBar下:

//设置appbar
appBar: new AppBar(
//底部
bottom: new TabBar(
indicatorColor: Colors.red, //指示器颜色 如果和标题栏颜色一样会白色
tabs: myTabs,//绑定数据
isScrollable: true, //是否可以滑动
),
),

10.4.绑定TabBar和TabBarView

class MyHomePage extends StatelessWidget {
final List myTabs = [
new Tab(text: ‘Android’),
new Tab(text: ‘IOS’),
new Tab(text: ‘Flutter’),
new Tab(text: ‘RN’),
new Tab(text: ‘Java’),
new Tab(text: ‘C’),
new Tab(text: ‘C++’),
new Tab(text: ‘Go’),
];
@override
Widget build(BuildContext context) {
return new DefaultTabController(
length: myTabs.length, //Tab长度
child: new Scaffold(
//设置appbar
appBar: new AppBar(
//底部
bottom: new TabBar(
indicatorColor: Colors.red, //指示器颜色 如果和标题栏颜色一样会白色
tabs: myTabs,//绑定数据
isScrollable: true, //是否可以滑动
),

),
body: new TabBarView(
//选中哪个Tabs,body就会显示
children: myTabs.map((Tab tab) {
return new Center(child: new Text(tab.text));
}).toList(),
),

);
}
}

效果如下图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

11.BottomNavigationBar

BottomNavigationBar即是底部导航栏控件,显示在页面底部的设计控件,用于在试图切换,底部导航栏包含多个标签、图标或者两者搭配的形式,简而言之提供了顶级视图之间的快速导航。

11.1.构建底部标签

//底部数据
final Map bottomMap ={
“首页”:Icon(Icons.home),
“朋友圈”:Icon(Icons.camera),
“信息”:Icon(Icons.message),
“其他”:Icon(Icons.devices_other),
};

11.2.创建导航栏

因为点击导航栏需要对应的字体显示,所以MyHomePage需要继承StatefulWidget,增加State

//用无状态控件显示

总结

找工作是个很辛苦的事情,而且一般周期都比较长,有时候既看个人技术,也看运气。第一次找工作,最后的结果虽然不尽如人意,不过收获远比offer大。接下来就是针对自己的不足,好好努力了。

最后为了节约大家的时间,我把我学习所用的资料和面试遇到的问题和答案都整理成了PDF文档

喜欢文章的话请关注、点赞、转发 谢谢!

new DefaultTabController(
length: myTabs.length, //Tab长度
child: new Scaffold(
//设置appbar
appBar: new AppBar(
//底部
bottom: new TabBar(
indicatorColor: Colors.red, //指示器颜色 如果和标题栏颜色一样会白色
tabs: myTabs,//绑定数据
isScrollable: true, //是否可以滑动
),

),
body: new TabBarView(
//选中哪个Tabs,body就会显示
children: myTabs.map((Tab tab) {
return new Center(child: new Text(tab.text));
}).toList(),
),

);
}
}

效果如下图:

[外链图片转存中…(img-wdmKzX7l-1720087595802)]

11.BottomNavigationBar

BottomNavigationBar即是底部导航栏控件,显示在页面底部的设计控件,用于在试图切换,底部导航栏包含多个标签、图标或者两者搭配的形式,简而言之提供了顶级视图之间的快速导航。

11.1.构建底部标签

//底部数据
final Map bottomMap ={
“首页”:Icon(Icons.home),
“朋友圈”:Icon(Icons.camera),
“信息”:Icon(Icons.message),
“其他”:Icon(Icons.devices_other),
};

11.2.创建导航栏

因为点击导航栏需要对应的字体显示,所以MyHomePage需要继承StatefulWidget,增加State

//用无状态控件显示

总结

找工作是个很辛苦的事情,而且一般周期都比较长,有时候既看个人技术,也看运气。第一次找工作,最后的结果虽然不尽如人意,不过收获远比offer大。接下来就是针对自己的不足,好好努力了。

最后为了节约大家的时间,我把我学习所用的资料和面试遇到的问题和答案都整理成了PDF文档

喜欢文章的话请关注、点赞、转发 谢谢!

[外链图片转存中…(img-vx44D1rr-1720087595803)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值