Flutter 基础知识入门
一、组件
1.1、Text文本
1,import ‘package:flutter/material.dart’;为flutter sdk提供的组件
2,main方法可以写成箭头函数的方式
3,快速生成一个类:stless
import 'package:flutter/material.dart';
// void main() => runApp(MyApp());
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('曾经沧海难为水,除却巫山不是云。曾经沧海难为水,除却巫山不是云。曾经沧海难为水,除却巫山不是云。曾经沧海难为水,除却巫山不是云。',
textAlign: TextAlign.center,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 30.0,
color: Color.fromARGB(255, 255, 0, 255),
decoration: TextDecoration.underline,
decorationStyle: TextDecorationStyle.solid
),),
),
)
);
}
}
1.2、Container容器
Container相关属性
1,alignment子控件对其方式:
alignment: Alignment.center,
centerLeft、center、bottomLeft、bottomCenter、bottomRight、centerRight、topCenter、topLeft、topRight(前面是纵向,后面是横向)
alignment: const FractionalOffset(0.5,0.5),
FractionalOffset取值为0-1,这里的0.5相当于Alignment.center
2,width宽度 浮点或整数类型
3,height高度 浮点或整数类型
4,color背景颜色
5,padding内边距:EdgeInsets.all所有方向边距,EdgeInsets.fromLTRB左上右下的边距
6,margin外边距,用法与padding一样
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Welcome to Flutter',
home:Scaffold(
appBar: AppBar(
title: Text('Container容器'),
),
body: Center(
child: Container(
child: new Text('Hello World', style: TextStyle(fontSize: 40),),
alignment: Alignment.topLeft,
width: 500,
height: 400,
color: Colors.blue,
// padding: const EdgeInsets.all(10),
padding: const EdgeInsets.fromLTRB(10, 100, 30, 40),
),
),
)
);
}
}
decoration修饰图片背景
1,渐变色:这里与color冲突,需要去掉color属性
2,border边框样式
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Welcome to Flutter',
home:Scaffold(
appBar: AppBar(
title: Text('decoration修饰'),
),
body: Center(
child: Container(
child: new Text('Hello World', style: TextStyle(fontSize: 40),),
alignment: Alignment.topLeft,
width: 500,
height: 400,
margin: const EdgeInsets.all(10),
padding: const EdgeInsets.fromLTRB(10, 100, 30, 40),
decoration: new BoxDecoration(
gradient: const LinearGradient(colors: [Colors.pink,Colors.amber,Colors.limeAccent]),
border: Border.all(width: 2,color: Colors.deepOrange)
),
),
),
)
);
}
}
1.3、Image图片
1.3.1、网络图片、本地资源
Image.network(网络图片)、Image.asset(本地资源)、Image.file(sd卡资源)、Image.memory
Container(
child: new Image.network(
'https://tva1.sinaimg.cn/large/008i3skNly1gtbnmq97aag30k814qb29.gif',
fit: BoxFit.scaleDown,
color: Colors.greenAccent,
colorBlendMode: BlendMode.modulate,
),
width: 300,
height: 500,
color: Colors.limeAccent,
)
需要在pubspec.yaml中配置图片
Image.asset(
'images/140133.20138321_o.png',
fit: BoxFit.scaleDown,
color: Colors.greenAccent,
colorBlendMode: BlendMode.modulate,
)
如果不配置,打包时会出现这种问题
2,fit属性:
contain:宽高适配其中一个,不变形,无裁切
fitWidth:宽度适配,不变形,高度裁切
fitHeight:高度适配,不变形,宽度裁切
fill:长宽适配,变形,无裁切
cover:长宽适配,不变形,裁切一个方向
3,混合模式
colorBlendMode配合color属性使用,起到颜色叠加等滤镜效果
1.3.2、repeat 属性
repeatX:横向重复
repeatY:纵向重复
repeat:横纵向重复
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Welcome to Flutter',
home: Scaffold(
appBar: AppBar(
title: Text('Repeat属性'),
),
body: Center(
child: Container(
child: new Image.network(
'https://tva1.sinaimg.cn/large/008i3skNly1gtbnmq97aag30k814qb29.gif',
fit: BoxFit.scaleDown,
repeat: ImageRepeat.repeatX,
),
width: 300,
height: 500,
color: Colors.limeAccent,
),
),
));
}
}
1.3.3、圆形头像
方式一:Container容器
利用Container容器的decoration剪切
final first = Container( width: 300, height: 300, decoration: BoxDecoration( color: Colors.yellow, //设置方框背景颜色// borderRadius: BorderRadius.all(// Radius.circular(150) //变成圆形,不过一般不这么实现圆形图片// ), borderRadius: BorderRadius.circular(150), //实现圆形图片的方式一: 有些麻烦 image: DecorationImage(image: NetworkImage('http://img5.mtime.cn/mg/2021/08/24/110937.63038065_285X160X4.jpg'), fit: BoxFit.cover //铺满全屏 ), ), );
方式二:ClipOval
使用系统提供的椭圆控件
final second = ClipOval( child: Image.network( 'http://img5.mtime.cn/mg/2021/08/24/110937.63038065_285X160X4.jpg', height: 100, width: 100, fit: BoxFit.cover, ), );
方式三:CircleAvatar(推荐)
使用系统提供的头像圆形控件
final third = CircleAvatar( backgroundImage: new NetworkImage('http://img5.mtime.cn/mg/2021/08/24/110937.63038065_285X160X4.jpg'), radius: 100, );
1.4、ListView列表
Flutter使用new和不用new有啥区别?
- dart 1.x的时候,
new 是不能省略的。 - dart 2.x的时候,
new 是可选关键词,可以省略
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Welcome to Flutter', home: Scaffold( appBar: AppBar( title: Text('ListView列表组件'), ), body: MyList() )); }}class MyList extends StatelessWidget{ @override Widget build(BuildContext context) { return ListView( children: [ ListTile( leading: new Icon(Icons.ac_unit), title: new Text('ac_unit'), ), ListTile( leading: new Icon(Icons.memory), title: new Text('memory'), ), Image.network('https://tva1.sinaimg.cn/large/008i3skNly1gtbnmryeetj30wq0jagmn.jpg'), Image.network('https://tva1.sinaimg.cn/large/008i3skNly1gtbnmryeetj30wq0jagmn.jpg'), ], ); }}
横向列表组件
scrollDirection: Axis.horizontal,
class MyList extends StatelessWidget{ @override Widget build(BuildContext context) { return ListView( scrollDirection: Axis.horizontal, children: [ Container( width: 180, color: Colors.lightBlue, ), Container( width: 180, color: Colors.amber, ), Container( width: 180, color: Colors.deepOrange, ), Container( width: 180, color: Colors.deepPurple, ), ], ); }}
构造函数参数传递,生成动态列表
1,dart里面列表使用list,使用List的generate方法动态赋值
List tempList=new List<String>.generate(100, (index) => "tempList $index");
2,MyApp({Key key})其中的key是默认必须要带的
3,@required注解表示字段必传
4,改动main函数里面的东西需要重新运行,否则会不生效或者报错
import 'package:flutter/material.dart';void main() => runApp(MyApp(items: new List<String>.generate(100, (index) => "item $index")));class MyApp extends StatelessWidget { final List<String> items; MyApp({Key key, @required this.items}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( title: 'Welcome to Flutter', home: Scaffold( appBar: AppBar( title: Text('ListView动态列表'), ), body: new ListView.builder( itemCount: items.length, itemBuilder: (context, index) { return new ListTile( title: new Text('${items[index]}'), ); }))); }}
1.5、GridView表格
常用GridView.count创建表格组件,属性解析:
1,crossAxisCount 每行数量
2,crossAxisSpacing 行内间距
3,mainAxisSpacing列内间距
4,childAspectRatio item的宽高比
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Welcome to Flutter', home: Scaffold( appBar: AppBar( title: Text('Grid表格布局'), ), body: GridView.count( crossAxisCount: 2, crossAxisSpacing: 2, mainAxisSpacing: 2, childAspectRatio: 1, // padding: const EdgeInsets.all(20), children: [ Image.network('http://img5.mtime.cn/mg/2021/08/24/141454.81651527_285X160X4.jpg',fit: BoxFit.cover,), Image.network('http://img5.mtime.cn/mg/2021/08/24/134535.67957178_285X160X4.jpg',fit: BoxFit.cover,), Image.network('http://img5.mtime.cn/mg/2021/08/24/112722.60735295_285X160X4.jpg',fit: BoxFit.cover,), Image.network('http://img5.mtime.cn/mg/2021/08/24/110937.63038065_285X160X4.jpg',fit: BoxFit.cover,), Image.network('http://img5.mtime.cn/mg/2021/08/24/101606.96675436_285X160X4.jpg',fit: BoxFit.cover,), Image.network('http://img5.mtime.cn/mg/2021/08/24/094036.69360356_285X160X4.jpg',fit: BoxFit.cover,), Image.network('http://img5.mtime.cn/mg/2021/08/24/093233.40634890_285X160X4.jpg',fit: BoxFit.cover,), Image.network('http://img5.mtime.cn/mg/2021/08/24/090626.28438629_285X160X4.jpg',fit: BoxFit.cover,), ], ))); }}
二、布局
2.1、Row水平布局
Row水平布局组件:
1,子组件嵌套Expanded为灵活布局,子组件相当于加了权重1
2,子组件没有嵌套Expanded为不灵活布局,由子控件实际宽高决定大小
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Welcome to Flutter',
home: Scaffold(
appBar: AppBar(
title: Text('水平布局'),
),
body: new Row(
children: [
RaisedButton(
onPressed: () {},
color: Colors.redAccent,
child: new Text('red button'),
),
Expanded(
child: RaisedButton(
onPressed: () {},
color: Colors.orangeAccent,
child: new Text('orange button'),
),
),
RaisedButton(
onPressed: () {},
color: Colors.redAccent,
child: new Text('red button'),
),
],
)));
}
}
2.2、Column垂直布局
Column垂直布局组件:
1,与Row相反,用法一样
2,crossAxisAlignment:指定副轴对其方式
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Welcome to Flutter',
home: Scaffold(
appBar: AppBar(
title: Text('垂直布局'),
),
body: new Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text('I am Chinese.'),
Expanded(child: Text('I am Chinese. I am Chinese.'),),
Text('I am Chinese. I am Chinese. I am Chinese.'),
],
)));
}
}
2.3、stack层叠布局
stack层叠布局,相当于css的position布局
1,这里alignment的FractionalOffset(0.5,0.5)等价于Alignment.center
2,CircleAvatar为圆形头像框
3,Positioned控件:用它包裹可以定位子组件位置
var stack = new Stack(
// alignment: Alignment.center,
alignment: const FractionalOffset(0.5, 0.5),
children: [
new CircleAvatar(
backgroundImage: new NetworkImage(
'http://img5.mtime.cn/mg/2021/08/24/110937.63038065_285X160X4.jpg'),
radius: 100,
),
new Container(
decoration: new BoxDecoration(color: Colors.orangeAccent),
padding: EdgeInsets.all(5),
child: Text('头像测试'),
),
new Positioned(
bottom: 0,
right: 0,
child: new Text(
'这个是第三层的Text组件',
style: TextStyle(color: Colors.orange),
))
],
);
2.4、Card卡片布局
卡片布局
1,卡片布局也就是对布局左右加上了一点阴影
2,Divider()为横向的分割线
var card=Card(
child: Column(
children: [
ListTile(
title: Text('地址1',style: TextStyle(fontWeight: FontWeight.w500),),
subtitle: Text('张三 13632432',style: TextStyle(fontWeight: FontWeight.w500),),
leading: Icon(Icons.account_box),
),
Divider(),
ListTile(
title: Text('地址1',style: TextStyle(fontWeight: FontWeight.w500),),
subtitle: Text('张三 13632432',style: TextStyle(fontWeight: FontWeight.w500),),
leading: Icon(Icons.account_box),
),
Divider(),
ListTile(
title: Text('地址1',style: TextStyle(fontWeight: FontWeight.w500),),
subtitle: Text('张三 13632432',style: TextStyle(fontWeight: FontWeight.w500),),
leading: Icon(Icons.account_box),
),
Divider(),
],
),
);
2.5、Drawer侧滑菜单
侧滑菜单用到了Drawer组件
脚手架组件Scaffold中添加drawer参数
import 'package:flutter/material.dart';
class SecondScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('drawer侧滑菜单'),
),
body: new Container(
child:new Center(
child: new RaisedButton(
onPressed: () {
//关闭侧滑栏
Navigator.pop(context);
},
child: new Text('返回'),
),
),
),
drawer: new Drawer(
child: new SecondScreen(),
),
);
}
}
三、路由导航
3.1、路由跳转
不带参数跳转
Navigator.push(context, MaterialPageRoute(builder: (context) => new SecondScreen()))
带参数跳转
final result = await Navigator.push(context, MaterialPageRoute(builder: (context) => ProductDetail(product: products[index])));
3.2、路由返回
不带参数返回
Navigator.pop(context);
带参数返回
Navigator.pop(context,"asdfasdfadsf");
demo示例:
import 'package:flutter/material.dart';
class Product {
final String title;
final String description;
Product(this.title, this.description);
}
void main() {
runApp(MaterialApp(
title: '路由导航',
home: ProductionList(
products: List.generate(
20, (index) => Product('商品$index', '这是一个商品详情,编号为$index'))),
));
}
class ProductionList extends StatelessWidget {
final List<Product> products;
const ProductionList({Key key, @required this.products}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('商品列表'),
),
body: ListView.builder(
itemCount: products.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(products[index].title),
onTap: () async {
String result = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
ProductDetail(product: products[index])));
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(result)));
},
);
}),
);
}
}
class ProductDetail extends StatelessWidget {
final Product product;
const ProductDetail({Key key, @required this.product}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('${product.title}'),
),
body: ListTile(
title: Text('${product.description}'),
onTap: () {
Navigator.pop(context,'asdfadsf');
},
),
);
}
}
四、安卓打包
4.1、androidstudio打包
使用androidstudio上的build打包,会生成apk、flutter-apk文件夹下的apk包65M
4.2、gradlew命令打包
使用gradlew命令打包,包大小也都是65M左右
./gradlew assembleDebug./gradlew assembleRelease
4.3、flutter命令打包
使用flutter命令打包会生成apk,flutter-apk文件下的包18M
flutter build apk
五、打印日志
print('Hello world!');
六、事件通信
6.1、callback
我们可以通过传递一个callback给组件或者下一个页面,然后回调数据。例如在A页面传递callback函数
Navigator.push( context, MaterialPageRoute( builder: (context) => ProductDetail( product: products[index], callback: (c, str) => { ScaffoldMessenger.of(c).showSnackBar( SnackBar(content: Text(str))) })));
在B页面调用callback函数
callback(context, '123213');
全部代码
import 'package:flutter/material.dart';class Product { final String title; final String description; Product(this.title, this.description);}void main() { runApp(MaterialApp( title: '路由导航', home: ProductionList( products: List.generate( 20, (index) => Product('商品$index', '这是一个商品详情,编号为$index'))), ));}class ProductionList extends StatelessWidget { final List<Product> products; const ProductionList({Key key, @required this.products}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('商品列表'), ), body: ListView.builder( itemCount: products.length, itemBuilder: (context, index) { return ListTile( title: Text(products[index].title), onTap: () async { String result = await Navigator.push( context, MaterialPageRoute( builder: (context) => ProductDetail( product: products[index], callback: (c, str) => { ScaffoldMessenger.of(c).showSnackBar( SnackBar(content: Text(str))) }))); ScaffoldMessenger.of(context) .showSnackBar(SnackBar(content: Text(result))); }, ); }), ); }}class ProductDetail extends StatelessWidget { final Product product; final Function callback; const ProductDetail( {Key key, @required this.product, @required this.callback}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('${product.title}'), ), body: ListTile( title: Text('${product.description}'), onTap: () { callback(context, '123213'); Navigator.pop(context, 'asdfadsf'); }, ), ); }}
|