初学flutter,一顿复制粘贴相关代码,哈哈哈
搞个如图片布局
底部tab + 侧边栏 + 列表
main.dart中的代码
import 'package:flutter/material.dart';
import './movie/list.dart';
//主函数(入口函数),下面我会简单说说Dart的函数
void main() => runApp(MyApp());
// 声明MyApp类
class MyApp extends StatelessWidget {
//重写build方法
@override
Widget build(BuildContext context) {
//返回一个Material风格的组件
return MaterialApp(
home: DefaultTabController(
length: 3,
child: Scaffold(
//创建一个Bar,并添加文本
appBar: AppBar(
title: Text('电影列表'),
centerTitle: true,
actions: <Widget>[
IconButton(
icon: Icon(Icons.search),
onPressed: () {},
)
],
),
drawer: Drawer(
child: Container(
decoration: BoxDecoration(color: Colors.black87),
child: ListView(
padding: EdgeInsets.all(0.0),
children: <Widget>[
UserAccountsDrawerHeader(
accountEmail: Text('accountEmail'),
accountName: Text('accountName'),
currentAccountPicture: CircleAvatar(
backgroundImage: NetworkImage(
'https://avatars0.githubusercontent.com/u/19768767?s=400&u=fcc8a73c2e55aa8efc5c63041df8cd912e43e05b&v=4'),
),
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(
'https://avatars0.githubusercontent.com/u/19768767?s=400&u=fcc8a73c2e55aa8efc5c63041df8cd912e43e05b&v=4'),
fit: BoxFit.cover)),
),
ListTile(
title: Text('用户反馈', style: TextStyle(color: Colors.white)),
trailing: Icon(Icons.feedback, color: Colors.white),
),
ListTile(
title: Text('系统设置', style: TextStyle(color: Colors.white)),
trailing: Icon(Icons.settings, color: Colors.white),
),
ListTile(
title: Text('我要发布', style: TextStyle(color: Colors.white)),
trailing: Icon(Icons.send, color: Colors.white),
),
Divider(color: Colors.white30),
ListTile(
title: Text('注销', style: TextStyle(color: Colors.white)),
trailing: Icon(Icons.exit_to_app, color: Colors.white),
)
],
),
),
),
bottomNavigationBar: Container(
decoration: BoxDecoration(
color: Colors.black,
),
height: 50,
child: TabBar(
labelStyle: TextStyle(height: 0, fontSize: 12),
tabs: <Widget>[
Tab(icon: Icon(Icons.movie_filter), text: '正在热映'),
Tab(
icon: Icon(Icons.movie_filter),
text: '即将上映',
),
Tab(
icon: Icon(Icons.movie_filter),
text: 'Top250',
),
],
),
),
body: TabBarView(children: <Widget>[
new MovieList(mt: 'in_theaters'),
new MovieList(mt: 'coming_soon'),
new MovieList(mt: 'top250'),
])),
));
}
}
同级目录下movie文件夹中list.dart 代码
import 'package:flutter/material.dart';
import 'package:dio/dio.dart';
Dio dio = new Dio();
class MovieList extends StatefulWidget {
// 固定写法
// MovieList({Key key}) : super(key: key)
MovieList({Key key, @required this.mt}) : super(key: key);
var mt;
@override
_MovieListState createState() {
return new _MovieListState();
}
}
//有状态控件。必须有一个状态管理类,来进行实现
class _MovieListState extends State<MovieList> {
// 默认显示第一页数据
int page = 1;
// 每页显示的数据条数
int pagesize = 10;
// 电影列表数据
var mlist = [];
// 总数据条数,实现分页效果的
var total = 0;
// 是否加载完毕了
bool isover = false;
// 是否正在加载数据
bool isloading = true;
ScrollController _scrollCtrl;
// 保持当前页面的数据状态
@override
bool get wantKeepAlive => true;
// 控件被创建的时候,会执行 initState
@override
void initState() {
super.initState();
_scrollCtrl = new ScrollController();
_scrollCtrl.addListener(() {
if (_scrollCtrl.position.pixels == _scrollCtrl.position.maxScrollExtent) {
// print('滑动到了底部');
// 是否正在加载中或所有数据加载完毕了
if (isloading || isover) return;
// 判断是否加载完毕了所有的数据
if (page * pagesize >= total) {
setState(() {
isover = true;
});
return;
}
// 页码值自增 +1
setState(() {
page++;
});
// 获取下一页数据
getMovieList();
}
});
getMovieList();
}
// 渲染当前这个 MovieList 控件的UI结构
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: mlist.length,
itemBuilder: (BuildContext ctx, int i) {
// 每次循环,都拿到当前的电影Item项
var mitem = mlist[i];
return Container(
height: 200,
decoration: BoxDecoration(border: Border(top: BorderSide(color: Colors.black12))),
child: Row(children: <Widget>[
Image.network(mitem['images']['small'], width: 130, height: 180, fit: BoxFit.cover,),
Expanded(
child: Container(
padding: EdgeInsets.only(left: 10),
height: 200,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Text('电影名称: ${mitem['title']}', style: TextStyle(fontSize: 12),),
Text('上映年份: ${mitem['year']}', style: TextStyle(fontSize: 12),),
Text('电影类型: ${mitem['genres'].join(' ')}', style: TextStyle(fontSize: 12),),
Text('豆瓣评分: ${mitem['rating']['average']}', style: TextStyle(fontSize: 12),),
Row(
children: <Widget>[
Text('主演:', style: TextStyle(fontSize: 12)),
Row(
children: List.generate(
mlist[i]['casts'].length,
(int index) => Container(
margin: EdgeInsets.symmetric(vertical: 0, horizontal: 5),
child: CircleAvatar(
backgroundImage: NetworkImage(mlist[
i]['casts'][index]
['avatars'] ==
null
? 'https://img3.doubanio.com/f/movie/8dd0c794499fe925ae2ae89ee30cd225750457b4/pics/movie/celebrity-default-medium.png'
: mlist[i]['casts'][index]
['avatars']['small']),
),
)
)
)
],
)
]),
),
)
],),
);
},
controller: _scrollCtrl,
);
}
getMovieList() async {
// js 中有模板字符串
// 偏移量的计算公式 (page - 1) * pageSize
int offset = (page - 1) * pagesize;
var response = await dio.get('http://www.liulongbin.top:3005/api/v2/movie/${widget.mt}?start=$offset&count=$pagesize');
var result = response.data;
// 今后只要为私有数据,都需要把赋值的操作,放到setState函数中,否则,页面不会更新
setState(() {
mlist = result['subjects'];
total = result['total'];
});
// print(result);
}
}