注:本文所有内容学习引用自技术胖大佬
基础代码
import 'package:flutter/material.dart';
void main () => runApp(MyApp());
class MyApp extends StatelessWidget{
@override
Widget build(BuildContext context ){
return MaterialApp(
title:'Text widget',
home:Scaffold(
body:Center(
child:Text(
'Hello ljhHello ljhHello ljhHello ljhHello ljhHelloHello ljhHello ljhHello ljh ljhHello ljh',
textAlign: TextAlign.right,
//最大行数
maxLines: 1,
//超出屏幕部分显示方式
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 25.0,
color:Color.fromARGB(255, 255 , 150, 100),
decoration: TextDecoration.underline,
decorationStyle: TextDecorationStyle.solid,
),
)
),
),
);
}
}
import 'package:flutter/material.dart';
void main () => runApp(MyApp());
class MyApp extends StatelessWidget{
@override
Widget build(BuildContext context ){
return MaterialApp(
title:'Text widget',
home:Scaffold(
body:Center(
child:Container(
child:new Text('Hello JSPang',style: TextStyle(fontSize: 40.0),),
alignment: Alignment.topLeft,
width:500.0,
height:400.0,
padding:const EdgeInsets.fromLTRB(10.0,30.0,0.0,0.0),
margin: const EdgeInsets.all(10.0),
decoration:new BoxDecoration(
gradient:const LinearGradient(
colors:[Colors.lightBlue,Colors.greenAccent,Colors.purple]
),
border:Border.all(width:2.0,color:Colors.red)
),
),
),
),
);
}
}
图片
import 'package:flutter/material.dart';
void main () => runApp(MyApp());
class MyApp extends StatelessWidget{
@override
Widget build(BuildContext context ){
return MaterialApp(
title:'Text widget',
home:Scaffold(
body:Center(
child:Container(
child:new Image.network(
"http://img.improve-yourmemory.com/pic/33afa10cf2b273b4e7beb194c0a9bcc1-0.jpg",
fit: BoxFit.fill,
color: Colors.red,
colorBlendMode: BlendMode.darken,
repeat: ImageRepeat.repeat,
),
width:300.0,
height:200.0,
color: Colors.lightBlue,
),
),
),
);
}
}
列表
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'JSPang Flutter Demo',
home: Scaffold(
appBar: new AppBar(title: new Text('这是tarbar')),
body: new ListView(children: <Widget>[
new ListTile(
leading: new Icon(Icons.access_time),
title: new Text('access_time')),
new ListTile(
leading: new Icon(Icons.access_time),
title: new Text('access_time')),
new ListTile(
leading: new Icon(Icons.access_time),
title: new Text('access_time')),
new Image.network(
"http://img.improve-yourmemory.com/pic/33afa10cf2b273b4e7beb194c0a9bcc1-0.jpg",
fit: BoxFit.fill,
color: Colors.red,
colorBlendMode: BlendMode.darken,
repeat: ImageRepeat.repeat,
)
]),
),
);
}
}
所有布局 widgets 都具有以下任一项:
一个 child 属性,如果它们只包含一个子项 —— 例如 Center 和 Container
一个 children 属性,如果它们包含多个子项 —— 例如 Row、Column、ListView 和 Stack
组件
import 'package:flutter/material.dart';
void main () => runApp(MyApp());
class MyApp extends StatelessWidget{
@override
Widget build(BuildContext context ){
return MaterialApp(
title:'ListView widget',
home:Scaffold(
body:Center(
child:Container(
height:200.0,
child:MyFuck()
),
),
),
);
}
}
class MyFuck extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'JSPang Flutter Demo',
home: Scaffold(
appBar: new AppBar(title: new Text('这是tarbar')),
body: new ListView(children: <Widget>[
new ListTile(
leading: new Icon(Icons.access_time),
title: new Text('access_time')),
new ListTile(
leading: new Icon(Icons.access_time),
title: new Text('access_time')),
new ListTile(
leading: new Icon(Icons.access_time),
title: new Text('access_time')),
new Image.network(
"http://img.improve-yourmemory.com/pic/33afa10cf2b273b4e7beb194c0a9bcc1-0.jpg",
fit: BoxFit.fill,
color: Colors.red,
colorBlendMode: BlendMode.darken,
repeat: ImageRepeat.repeat,
)
]),
),
);
}
}
动态获取列表
import 'package:flutter/material.dart';
void main () => runApp(MyApp(
items: new List<String>.generate(1000, (i)=> "Item $i")
));
class MyApp extends StatelessWidget{
final List<String> items;
//这一行不太懂,用了dart语法
//构造函数 key 传递个参数 调用父类
MyApp({Key key, @required this.items}):super(key:key);
@override
Widget build(BuildContext context ){
return MaterialApp(
title:'ListView widget',
home:Scaffold(
body:new ListView.builder(
itemCount:items.length,
itemBuilder:(context,index){
return new ListTile(
title:new Text('${items[index]}'),
);
}
)
),
);
}
}
GridView网络列表组件
import 'package:flutter/material.dart';
void main () => runApp(MyApp());
class MyApp extends StatelessWidget{
@override
Widget build(BuildContext context ){
return MaterialApp(
title:'ListView widget',
home:Scaffold(
body:GridView.count(
padding:const EdgeInsets.all(20.0),
//crossAxisSpacing:网格间的空当,相当于每个网格之间的间距
crossAxisSpacing: 10.0,
//crossAxisCount:网格的列数,相当于一行放置的网格数量
crossAxisCount: 3,
children: <Widget>[
const Text('I am Jspang'),
const Text('I love Web'),
const Text('jspang.com'),
const Text('我喜欢玩游戏'),
const Text('我喜欢看书'),
const Text('我喜欢吃火锅')
],
)
),
);
}
}
水平布局Row
Flutter中的row控件就是水平控件,它可以让Row里边的子元素进行水平排列
不灵活布局
import 'package:flutter/material.dart';
void main () => runApp(MyApp());
class MyApp extends StatelessWidget{
@override
Widget build(BuildContext context ){
return MaterialApp(
title:'ListView widget',
home:Scaffold(
appBar:new AppBar(
title:new Text('水平方向布局'),
),
body:new Row(
children: <Widget>[
new RaisedButton(
onPressed: (){
},
color:Colors.redAccent,
child:new Text('红色按钮')
),
new RaisedButton(
onPressed: (){
},
color:Colors.orangeAccent,
child: new Text('黄色按钮'),
),
new RaisedButton(
onPressed: (){
},
color:Colors.pinkAccent,
child:new Text('粉色按钮')
)
],
)
),
);
}
}
灵活布局
import 'package:flutter/material.dart';
void main () => runApp(MyApp());
class MyApp extends StatelessWidget{
@override
Widget build(BuildContext context ){
return MaterialApp(
title:'ListView widget',
home:Scaffold(
appBar:new AppBar(
title:new Text('水平方向布局'),
),
body:new Row(
children: <Widget>[
Expanded(child:new RaisedButton(
onPressed: (){
},
color:Colors.redAccent,
child:new Text('红色按钮')
)),
Expanded(child:new RaisedButton(
onPressed: (){
},
color:Colors.orangeAccent,
child: new Text('黄色按钮'),
)
),
Expanded(child:new RaisedButton(
onPressed: (){
},
color:Colors.pinkAccent,
child:new Text('粉色按钮')
)
)
],
)
),
);
}
}
混用
import 'package:flutter/material.dart';
void main () => runApp(MyApp());
class MyApp extends StatelessWidget{
@override
Widget build(BuildContext context ){
return MaterialApp(
title:'ListView widget',
home:Scaffold(
appBar:new AppBar(
title:new Text('水平方向布局'),
),
body:new Row(
children: <Widget>[
Expanded(child:new RaisedButton(
onPressed: (){
},
color:Colors.redAccent,
child:new Text('红色按钮')
)),
new RaisedButton(
onPressed: (){
},
color:Colors.orangeAccent,
child: new Text('黄色按钮'),
),
Expanded(child:new RaisedButton(
onPressed: (){
},
color:Colors.pinkAccent,
child:new Text('粉色按钮')
)
)
],
)
),
);
}
}
垂直排列column
把row改成column
crossAxisAlignment: CrossAxisAlignment.start, //居左对齐
crossAxisAlignment: CrossAxisAlignment.end, //居右对齐
crossAxisAlignment: CrossAxisAlignment.center, //居中对齐
主轴和副轴
main轴:如果你用column组件,那垂直就是主轴,如果你用Row组件,那水平就是主轴。
cross轴:cross轴我们称为幅轴,是和主轴垂直的方向。比如Row组件,那垂直就是幅轴,Column组件的幅轴就是水平方向的。
主轴居中
import 'package:flutter/material.dart';
void main () => runApp(MyApp());
class MyApp extends StatelessWidget{
@override
Widget build(BuildContext context ){
return MaterialApp(
title:'ListView widget',
home:Scaffold(
appBar:new AppBar(
title:new Text('垂直方向布局'),
),
body:Column(
//主轴设置居中
mainAxisAlignment: MainAxisAlignment.center,
//副轴设置左开始
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('I am JSPang'),
Text('my website is jspang.com'),
Text('I love coding')
],
)
),
);
}
}
垂直水平居中
加入center组件
import 'package:flutter/material.dart';
void main () => runApp(MyApp());
class MyApp extends StatelessWidget{
@override
Widget build(BuildContext context ){
return MaterialApp(
title:'ListView widget',
home:Scaffold(
appBar:new AppBar(
title:new Text('垂直方向布局'),
),
body:Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Center(child:Text('I am JSPang')),
Center(child:Text('my website is jspang.com')),
Center(child:Text('I love coding'))
],
)
),
);
}
}
Stack层叠布局
import 'package:flutter/material.dart';
void main () => runApp(MyApp());
class MyApp extends StatelessWidget{
@override
Widget build(BuildContext context ){
var stack = new Stack(
//alignment属性是控制层叠的位置的,建议在两个内容进行层叠时使用。它有两个值X轴距离和Y轴距离,值是从0到1的,都是从上层容器的左上角开始算起的。
alignment: const FractionalOffset(0.5, 0.5),
children: <Widget>[
new CircleAvatar(
backgroundImage: new NetworkImage('https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=2557853891,1393276761&fm=224&gp=0.jpg'),
radius: 100.0,
),
new Container(
decoration: new BoxDecoration(
color: Colors.lightBlue,
),
padding: EdgeInsets.all(5.0),
child: new Text('我是胖头鱼'),
)
],
);
return MaterialApp(
title:'ListView widget',
home:Scaffold(
appBar:new AppBar(
title:new Text('垂直方向布局'),
),
body:Center(child:stack),
),
);
}
}
层叠定位组件
超过两个组件的层叠该如何进行定位那?这就是我们加今天要学的主角Positioned组件了。这个组件也叫做层叠定位组件
Positioned组件的属性:
bottom: 距离层叠组件下边的距离
left:距离层叠组件左边的距离
top:距离层叠组件上边的距离
right:距离层叠组件右边的距离
width: 层叠定位组件的宽度
height: 层叠定位组件的高度
import 'package:flutter/material.dart';
void main () => runApp(MyApp());
class MyApp extends StatelessWidget{
@override
Widget build(BuildContext context ){
var stack = new Stack(
children: <Widget>[
new CircleAvatar(
backgroundImage: new NetworkImage('https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=2557853891,1393276761&fm=224&gp=0.jpg'),
radius: 100.0,
),
new Positioned(
top:10.0,
left:10.0,
child: new Text('pangtouyu'),
),
new Positioned(
bottom:10.0,
right:10.0,
child: new Text('胖头鱼'),
)
],
);
return MaterialApp(
title:'ListView widget',
home:Scaffold(
appBar:new AppBar(
title:new Text('层叠布局'),
),
body:Center(child:stack),
),
);
}
}
卡片组件布局
import 'package:flutter/material.dart';
void main () => runApp(MyApp());
class MyApp extends StatelessWidget{
@override
Widget build(BuildContext context ){
//卡片组件
var card = new Card(
//垂直布局
child: Column(
children: <Widget>[
ListTile(
title:new Text('吉林省吉林市昌邑区',style: TextStyle(fontWeight: FontWeight.w500),),
subtitle: new Text('技术胖:1513938888'),
leading: new Icon(Icons.account_box,color: Colors.lightBlue,),
),
new Divider(),
ListTile(
title:new Text('北京市海淀区中国科技大学',style: TextStyle(fontWeight: FontWeight.w500),),
subtitle: new Text('胜宏宇:1513938888'),
leading: new Icon(Icons.account_box,color: Colors.lightBlue,),
),
new Divider(),
ListTile(
title:new Text('河南省濮阳市百姓办公楼',style: TextStyle(fontWeight: FontWeight.w500),),
subtitle: new Text('JSPang:1513938888'),
leading: new Icon(Icons.account_box,color: Colors.lightBlue,),
),
new Divider(),
],
),
);
return MaterialApp(
title:'ListView widget',
home:Scaffold(
appBar:new AppBar(
title:new Text('卡片布局'),
),
body:Center(child:card),
),
);
}
}
代码中使用了一个垂直布局组件Column组件,然后利用了ListTile实现内部列表,这里需要说明的是ListTile不光可以使用在ListView组件中,然后容器组件其实都可以使用
页面导航和返回
它有两个最基本的属性:
child:可以放入容器,图标,文字。让你构建多彩的按钮。
onPressed:点击事件的相应,一般会调用Navigator组件。
我们在作页面导航时,大量的使用了RaisedButton组件,这个组件的使用在实际工作中用的也比较多。
Navigator.push 和 Navigator.pop
Navigator.push:是跳转到下一个页面,它要接受两个参数一个是上下文context,另一个是要跳转的函数。
Navigator.pop:是返回到上一个页面,使用时传递一个context(上下文)参数,使用时要注意的是,你必须是有上级页面的,也就是说上级页面使用了Navigator.push。
import 'package:flutter/material.dart';
void main(){
runApp(MaterialApp(
title:'导航演示1',
home:new FirstScreen()
));
}
class FirstScreen extends StatelessWidget{
@override
Widget build(BuildContext context){
return new Scaffold(
appBar: AppBar(title:Text('导航页面')),
body:Center(
child:RaisedButton(
child:Text('查看商品详情页面'),
onPressed: (){
Navigator.push(context,new MaterialPageRoute(
builder:(context) =>new SecondScreen())
);
},
)
)
);
}
}
class SecondScreen extends StatelessWidget{
@override
Widget build(BuildContext context){
return Scaffold(
appBar:AppBar(title:Text('技术胖商品详情页')),
body:Center(child:RaisedButton(
child:RaisedButton(
child:Text('返回'),
onPressed: (){
Navigator.pop(context);
},
)
))
);
}
}
导航参数的传递和接收
import 'package:flutter/material.dart';
//传递的数据结构,也可以理解为对商品数据的抽象
class Product{
final String title; //商品标题
final String description; //商品描述
Product(this.title,this.description);
}
void main(){
runApp(MaterialApp(
title:'数据传递案例',
home:ProductList(
products:List.generate(
20,
(i)=>Product('商品 $i','这是一个商品详情,编号为:$i')
),
)
));
}
class ProductList extends StatelessWidget{
final List<Product> 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(products[index].title),
onTap:(){
Navigator.push(
context,
MaterialPageRoute(
builder:(context)=>new ProductDetail(product:products[index])
)
);
}
);
},
)
);
}
}
class ProductDetail extends StatelessWidget {
final Product product;
ProductDetail({Key key ,@required this.product}):super(key:key);
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title:Text('${product.title}'),
),
body:Center(child: Text('${product.description}'),)
);
}
}
页面跳转并返回数据
页面跳转后,当我们返回页面时返回结果到上一个页面(也就是父页面)。这样的场景经常用于,我们去子页面选择了一项选项,然后把选择的结果返回给父级页面。
异步请求和等待
Dart中的异步请求和等待和ES6中的方法很像,直接使用async…await就可以实现。比如下面作了一个找小姐姐的方法,然后进行跳转,注意这时候是异步的。等待结果回来之后,我们再显示出来内容。具体代码如下:
_navigateToXiaoJieJie(BuildContext context) async{ //async是启用异步方法
final result = await Navigator.push(//等待
context,
MaterialPageRoute(builder: (context)=> XiaoJieJie())
);
Scaffold.of(context).showSnackBar(SnackBar(content:Text('$result')));
}
}
SnackBar的使用
SnackBar是用户操作后,显示提示信息的一个控件,类似Tost,会自动隐藏。
SnackBar是以Scaffold的showSnackBar方法来进行显示的
Scaffold.of(context).showSnackBar(SnackBar(content:Text('$result')));
返回数据的方式
Navigator.pop(context,'xxxx'); //xxx就是返回的参数
完整代码
import 'package:flutter/material.dart';
void main(){
runApp(MaterialApp(
title:'页面跳转返回数据',
home:FirstPage()
));
}
class FirstPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar:AppBar(title:Text("找小姐姐要电话")),
body:Center(
child: RouteButton(),
)
);
}
}
//跳转的Button
class RouteButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return RaisedButton(
onPressed:(){
_navigateToXiaoJieJie(context);
},
child: Text('去找小姐姐'),
);
}
_navigateToXiaoJieJie(BuildContext context) async{ //async是启用异步方法
final result = await Navigator.push(//等待
context,
MaterialPageRoute(builder: (context)=> XiaoJieJie())
);
Scaffold.of(context).showSnackBar(SnackBar(content:Text('$result')));
}
}
class XiaoJieJie extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar:AppBar(
title:Text('我是小姐姐')
),
body:Center(
child:Column(
children: <Widget>[
RaisedButton(
child: Text('大长腿小姐姐'),
onPressed: (){
Navigator.pop(context,'大长腿:1511008888');
},
) ,
RaisedButton(
child: Text('小蛮腰小姐姐'),
onPressed: (){
Navigator.pop(context,'大长腿:1511009999');
},
) ,
],
)
) ,
);
}
}