第一部分 vscode终端操作快捷键 第二部分 hello world程序 第三部分 常用组件
附:
flutter中文文档https://flutterchina.club/docs/
书籍:flutter实战 https://book.flutterchina.club/
flutter自动代码生成器 https://ui.flutterdart.cn/
第一部分 vscode终端操作快捷键:
运行模拟器:flutter run
更新页面:R
显示网格:P
android/IOS模式切换:O
关闭终端:Q
热更新方法:用debug,按照VS的提示配置即可,配置完成后 如下
第二部分. 框架简介及hello world
一、总体架构
1、总体架构
其中engine部分 :
skia 图形UI框架
dart 虚拟机dartVM
text 渲染纹理
其中Framework部分:
foundation:功能接口
animation: 动画
painting:图像
gestures:触控
rendering:渲染
widgets:组件
meterial:googleUI风格
cupertino:IOSUI风格
2、GPU渲染
3.状态控制
4.Flutter理论基础知识
二、写一个hello world程序
主程序在main.dart里
import 'package:flutter/material.dart'; // 一个UI库 www.Material.IO
void main() => runApp(MyApp()); //main函数只有一句话:运行APP
class MyApp extends StatelessWidget{ //app继承于StatelessWidget组件对象
@override //重构build方法
Widget build(BuildContext context){ //组件的build的方法返回一个组件 参数是其上下文文件
return MaterialApp( //返回方法 返回组件
title: "welcome", //APP的title
home: Scaffold( //APP的主体,其类型是一个脚手架Scaffold
appBar: AppBar( //脚手架第一个组成是appbar
title: Text("welcome to big bear's flutter!!!"), //appbar的title
),
body: Center( //脚手架的第二个组成是body 给body一个center组件做内容
child: Text("hello 熊爸haha!"), //center里有一个子组件是 Text("???")
),
),
);
}
}
第三部分 常用静态组件
statelesswidget 无状态变化的组件
statefullwidget 有状态变化的组件
一、文字组件 Text("")
1.textAlign (文本对齐)
Text的子属性,可传入TextAlign类对象,比如:
TextAlign.center 居中
TextAlign.left 左对齐
TextAlign.right 右对齐
TextAlign.start 和文字开始对齐
TextAlign.end 和文字结束对齐
2. maxLines (最大显示行数)
Text的子属性,可传入数值
Text(
"hello 熊爸haha!锄禾日当午,汗滴禾下土。谁知盘中餐,粒粒皆辛苦。",
textAlign: TextAlign.end,
maxLines: 1,
)
3. overflow 溢出处理
Text的子属性,可传入TextOverflow类对象
\begin{array}[a] {|a|ca|} \hline 对象 & 对象名称\ \hline TextOverflow.clip & 溢出裁剪 \ \hline TextOverflow.ellipsis & 溢出显示... \ \hline TextOverflow.fade &最后一行上下渐变 \ \hline \end{array}\
4. style 文字样式
Text的子属性,可传入TextStyle类对象
TextStyle类对象:
import 'package:flutter/material.dart'; // 一个UI库 www.Material.IO
void main() => runApp(MyApp()); //main函数只有一句话:运行APP
class MyApp extends StatelessWidget{ //app继承于StatelessWidget组件对象
@override //重构build方法
Widget build(BuildContext context){ //组件的build的方法返回一个组件 参数是其上下文文件
return MaterialApp( //返回方法 返回组件
title: "welcome", //APP的title
home: Scaffold( //APP的主体,其类型是一个脚手架Scaffold
appBar: AppBar( //脚手架第一个组成是appbar
title: Text("welcome to big bear's flutter!!!"), //appbar的title
),
body: Center( //脚手架的第二个组成是body 给body一个center组件做内容
child: Text(
"hello 熊爸熊爸熊爸haha!锄禾日当午,汗滴禾下土。谁知盘中餐,粒粒皆辛苦。",
textAlign: TextAlign.left,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 25.0,
color:Color.fromARGB(255, 220, 125, 125),
decoration: TextDecoration.underline,
decorationStyle: TextDecorationStyle.wavy,
),
), //center里有一个子组件是 Text("???")
),
),
);
}
}
二、container组件 container() 容器
container() 相当于HTML里的div
import 'package:flutter/material.dart'; // 一个UI库 www.Material.IO
void main() => runApp(MyApp()); //main函数只有一句话:运行APP
class MyApp extends StatelessWidget{ //app继承于StatelessWidget组件对象
@override //重构build方法
Widget build(BuildContext context){ //组件的build的方法返回一个组件 参数是其上下文文件
return MaterialApp( //返回方法 返回组件
title: "welcome", //APP的title
home: Scaffold( //APP的主体,其类型是一个脚手架Scaffold
appBar: AppBar( //脚手架第一个组成是appbar
title: Text("welcome to big bear's flutter!!!"), //appbar的title
),
body: Center( //脚手架的第二个组成是body 给body一个center组件做内容
child: Container(
height: 400.0,
width: 300.0,
//color: Colors.pinkAccent,
margin: EdgeInsets.symmetric(horizontal: 010.0),
decoration: new BoxDecoration(
gradient: const LinearGradient(colors: [Colors.lightBlue,Colors.green],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
tileMode: TileMode.clamp,
),
border: Border.all(width: 2.0,color: Colors.blueGrey),
),
transform: Matrix4.rotationZ(0.1),
alignment: Alignment.topLeft,
padding: const EdgeInsets.fromLTRB(15.0, 30.0, 15.0, 0),
child: Text(
"锄禾日当午,汗滴禾下土,谁知盘中餐,粒粒皆辛苦!",
style: TextStyle(
fontSize: 24.0,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center,
),
), //center里有一个子组件是 Text("???")
),
),
);
}
}
三. image组件
import 'package:flutter/material.dart'; // 一个UI库 www.Material.IO
void main() => runApp(MyApp()); //main函数只有一句话:运行APP
class MyApp extends StatelessWidget{ //app继承于StatelessWidget组件对象
@override //重构build方法
Widget build(BuildContext context){ //组件的build的方法返回一个组件 参数是其上下文文件
return MaterialApp( //返回方法 返回组件
title: "welcome", //APP的title
home: Scaffold( //APP的主体,其类型是一个脚手架Scaffold
appBar: AppBar( //脚手架第一个组成是appbar
title: Text("welcome to big bear's flutter!!!"), //appbar的title
),
body: Center( //脚手架的第二个组成是body 给body一个center组件做内容
child: Container(
height: 600.0,
width: 400.0,
color: Colors.lightBlue,
child: Image.network(
"http://cms-bucket.ws.126.net/2019/1228/d84b26e0p00q37jrh002uc0009c005uc.png?imageView&thumbnail=200y140",
fit: BoxFit.scaleDown,
repeat: ImageRepeat.repeat,
color: Colors.pinkAccent,
colorBlendMode: BlendMode.darken,
)
),
),
),
);
}
}
四. Align组件 //对齐组件
五. Scaffold组件 //(脚手架)
脚手架是flutter页面框架结构中最重要的一环,他是页面的框架骨骼基础
六. AppBar组件 //APP导航条
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "TEST",
home: Scaffold(
appBar: AppBar(
leading: Icon(Icons.home),
title: Text("AppBar示例"),
centerTitle: true,
backgroundColor: Colors.deepPurpleAccent,
actions: [
IconButton(icon: Icon(Icons.print), tooltip: 'print', onPressed: () {}),
IconButton(icon: Icon(Icons.plus_one), tooltip: 'more', onPressed: () {}),
IconButton(icon: Icon(Icons.share), tooltip: 'share', onPressed: () {}),
PopupMenuButton(itemBuilder:
(context)=>>[
PopupMenuItem(
value: "share",
child: Text("分享到朋友圈"),
),
PopupMenuItem(
value: "quit",
child: Text("退出"),
)
]
)
],
),
body: Container(),
),
);
}
}
七. FloatingActionButton //悬浮按钮组件
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "TEST",
home: Scaffold(
appBar: AppBar(
title: Text("data"),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: FloatingActionButton(
tooltip: "小贴士,解释按键后会发生什么",
foregroundColor: Colors.black87,
backgroundColor: Colors.amberAccent,
hoverColor: Colors.deepPurple,
focusColor: Colors.deepPurpleAccent,
splashColor: Colors.greenAccent,
highlightElevation: 5,
hoverElevation: 15,
elevation: 5,
focusElevation: 10,
autofocus: true,
mini: true,
child: Icon(Icons.add),
onPressed: () {},
),
body: Container(),
),
);
}
}
八. BottomAppBar组件 //底部导航条
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "TEST",
home: Scaffold(
appBar: AppBar(title: Text("data"),),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: (){},
),
bottomNavigationBar: BottomAppBar(
notchMargin: 10.0,
color: Colors.amber,
elevation: 10,
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
IconButton(icon: Icon(Icons.search), onPressed: (){}),
IconButton(icon: Icon(Icons.menu), onPressed: (){}),
],
),
),
body: Container(),
),
);
}
}
九. ButtonBar //按钮条组件
十. NestedScrollView //可嵌套的滚动视图结构
十一. SliverAppBar //可扩展折叠的滚动工具栏
SliverAppBar 必须作为NestedScrollView 的子项才有用!!!!
十一. FlexibleSpaceBar组件 //可折叠空间组件
FlexibleSpaceBar必须作为SliverAppBar的子项才有用!!!!
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "TEST",
home: Scaffold(
appBar: AppBar(
title: Text("data"),
),
body: NestedScrollView(
headerSliverBuilder: (context, beScrolled) {
return [
(
centerTitle: true,
expandedHeight: 200,
floating: false,
pinned: true,
flexibleSpace: FlexibleSpaceBar(
background: Image.network(
"https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=793051438,2878586275&fm=11&gp=0.jpg",
fit: BoxFit.cover,
),
title: Text("可折叠组件"),
),
)
];
},
body: Center()),
),
);
}
}
十二. listView组件 列表布局
ListView的children是组件类型,所以可以随便添加任意组件
import 'package:flutter/material.dart'; // 一个UI库 www.Material.IO
void main() => runApp(MyApp()); //main函数只有一句话:运行APP
class MyApp extends StatelessWidget{ //app继承于StatelessWidget组件对象
@override //重构build方法
Widget build(BuildContext context){ //组件的build的方法返回一个组件 参数是其上下文文件
return MaterialApp( //返回方法 返回组件
title: "welcome", //APP的title
home: Scaffold( //APP的主体,其类型是一个脚手架Scaffold
appBar: AppBar( //脚手架第一个组成是appbar
title: Text("welcome to big bear's flutter!!!"), //appbar的title
),
body: Center(
child: Container(
height: 200,
color: Colors.pinkAccent,
child: MyList001(),
),
)
),
);
}
}
class MyList001 extends StatelessWidget{
@override
Widget build(BuildContext context) {
return ListView(
scrollDirection: Axis.horizontal,
children: [
Container(width: 180,color: Colors.lightBlue,),
Container(width: 180,color: Colors.pinkAccent,),
Container(width: 180,color: Colors.lightGreen,),
Container(width: 180,color: Colors.deepPurple,),
],
);
}
}
动态列表(参数传递内容的列表)
import 'package:flutter/material.dart';
void main() => runApp(MyApp(
items:List.generate(15,(i)=>"Item $i") //在myapp类里创建了一个属性叫items,它里面有一个列表
//里面的(i)=>"Item $i"是自动生成列表的项,就像python 列表中可以写lambda表达式一样
));
class MyApp extends StatelessWidget{
final List items; //类中建立属性items
MyApp({Key key,@required this.items}):super(key:key);
//Key key 重写构造函数默认传入的
//@required this.items 限定修饰 this.items必须传入
//:super(key:key) 调用祖先/父类无名无参构造函数,StatelessWidget 所以需要super往上找
@override
Widget build(BuildContext context){
return MaterialApp(
title: "welcome",
home: Scaffold(
body:ListView.builder( //用专门的builder方法构建动态列表
itemCount: items.length, //传入项目的数量
itemBuilder: (context,index){ //传入context上下文,同时传入index
//这里有点像JS,把下文中需要的参数实现一下
return ListTile( //listTile listview的项目瓦片
title: Text("${items[index]}"), //通过重构函数,我们将外部的信息传入了动态列表中
);
},
)
),
);
}
}
十三. 网格列表布局
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget{
@override
Widget build(BuildContext context){
return MaterialApp(
title: "welcome",
home: Scaffold(
appBar: AppBar(
title: Text("dasdasdas"),
),
body:MyGridList(),
),
);
}
}
class MyGridList extends StatelessWidget{
@override
Widget build(BuildContext context) {
return GridView.count(
padding: EdgeInsets.all(5.0),
crossAxisSpacing:5,
crossAxisCount: 3,
mainAxisSpacing: 5,
childAspectRatio: 0.7,
children: [
Image.network("https://image11.m1905.cn/uploadfile/2019/0829/thumb_1_150_203_20190829041446876955.jpg",fit: BoxFit.cover,),
Image.network("https://image11.m1905.cn/uploadfile/2019/1227/thumb_1_150_203_20191227090512473043.jpg",fit: BoxFit.cover,),
Image.network("https://image11.m1905.cn/uploadfile/2019/0123/thumb_1_150_203_20190123044311875088.jpg",fit: BoxFit.cover,),
Image.network("https://image11.m1905.cn/uploadfile/2018/0209/thumb_1_150_203_20180209015612332245.jpg",fit: BoxFit.cover,),
Image.network("https://image11.m1905.cn/uploadfile/2014/0812/thumb_1_150_203_20140812031906771224.jpg",fit: BoxFit.cover,),
Image.network("https://image11.m1905.cn/uploadfile/2009/1106/thumb_1_150_203_20091106112530726.jpg",fit: BoxFit.cover,),
Image.network("https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2577327061.webp",fit: BoxFit.cover,),
Image.network("https://img9.doubanio.com/view/photo/s_ratio_poster/public/p2578045524.jpg",fit: BoxFit.cover,),
Image.network("https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2556824333.jpg",fit: BoxFit.cover,),
Image.network("https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2574764569.jpg",fit: BoxFit.cover,),
Image.network("https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2568258113.jpg",fit: BoxFit.cover,),
Image.network("https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2541280047.jpg",fit: BoxFit.cover,),
],
);
}
}
按拓展性构建动态网格
import 'package:flutter/material.dart'; // 一个UI库 www.Material.IO
void main() => runApp(MaterialApp(
title: "组件",
home: MyApp(),
)); //main函数只有一句话:运行APP
class MyApp extends StatelessWidget {
List _buildList(int count) {
return List.generate(
count,
(int index) => Container(child: Image.asset('images/${index + 1}.jpg')),
);
}
//app继承于StatelessWidget组件对象
@override //重构build方法
Widget build(BuildContext context) {
//组件的build的方法返回一个组件 参数是其上下文文件
return Scaffold(
appBar: AppBar(
title: Text("data"),
),
body: GridView.extent(
maxCrossAxisExtent: 150.0,
padding: EdgeInsets.all(4.0),
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
children: _buildList(9),
),
);
}
}
十四. 按钮组件
十五. 水平布局
Row组件水平布局,搭配Expanded组件 可实现灵活的水平布局
对Row来说 主轴是水平方向
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget{
@override
Widget build(BuildContext context){
return MaterialApp(
title: "welcome",
home: Scaffold(
appBar: AppBar(
title: Text("熊爸"),
),
body:Row(
children: [
RaisedButton(
onPressed: (){print("点击了");},
color: Colors.amberAccent,
child: Text("amberAccent"),
),
Expanded(child: RaisedButton(
onPressed: (){print("点击了");},
color: Colors.lightBlue,
child: Text("lightBlue"),
),),
Expanded(child: RaisedButton(
onPressed: (){print("点击了");},
color: Colors.pinkAccent,
child: Text("pinkAccent"),
),)
],
),
),
);
}
}
十六. 垂直布局
对Row来说 主轴是垂直方向
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget{
@override
Widget build(BuildContext context){
return MaterialApp(
title: "welcome",
home: Scaffold(
appBar: AppBar(
title: Text("熊爸"),
),
body:Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text("熊爸"),
Expanded(child: Text("锄禾日当午,汗滴禾下土。谁知盘中餐,粒粒皆辛苦。"),),
Text("data"),
],
),
),
);
}
}
十七. Stack组件、Position组件(层叠布局 )
两层堆叠用Stack组件
多层堆叠用Position组件
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget{
@override
Widget build(BuildContext context){
return MaterialApp(
title: "welcome",
home: Scaffold(
appBar: AppBar(
title: Text("熊爸"),
),
body:Stack(
alignment: FractionalOffset(0.5,0.9),
children: [
CircleAvatar(child: Text("一部电影"),radius: 200,foregroundColor: Colors.purple,backgroundImage: NetworkImage("https://img9.doubanio.com/view/photo/s_ratio_poster/public/p2578045524.jpg"),),
Container(
width: 100,
height: 50,
color: Colors.lightBlue,
alignment: Alignment.center,
child: Text("本月最佳",style: TextStyle(color: Colors.white),),
)
],
),
),
);
}
}
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget{
@override
Widget build(BuildContext context){
return MaterialApp(
title: "welcome",
home: Scaffold(
appBar: AppBar(
title: Text("熊爸"),
),
body:Stack(
alignment: FractionalOffset(0.5,0.9),
children: [
CircleAvatar(child: Text("一部电影"),radius: 200,foregroundColor: Colors.purple,backgroundImage: NetworkImage("https://img9.doubanio.com/view/photo/s_ratio_poster/public/p2578045524.jpg"),),
Positioned(
top: 10.0,
left: 20.0,
child: Text("haha")
),
Positioned(
bottom: 10.0,
right: 20.0,
child: Text("OKOK")
),
],
),
),
);
}
}
十八. 圆盘组件
十九. 瓦片组件
二十. 卡片布局
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget{
@override
Widget build(BuildContext context){
return MaterialApp(
title: "welcome",
home: Scaffold(
appBar: AppBar(
title: Text("熊爸"),
),
body:Card(
borderOnForeground: true,
child: Column(
children: [
ListTile(
title: Text("anny baby",style: TextStyle(fontSize: 24,fontWeight: FontWeight.bold),),
subtitle: Text("a lovely girl"),
leading: CircleAvatar(backgroundImage: NetworkImage("https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2572847101.webp"),),
),
Divider(),
ListTile(
title: Text("anny baby",style: TextStyle(fontSize: 24,fontWeight: FontWeight.bold),),
subtitle: Text("a lovely girl"),
leading: Icon(Icons.satellite),
trailing: Icon(Icons.keyboard_arrow_right),
),
Divider(),
ListTile(
title: Text("anny baby",style: TextStyle(fontSize: 24,fontWeight: FontWeight.bold),),
subtitle: Text("a lovely girl"),
leading: Icon(Icons.satellite),
),
],
),
),
),
);
}
}
例2:
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "TEST",
home: Scaffold(
appBar: AppBar(title: Text("FlatButton")),
body: Column(
children: [
Card(
color: Colors.red[100],
margin: EdgeInsets.all(10),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
leading: Icon(Icons.shopping_basket),
title: Text(
"一加手机 OnePlus7pro",
style: TextStyle(fontSize: 25),
),
subtitle: Text("8+256G"),
contentPadding: EdgeInsets.all(10),
trailing: Text(
"¥3999",
style:
TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
),
ButtonBar(
children: [
FlatButton.icon(
textColor: Colors.deepPurple,
onPressed: () {},
icon: Icon(Icons.shopping_cart),
label: Text("购买")),
FlatButton.icon(
textColor: Colors.redAccent,
onPressed: () {},
icon: Icon(Icons.favorite),
label: Text("收藏")),
],
)
],
),
),
Card(
color: Colors.orange,
margin: EdgeInsets.all(10),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
leading: Icon(Icons.shopping_basket),
title: Text(
"小米手机 CC9",
style: TextStyle(fontSize: 25),
),
subtitle: Text("8+256G"),
contentPadding: EdgeInsets.all(10),
trailing: Text(
"¥1999",
style:
TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
),
ButtonBar(
children: [
FlatButton.icon(
textColor: Colors.deepPurple,
onPressed: () {},
icon: Icon(Icons.shopping_cart),
label: Text("购买")),
FlatButton.icon(
textColor: Colors.redAccent,
onPressed: () {},
icon: Icon(Icons.favorite),
label: Text("收藏")),
],
)
],
),
),
Card(
color: Colors.green,
margin: EdgeInsets.all(10),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
leading: Icon(Icons.shopping_basket),
title: Text(
"OPPO手机 FindX2",
style: TextStyle(fontSize: 25),
),
subtitle: Text("8+256G"),
contentPadding: EdgeInsets.all(10),
trailing: Text(
"¥3599",
style:
TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
),
ButtonBar(
children: [
FlatButton.icon(
textColor: Colors.deepPurple,
onPressed: () {},
icon: Icon(Icons.shopping_cart),
label: Text("购买")),
FlatButton.icon(
textColor: Colors.redAccent,
onPressed: () {},
icon: Icon(Icons.favorite),
label: Text("收藏")),
],
)
],
),
),
Card(
color: Colors.blueGrey,
margin: EdgeInsets.all(10),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
leading: Icon(Icons.shopping_basket),
title: Text(
"华为手机 Mate30",
style: TextStyle(fontSize: 25),
),
subtitle: Text("8+256G"),
contentPadding: EdgeInsets.all(10),
trailing: Text(
"¥3799",
style:
TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
),
ButtonBar(
children: [
FlatButton.icon(
textColor: Colors.deepPurple,
onPressed: () {},
icon: Icon(Icons.shopping_cart),
label: Text("购买")),
FlatButton.icon(
textColor: Colors.redAccent,
onPressed: () {},
icon: Icon(Icons.favorite),
label: Text("收藏")),
],
)
],
),
),
],
),
),
);
}
}
二十一. 分割线组件
Divider()
二十二. 导航
Navigator.push(context, route); //压栈,压入下一页
Navigator.pop(context); //弹栈,弹出一层
import 'package:flutter/material.dart'; // 一个UI库 www.Material.IO
void main() => runApp(MaterialApp(
title: "组件",
home: MyApp(),
)); //main函数只有一句话:运行APP
class FirstPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("第一页"),
),
body: Center(
child: RaisedButton(
child: Text("进入第二页"),
onPressed: () {
Navigator.push(
context, MaterialPageRoute(builder: (context) => SecondPage()));
},
),
),
);
}
}
class SecondPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("第二页"),
),
body: Column(
children: [
RaisedButton(
child: Text("返回"),
onPressed: () {
Navigator.pop(context);
},
),
RaisedButton(
child: Text("进入第三页"),
onPressed: (){
Navigator.push(context, MaterialPageRoute(builder: (context)=>ThirdPage()));
},
),
],
),
);
}
}
class ThirdPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("第三页"),
),
body: Center(
child: RaisedButton(
child: Text("返回"),
onPressed: () {
Navigator.pop(context);
},
),
),
);
}
}
class MyApp extends StatelessWidget {
//app继承于StatelessWidget组件对象
@override //重构build方法
Widget build(BuildContext context) {
//组件的build的方法返回一个组件 参数是其上下文文件
return FirstPage();
}
}
二十三. 带参数传递的导航
Navigator.push(context, MaterialPageRoute(builder: ( (context)=>SecPage(product: products[index],) )));
其实就是在构造函数中传递.
import 'package:flutter/material.dart';
class Product {
final String title;
final String description;
Product(this.title,this.description);
}
void main() {
runApp(MyApp(products: List.generate(50,(i)=>Product("商品$i","这是一个商品详情,编号为$i")),));
}
class MyApp extends StatelessWidget {
final List products;
const MyApp({Key key,@required this.products}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "test1",
home: ProductList(
products:List.generate(products.length, (i)=>products[i])),
);
}
}
class ProductList extends StatelessWidget {
final List products;
const ProductList({Key key,@required this.products}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("products"),),
body: ListView.builder(
itemCount: products.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(products[index].title),
onTap: (){
Navigator.push(context, MaterialPageRoute(
builder: (context)=>SecondPage(product: products[index],)
));
},
);
},
),
);
}
}
class SecondPage extends StatelessWidget {
final Product product;
const SecondPage({Key key,@required this.product}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("商品详情"),),
body: Text(product.description),
);
}
}
例二:页面跳转发送数据
import 'package:flutter/material.dart';
class Product {
final String title;
final String description;
Product(this.title, this.description);
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "页面间数据传递",
home: ProductList(
products: List.generate(20, (i) => "$i"),
),
);
}
}
class ProductList extends StatelessWidget {
final List products;
ProductList({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("这是商品:$index"),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: ((context) => SecPage(
product: Product("$index","这件$index 号商品是我们村的爆款哦!"),
))));
},
);
},
));
}
}
class SecPage extends StatelessWidget {
final Product product;
SecPage({Key key, @required this.product}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("$product 的商品详情")),
body: Center(
child: Column(
children: [
Text(
"商品显示在这里,商品编号:${product.title},\n商品描述:${product.description}.\n它$product 非常诱人!!\n您还在犹豫个啥???",
style: TextStyle(fontSize: 20),
),
RaisedButton(
child: Text("返回"),
onPressed: () {
Navigator.pop(context);
},
),
],
),
),
);
}
}
例三:页面跳转返回数据
二十四. 异步请求和等待
import 'package:flutter/material.dart'; // 一个UI库 www.Material.IO
void main(){
runApp(MaterialApp(
title: "页面跳转",
home:FirstPage(),
));
}
class FirstPage extends StatelessWidget {
const FirstPage({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("dataa"),),
body: Center(child:RouteBut()),
);
}
}
class RouteBut extends StatelessWidget {
const RouteBut({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return RaisedButton(
shape: StadiumBorder(),
onPressed: (){
_navi_in(context);
},
color: Colors.lightBlue,
child: Text("进入"),
);
}
_navi_in(BuildContext context) async{
final result=await Navigator.push(context,
MaterialPageRoute(
builder: (contex)=>SecondPage()
)
);
Scaffold.of(context).showSnackBar(SnackBar(content: Text(result),));
}
}
class SecondPage extends StatelessWidget {
const SecondPage({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
child: Scaffold(
appBar: AppBar(title: Text("设置返回数据"),),
body: Center(
child: Column(
children: [
RaisedButton(
child: Text("返回数据1"),
onPressed: (){
Navigator.pop(context,"数据1");
},
),
RaisedButton(
child: Text("返回数据2"),
onPressed: (){
Navigator.pop(context,"数据2");
},
),
],
),
),
),
);
}
}
二十五. 加载静态资源
在项目里创建一个资源文件夹,放入资源
找到pubspec.yaml文件并打开
注册资源:
注册后就可以引用了
import 'package:flutter/material.dart'; // 一个UI库 www.Material.IO
void main()=>runApp(MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "myAPP",
home: Scaffold(
appBar: AppBar(title: Text("daaata"),),
body:Container(
child: Image.asset("images/test1.jpg"),
)
),
);
}
}
二十六. Expanded //拓展组件
Expanded 组件可以让 Row、Column、Flex等子组件在其主轴方向上展开并填充可用空间。类似 Android 中的 widget 属性的用法
import 'package:flutter/material.dart'; // 一个UI库 www.Material.IO
void main() => runApp(MyApp()); //main函数只有一句话:运行APP
class MyApp extends StatelessWidget {
//app继承于StatelessWidget组件对象
@override //重构build方法
Widget build(BuildContext context) {
//组件的build的方法返回一个组件 参数是其上下文文件
final mytitle = "listview";
return MaterialApp(
//返回方法 返回组件
title: mytitle, //APP的title
home: Scaffold(
//APP的主体,其类型是一个脚手架Scaffold
appBar: AppBar(
//脚手架第一个组成是appbar
title: Text(mytitle), //appbar的title
),
body: Row(
children: [
Image.network(
"https://i0.hdslb.com/bfs/bangumi/b919ca54abfa2aaed952f197da67211118944923.jpg@144w_144h.webp",
width: 50,
),
Text("这是一个非常非常非常非常长的句子!!!长到这个ROW放不下了!!!"),
Icon(Icons.sentiment_satisfied),
],
)),
);
}
}
如果用上expanded组件则:
import 'package:flutter/material.dart'; // 一个UI库 www.Material.IO
void main() => runApp(MyApp()); //main函数只有一句话:运行APP
class MyApp extends StatelessWidget {
//app继承于StatelessWidget组件对象
@override //重构build方法
Widget build(BuildContext context) {
//组件的build的方法返回一个组件 参数是其上下文文件
final mytitle = "listview";
return MaterialApp(
//返回方法 返回组件
title: mytitle, //APP的title
home: Scaffold(
//APP的主体,其类型是一个脚手架Scaffold
appBar: AppBar(
//脚手架第一个组成是appbar
title: Text(mytitle), //appbar的title
),
body: Row(
children: [
Image.network(
"https://i0.hdslb.com/bfs/bangumi/b919ca54abfa2aaed952f197da67211118944923.jpg@144w_144h.webp",
width: 50,
),
Expanded(child: Text("这是一个非常非常非常非常长的句子!!!长到这个ROW放不下了!!!所以expanded组件就自动修改了一下文本样式,终于让ROW能显示了!!!"),),
Icon(Icons.sentiment_satisfied),
],
)),
);
}
}
二十七. sizebox盒模型
二十八. GestureDetector组件(手势监听)
import 'package:flutter/material.dart'; // 一个UI库 www.Material.IO
void main() => runApp(MaterialApp(
title: "组件",
home: MyApp(),
)); //main函数只有一句话:运行APP
class Mybutton extends StatelessWidget{
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: (){
final mysnak=SnackBar(content: Text("触发ontap,冒出提示框!!"));
Scaffold.of(context).showSnackBar(mysnak);
},
child: Container(
padding: EdgeInsets.all(12.0),
decoration: BoxDecoration(
color: Theme.of(context).buttonColor,
borderRadius: BorderRadius.circular(10.0),
),
child: Text("点一下"),
),
);
}
}
class MyApp extends StatelessWidget {
//app继承于StatelessWidget组件对象
@override //重构build方法
Widget build(BuildContext context) {
//组件的build的方法返回一个组件 参数是其上下文文件
return Scaffold(
appBar: AppBar(
title: Text("data"),
),
body: Center(child:Mybutton()),
);
}
}
二十九. Dismissible组件(滑动删除)
import 'package:flutter/material.dart'; // 一个UI库 www.Material.IO
void main() => runApp(MaterialApp(
title: "组件",
home: MyApp(),
)); //main函数只有一句话:运行APP
class MyApp extends StatelessWidget {
List items = List.generate(30, (i) => "item${i + 1}");
//app继承于StatelessWidget组件对象
@override //重构build方法
Widget build(BuildContext context) {
//组件的build的方法返回一个组件 参数是其上下文文件
return Scaffold(
appBar: AppBar(
title: Text("data"),
),
body: ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return Dismissible(
key: Key(items[index]),
onDismissed: (derction) {
items.removeAt(index);
Scaffold.of(context)
.showSnackBar(SnackBar(content: Text("data:$derction")));
},
child: ListTile(
title: Text("列表${items[index]}"),
),
);
},
),
);
}
}
三十. SnackBar
Scaffold.of(context).showSnackBar(SnackBar(content: Text("data:$derction")));
例2:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "TEST",
home: Scaffold(
appBar: AppBar(
title: Text("data"),
),
body: Center(
child: MyBut1(),
)));
}
}
class MyBut1 extends StatelessWidget {
final mySnak1 = SnackBar(
content: Row(
children: [
Icon(Icons.cake),
Text("感谢点击!!"),
],
),
backgroundColor: Colors.deepPurpleAccent,
//持续时间
duration: Duration(milliseconds: 1500),
//反馈动作
action: SnackBarAction(
label: "OK", textColor: Colors.greenAccent, onPressed: () {}),
);
@override
Widget build(BuildContext context) {
return RaisedButton(
child: Text("点击出现snackBar"),
onPressed: () {
Scaffold.of(context).showSnackBar(mySnak1);
},
);
}
}
三十一. 自定义字体
1.新建字体文件夹font 并放入字体文件
2.在pubspec.yaml文件中注册字体.
3.在程序中引用
import 'package:flutter/material.dart'; // 一个UI库 www.Material.IO
void main() => runApp(MaterialApp(
title: "组件",
home: MyApp(),
)); //main函数只有一句话:运行APP
class MyApp extends StatelessWidget {
List items = List.generate(30, (i) => "item${i + 1}");
//app继承于StatelessWidget组件对象
@override //重构build方法
Widget build(BuildContext context) {
//组件的build的方法返回一个组件 参数是其上下文文件
return Scaffold(
appBar: AppBar(
title: Text("data"),
),
body: Center(
child: Text(
"自定d义字体1data!!?!!@#%@#abasdasdaxkl123454563",
style: TextStyle(
fontSize: 25,
fontFamily: "xkzzt",
),
),
),
);
}
}
三十二. hero组件 //页面过度动画
注意:要过渡的两个页面应该设置同样的tag
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "test",
home: FirstPage(),
);
}
}
class FirstPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("第一页"),
),
body: GestureDetector(
child: Hero(
tag: "pic1",
child: Icon(Icons.picture_in_picture),),
onTap: () {
Navigator.push(
context, MaterialPageRoute(builder: (contex) => SecPage()));
},
),
);
}
}
class SecPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("第二页")),
body: Center(
child: GestureDetector(
child: Hero(
tag: "pic1",
child: Image.network(
"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1581017576843&di=e5876e0581a47faa82797803e4949794&imgtype=0&src=http%3A%2F%2F5b0988e595225.cdn.sohucs.com%2Fimages%2F20180910%2Ff96bbc903e094492a571515d0e417bf3.jpeg"),
),
onTap: () {
Navigator.pop(context);
},
),
),
);
}
}
三十三. ConstrainedBox //可伸缩盒子
伸缩盒子给子组件限定了一个最大和最小空间,子组件不得超过此空间.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "TEST",
home: Scaffold(
appBar: AppBar(title: Text("ConstrainedBox")),
body: Container(
height: 500,
child: ConstrainedBox(
constraints: BoxConstraints(
maxWidth:300,
minHeight: 200,
maxHeight: 500,
minWidth: 200,
),
child: Container(
width: 0,
height: 600,
color: Colors.redAccent,
),
),
),
));
}
}
三十四. DecoratedBox //带装饰的盒子
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "TEST",
home: Scaffold(
appBar: AppBar(title: Text("bottomNavigatorBar")),
body: Center(
child: Container(
width: 350,
height: 600,
child: DecoratedBox(
position: DecorationPosition.foreground,
//决定装饰器位置,会不会遮挡child里的组件
decoration: BoxDecoration(
color: Colors.teal,
image: DecorationImage(
image: NetworkImage(
'http://a1.att.hudong.com/05/00/01300000194285122188000535877.jpg'),
),
borderRadius: BorderRadius.circular(20),
backgroundBlendMode: BlendMode.colorBurn,
border: Border.all(
width: 6,
color: Colors.black38,
),
//shape: BoxShape.rectangle
),
child: Text(
"可爱可爱小猫咪",
style: TextStyle(fontSize: 25),
),
),
),
),
));
}
}
三十五. FittedBox //自适应填充盒模型
此盒子允许他的子组件有自适应性
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "TEST",
home: Scaffold(
appBar: AppBar(title: Text("FittedBox")),
body: Column(
children: [
Container(
width: 200,
height: 100,
color: Colors.greenAccent,
child: FittedBox(
fit: BoxFit.fill,
alignment: Alignment.center,
child: Text("使用fill模式自适应"),
),
)
],
),
),
);
}
}
三十六. OverflowBox //允许溢出的盒模型
此盒子允许他的子组件溢出
三十七. RotatedBox //允许旋转盒模型
此盒子允许他的子组件旋转,会顺时针旋转 quarterTurns × 90°
注意data的方向
三十八. SizedBox //限定大小的盒模型
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "TEST",
home: Scaffold(
appBar: AppBar(title: Text("RotatedBox")),
body: SizedBox(
width: 200,
height: 200,
child: Container(
width: 400,
height: 100,
color: Colors.blue,
)),
),
);
}
}
子组件设置了宽高,但不管用了
三十九. FlatButton //扁平按钮组件
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "TEST",
home: Scaffold(
appBar: AppBar(title: Text("FlatButton")),
body: Center(
child: Column(
children: [
FlatButton(
child: Text("data"),
colorBrightness: Brightness.dark,
onHighlightChanged: (n) {},
onPressed: () {},
onLongPress: () {},
color: Colors.pinkAccent,
),
FlatButton.icon(
color: Colors.amberAccent,
onPressed: () {},
icon: Icon(Icons.history),
label: Text("null")),
],
),
),
),
);
}
}
四十. IconButton //图标按钮组件
四十一 OutlineButton //外边线按钮组件
四十二. RawMaterialButton //原始按钮组件
第四部分 常用动态组件
一. tabbar组件 //选项卡
选项卡是一个动态组件,动态组件创建如下:
创建步骤:
1.在appbar中加一个tabbar
2.在body中加一个tabbarview
3.制作一个控制器_tabController来关联上面的二者
4.重写initState() dispose() 用来实现上述控制器
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(title: "TEST", home: Demo());
}
}
class Demo extends StatefulWidget {
@override
_DemoState createState() => _DemoState();//重写创建状态
}
class _DemoState extends State with SingleTickerProviderStateMixin {//必须加SingleTickerProviderStateMixin
ScrollController _scrollController; //类内声明了一个ScrollController组件,名叫_scrollController
TabController _tabController;//类内声明了一个TabController组件,名叫_tabController
@override
void initState() { //重写初始化状态函数
super.initState(); //必须先继承父类
_scrollController = ScrollController(); //初始化时创建一个ScrollController,赋值给_scrollController
_tabController = TabController(length: 6, vsync: this);//初始化时创建一个TabController,赋值给_tabController
//length必须与选项卡数量对应
}
@override
void dispose() { //重写释放函数
_scrollController.dispose(); //注销_scrollController组件
_tabController.dispose();//注销_tabController组件
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: Icon(Icons.home),
title: Text("tabBar"),
bottom: TabBar( //在APPBAR的底部加一个tabbar
controller: _tabController, //控制器为_tabController
tabs: [ //里面的Tab
Tab(text: '语文',icon: Icon(Icons.font_download),),
Tab(text: '数学',icon: Icon(Icons.format_list_numbered),),
Tab(text: '英语',icon: Icon(Icons.nature),),
Tab(text: '历史',icon: Icon(Icons.history),),
Tab(text: '地理',icon: Icon(Icons.map),),
Tab(text: '生物',icon: Icon(Icons.book),),
],
),
),
body: TabBarView( //在body里加一个TabBarView
controller: _tabController, //也用_tabController作为控制器,这样就能和tabbar对应起来
children: [ //子元素个数应该和tabbar对应起来
Text("语文"),
Text("数学"),
Text("英语"),
Text("历史"),
Text("地理"),
Text("生物"),
],
),
);
}
}
二. 底部导航栏
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "TEST",
home: Scaffold(
appBar: AppBar(title: Text("bottomNavigatorBar")),
body: Container(
height: 500,
),
bottomNavigationBar: Demo(),
));
}
}
class Demo extends StatefulWidget {
@override
_DemoState createState() => _DemoState();
}
class _DemoState extends State {
int _currentIndex = 1;
void _onItemTapped(int index) {
setState(() {
_currentIndex = index;
});
}
@override
Widget build(BuildContext context) {
return BottomNavigationBar(
onTap: _onItemTapped,
type: BottomNavigationBarType.fixed,
currentIndex: _currentIndex,
items: [
BottomNavigationBarItem(
title: Text("book"),
icon: Icon(Icons.book),
),
BottomNavigationBarItem(
title: Text("shop"),
icon: Icon(Icons.shop),
),
BottomNavigationBarItem(
title: Text("music"),
icon: Icon(Icons.queue_music),
),
],
);
}
}
三. 下拉按钮组件
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "TEST",
home: Scaffold(
appBar: AppBar(title: Text("DropdownButDemo")),
body: Center(
child: DropdownButDemo(),
),
),
);
}
}
class DropdownButDemo extends StatefulWidget {
@override
_DropdownButDemoState createState() => _DropdownButDemoState();
}
class _DropdownButDemoState extends State with SingleTickerProviderStateMixin {
int _cureentValue=1;
List dropItemsList(){
final List mitems=List();
final DropdownMenuItem item1 =DropdownMenuItem(child: Text("book"),value: 1);
final DropdownMenuItem item2 =DropdownMenuItem(child: Text("shop"),value: 2);
final DropdownMenuItem item3 =DropdownMenuItem(child: Text("cake"),value: 3);
final DropdownMenuItem item4 =DropdownMenuItem(child: Text("bank"),value: 4);
mitems.add(item1);
mitems.add(item2);
mitems.add(item3);
mitems.add(item4);
return mitems;
}
@override
Widget build(BuildContext context) {
return DropdownButton(
value: _cureentValue,
items: dropItemsList(),//下拉列表
hint: Text("请下拉"),//提示文本
iconSize: 48,//图标大小
elevation: 10,//阴影
isExpanded: true,//继承父容器的大小
focusColor: Colors.redAccent, //获得焦点的颜色
iconEnabledColor: Colors.amber,//按钮可用时的颜色
iconDisabledColor: Colors.grey,//按钮不可用时的颜色
icon: Icon(Icons.keyboard_arrow_down),
style: TextStyle(fontSize: 30,color: Colors.black54,),//字体样式
isDense:true,
itemHeight:80,
autofocus: true,
onChanged: (T){
setState((){
_cureentValue=T;
});
},
);
}
}
第五部分 打包与发布
Android打包(VScode)
一 配置APP图标
图标目录: /android/app/src/main/res/
进入之后你会看到很多mipmap-为前缀命名的文件夹,后边的是像素密度,可以看出图标的分辨率。
mdpi (中) ~160dpi
hdpi (高) ~240dip
xhdpi (超高) ~320dip
xxhdpi (超超高) ~480dip
xxxhdpi (超超超高) ~640dip
将对应像素密度的图片放入对应的文件夹中,图片记得用png格式,记得名字要统一,才能一次性进行配置。
二 配置AndroidManifest.xml
这个文件主要用来配置APP的名称、图标和系统权限,所在的目录在:/android/app/src/main/AndroidManifest.xml
android:label="flutter_app" //配置APP的名称,支持中文
android:icon="@mipmap/ic_launcher" //APP图标的文件名称
三 生成keystore
keytool -genkey -v -keystore e:/key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias key
在安卓根目录建立key属性文件,并配置
storePassword= //输入上一步创建KEY时输入的 密钥库 密码
keyPassword= //输入上一步创建KEY时输入的 密钥 密码
keyAlias=key
storeFile= //key.jks的存放路径
四 配置android\app\build.gradle
在android{}上面添加如下代码:
def keystorePropertiesFile = rootProject.file("key.properties")
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
把下面内容替换
替换成:
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
五 生成APK
运行命令:
flutter build apk