在Flutter 中自定义组件其实就是一个类,这个类需要继承 StatelessWidget 或 StatefulWidget
StatelessWidget: 无状态组件,状态不可变的widget
StatefulWidget: 有状态组件,持有的状态可能在widget 生命周期改变
import 'package:flutter/material.dart';
void main(){
runApp(MyApp());
}
class MyApp extends StatelessWidget{
@override
Widget build(BuildContext context) {
// TODO: implement build
return Center(
child: Text(
"我是一个文本内容",
textDirection: TextDirection.ltr, // 文字方向
// 文字样式
style: TextStyle(
fontSize: 40.0,
fontWeight: FontWeight.bold,
// color: Colors.yellow
color: Color.fromRGBO(255, 222, 222, 0.5)
),
),
);
}
}
二、MaterialApp 和 Scaffold
1、MaterialApp
MaterialApp 是一个方便的Widget,它封装了应用程序实现 Material Design 所需要的一些Widget。一般作为顶层widget 使用。
常用的属性:
home(主页)
title(标题)
color(颜色)
theme(主题)
routes(路由)
…
Scaffold 是Material Design 布局结构的基本实现。此类提供了用于显示drawer、snackbar 和底部 sheet 的API。
Scaffold 有下面几个主要属性:
appBar - 显示在界面顶部的一个AppBar。
body - 当前界面所显示的主要内容Widget。
drawer - 抽屉菜单控件。
…
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
title: "我是一个标题",
home: Scaffold(
appBar: AppBar(
title: Text('IT 营'),
elevation: 30.0, //设置标题阴影不需要的话值设置成0.0
),
body: MyHome(),
),
theme: ThemeData(
// 设置主题颜色
primarySwatch: Colors.yellow),
);
}
}
class MyHome extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return Center(
child: Text(
"我是Dart 一个文本内容",
textDirection: TextDirection.ltr,
style: TextStyle(
fontSize: 40.0, fontWeight: FontWeight.bold, color: Colors.black38
// color: Color.fromRGBO(255, 222, 222, 0.5)
),
),
);
;
}
}
三、Container 组件、Text 组件
1、Text 组件
属性 | 功能 |
---|---|
textAlign | 文本对齐方式(center 居中,left 左对齐,right 右对齐,justfy 两端对齐) |
textDirection | 文本方向(ltr 从左至右,rtl 从右至左) |
overflow | 文字超出屏幕之后的处理方式(clip 裁剪,fade 渐隐,ellipsis 省略号) |
textScaleFactor | 字体显示倍率 |
maxLines | 文字显示最大行数 |
style | 字体的样式设置 |
TextStyle 常用参数:
属性 | 功能 |
---|---|
decoration | 文字装饰线(none 没有线,lineThrough 删除线,overline 上划线,underline 下划线) |
decorationColor | 文字装饰线颜色 |
decorationStyle | 文字装饰线风格([dashed,dotted] 虚线,double 两根线,solid 一根实线,wavy 波浪线) |
wordSpacing | 单词间隙(如果是负值,会让单词变得更紧凑) |
letterSpacing | 字母间隙(如果是负值,会让字母变得更紧凑) |
fontStyle | 文字样式(italic 斜体,normal 正常体) |
fontSize | 文字大小 |
color | 文字颜色 |
fontWeight | 字体粗细(bold 粗体,normal 正常体) |
属性 | 功能 |
---|---|
alignment | topCenter:顶部居中对齐 topLeft:顶部左对齐 topRight:顶部右对齐 center:水平垂直居中对齐 centerLeft:垂直居中水平居左对齐 centerRight:垂直居中水平居右对齐 bottomCenter 底部居中对齐 bottomLeft:底部居左对齐 bottomRight:底部居右对齐 |
margin | margin 属性是表示Container 与外部其他组件的距离。margin: EdgeInsets.all(20.0) |
padding | padding 就是Container 的内边距, 指Container 边缘与Child 之间的距离padding: EdgeInsets.all(10.0) |
transform | 让Container 进行一些旋转之类的transform: Matrix4.rotationZ(0.2) |
height | 容器高度 |
width | 容器宽度 |
child | 容器子元素 |
decoration | 组件样式 |
decoration: BoxDecoration(
color: Colors.blue,
// 边框样式
border: Border.all(
color: Colors.red,
width: 2.0,
),
// 边框圆角
borderRadius:
BorderRadius.all(
Radius.circular(8.0)
)
)
四、图片组件
1、Image 组件
图片组件是显示图像的组件,Image 组件有很多构造函数,这里例举两个:
Image.asset, 本地图片
Image.network 远程图片
Image 组件的常用属性:
属性名 | 类型 | 说明 |
---|---|---|
alignment | Alignment | 图片的对齐方式 |
color 和 colorBlendMode | 设置图片的背景颜色,通常和colorBlendMode 配合一起使用,这样可以使图片颜色和背景色混合。 | |
fit | BoxFit | fit 属性用来控制图片的拉伸和挤压,这都是根据父容器来的。 BoxFit.fill: 全图显示,图片会被拉伸,并充满父容器。 BoxFit.contain: 全图显示,显示原比例,可能会有空隙。 BoxFit.cover:显示可能拉伸,可能裁切,充满(图片要充满整个容器,还不变形)。 BoxFit.fitWidth:宽度充满(横向充满),显示可能拉伸,可能裁切。 BoxFit.fitHeight :高度充满(竖向充满),显示可能拉伸,可能裁切。 BoxFit.scaleDown:效果和contain 差不多,但是此属性不允许显示超过源图片大小,可小不可大。 |
repeat | ImageRepeat | ImageRepeat.repeat : 横向和纵向都进行重复,直到铺满整个画布。 ImageRepeat.repeatX: 横向重复,纵向不重复。 ImageRepeat.repeatY:纵向重复,横向不重复。 |
width | 宽度 一般结合ClipOval 才能看到效果 | |
height | 高度 一般结合ClipOval 才能看到效果 |
return Center(
child: Container(
child: Image.network(
"http://www.kaotop.com/file/tupian/20220518/20130828161137-1346445960.jpg",
alignment: Alignment.topLeft,
color: Colors.red,
colorBlendMode: BlendMode.colorDodge,
// repeat: ImageRepeat.repeatX,
fit: BoxFit.cover,
),
width: 300.0,
height: 400.0,
decoration: BoxDecoration(
color: Colors.yellow
),
),
);
2、引入本地图片
然后,打开 pubspec.yaml 声明一下添加的图片文件
代码中使用
child: Container(
child: Image.asset("images/a.jpeg",
fit:BoxFit.cover
),
width: 300.0,
height: 300.0,
decoration: BoxDecoration(
color: Colors.yellow
),
)
3、实现圆角图片
child: Container(
width: 300.0,
height: 300.0,
decoration: BoxDecoration(
color: Colors.yellow,
borderRadius: BorderRadius.circular(20),
image: DecorationImage(
image: NetworkImage("http://www.kaotop.com/file/tupian/20220518/20130828161137-1346445960.jpg"),
fit: BoxFit.cover
)
),
),
4、实现圆形图片
Center(
child: ClipOval(
child: Image.network(
"https://www.itying.com/images/201905/thumb_img/1101_thumb_G_1557845381862.jpg",
width: 150.0,
height: 150.0,
),
)),
五、列表组件
列表布局是我们项目开发中最常用的一种布局方式。Flutter 中我们可以通过 ListView 来定义列表项,支持垂直和水平方向展示。通过一个属性就可以控制列表的显示方向。
列表有以下分类:
1、垂直列表
2、垂直图文列表
3、水平列表
4、动态列表
5、矩阵式列表
属性 | 类型 | 说明 |
---|---|---|
scrollDirection | Axis | Axis.horizontal 水平列表 Axis.vertical 垂直列表 |
padding | EdgeInsetsGeometry | 内边距 |
resolve | bool | 组件反向排序 |
children | List | 列表元素 |
class HomeContent extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return Center(
child: ListView(
children: [
ListTile(
leading: Icon(Icons.phone),
title: Text(
"this is list",
style: TextStyle(fontSize: 28.0),
),
subtitle: Text('this is list this is list'),
),
ListTile(
title: Text("this is list"),
subtitle: Text('this is list this is list'),
trailing: Icon(Icons.phone),
),
ListTile(
title: Text("this is list"),
subtitle: Text('this is list this is list'),
)
],
),
);
}
}
水平列表
class HomeContent extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return Container(
height: 200.0,
margin: EdgeInsets.all(5),
child: ListView(
scrollDirection: Axis.horizontal, // 定义水平列表
children: [
Container(
width: 180.0,
color: Colors.lightBlue,
),
Container(
width: 180.0,
color: Colors.amber,
child: ListView(
children: [
Image.network(
'http://www.kaotop.com/file/tupian/20220518/childhood-in-a-picture.jpg'),
SizedBox(height: 16.0),
Text(
'这是一个文本信息',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 16.0),
)
],
),
),
Container(
width: 180.0,
color: Colors.deepOrange,
),
Container(
width: 180.0,
color: Colors.deepPurpleAccent,
),
],
));
}
}
动态列表(动态循环数据)
class HomeContent extends StatelessWidget {
List list = new List();
HomeContent({Key key}) : super(key: key) {
for (var i = 0; i < 20; i++) {
list.add("这是第${i}条数据");
}
print(list);
}
@override
Widget build(BuildContext context) {
return ListView.builder( // 定义动态列表
itemCount: this.list.length,
itemBuilder: (context, index) {
// print(context);
return ListTile(
leading: Icon(Icons.phone),
title: Text("${list[index]}"),
);
},
);
}
}
2、GridView 组件
GridView 创建网格列表有多种方式,主要介绍两种:
1、可以通过GridView.count 实现网格布局
2、通过GridView.builder 实现网格布局
常用属性:
名称 | 类型 | 说明 |
---|---|---|
scrollDirection | Axis | 滚动方向 |
padding | EdgeInsetsGeometry | 内边距 |
resolve | bool | 组件反向排序 |
crossAxisSpacing | double | 水平子Widget 之间间距 |
mainAxisSpacing | double | 垂直子Widget 之间间距 |
crossAxisCount | int | 一行的Widget 数量 |
childAspectRatio | double | 子Widget 宽高比例 |
children | [ ] | 子元素 |
gridDelegate | SliverGridDelegateWithFixedCrossAxisCount(常用) SliverGridDelegateWithMaxCrossAxisExtent | 控制布局,主要用在GridView.builder 里面 |
GridView.count 实现网格布局:
class LayoutContent extends StatelessWidget {
List _getListData() {
var tempList = listData.map((value) {
return Container(
child: Column(
children: [
Image.network(value["imageUrl"]),
SizedBox(height: 12),
Text(value["title"],
textAlign: TextAlign.center, style: TextStyle(fontSize: 20)),
],
),
decoration: BoxDecoration(
border: Border.all(
color: Color.fromRGBO(230, 230, 230, 0.9), width: 1.0)),
);
});
// ('124124','124214')
return tempList.toList();
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return GridView.count(
padding: EdgeInsets.all(20),
crossAxisCount: 2,
crossAxisSpacing: 20,
mainAxisSpacing: 20,
// childAspectRatio:0.7,
children: this._getListData(),
);
}
}
GridView.builder 实现网格布局:
class LayoutContent extends StatelessWidget {
Widget _getListData(context, index) {
return Container(
child: Column(
children: [
Image.network(listData[index]["imageUrl"]),
SizedBox(height: 12),
Text(listData[index]["title"],
textAlign: TextAlign.center, style: TextStyle(fontSize: 20)),
],
),
decoration: BoxDecoration(
border: Border.all(
color: Color.fromRGBO(230, 230, 230, 0.9), width: 1.0)),
);
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return GridView.builder(
itemCount: listData.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
//横轴元素个数
crossAxisCount: 2,
//纵轴间距
mainAxisSpacing: 20.0,
//横轴间距
crossAxisSpacing: 10.0,
//子组件宽高长度比例
childAspectRatio: 1.0),
itemBuilder: this._getListData,
);
}
}
六、StatefulWidget 有状态组件
在 Flutter 中自定义组件其实就是一个类,这个类需要继承 StatelessWidget / StatefulWidget。StatelessWidget 是无状态组件,状态不可变的 widgetStatefulWidget 是有状态组件,持有的状态可能在 widget 生命周期改变。通俗的讲:如果我们想改变页面中的数据的话这个时候就需要用到 StatefulWidget
class HomePage extends StatefulWidget {
//Flutter2.2.0之后需要注意把Key改为可空类型 {Key? key} 表示Key为可空类型
HomePage({Key? key}) : super(key: key);
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State {
List list=[];
@override
Widget build(BuildContext context) {
return ListView(
children: [
Column(
children: this.list.map((value){
return ListTile(
title: Text(value),
);
}).toList()
),
SizedBox(height: 20),
//Flutter2.x以后可以使用ElevatedButton替代RaisedButton也可以继续使用RaisedButton
ElevatedButton(
child: Text("按钮"),
onPressed: (){
// 通过 setState 方法改变状态
setState(() {
this.list.add('新增数据1');
this.list.add('新增数据2');
});
},
)
],
);
}
}
七、BottomNavigationBar 自定义底部导航条
BottomNavigationBar 是底部导航条,可以让我们定义底部 Tab 切换,BottomNavigationBar 是 Scaffold 组件的参数。
BottomNavigationBar 常见的属性:
属性 | 说明 |
---|---|
items | List 底部导航条按钮集合 |
iconSize | icon 大小 |
currentIndex | 默认选中第几个 |
onTap | 选中变化回调函数 |
fixedColor | 选中的颜色 |
type | BottomNavigationBarType.fixed BottomNavigationBarType.shifting |
Scaffold(
appBar: AppBar(
title: Text('Flutter Demo')
),
body: this._pagesList[this._curentIndex], // 通过改变值实现页面切换
bottomNavigationBar: BottomNavigationBar(
currentIndex: _curentIndex,
onTap: _changePage,
fixedColor: Colors.black,
type: BottomNavigationBarType.fixed,
items: [
BottomNavigationBarItem(
title:Text("首页"),
icon:Icon(Icons.home)
),
BottomNavigationBarItem(
title:Text("分类"),
icon:Icon(Icons.category)
),
BottomNavigationBarItem(
title:Text("设置"),
icon:Icon(Icons.settings)
),
],
),
)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)