玖叶教程网

前端编程开发入门

Flutter第六期 - ListView+GridView混合

列表是APP的核心功能,目前这个库不算完善,以后国外的大神应该会补全,现在的样式就是很基础的东西,解决一些常用的加载,至于后面的自定义tag需要一个过程,混合布局可以参考flutter_staggered_grid_view,下面是基础的写法:

import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
//Stateless widgets 是不可变的, 这意味着它们的属性不能改变 - 所有的值都是最终的.
//Stateful widgets 持有的状态可能在widget生命周期中发生变化. 实现一个 stateful widget 至少需要两个类:
class MyApp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
// final wordPair = new WordPair.random();
 return new MaterialApp(
 title: 'ListView3+GridView33',
 debugShowCheckedModeBanner: false,
 theme: new ThemeData(
 primarySwatch: Colors.blue,
// fontFamily: 'fontdemo1'
 ),
 home: new Scaffold(
 appBar: new AppBar(
 title: new Text('图片加载'),
 ),
 body: new Center(
// child: new ListView(
// shrinkWrap: true,
// padding: const EdgeInsets.all(20.0),
// children: <Widget>[
// const Text('I\'m dedicating every day to you'),
// const Text('Domestic life was never quite my style'),
// const Text('When you smile, you knock me out, I fall apart'),
// const Text('And I thought I was so smart'),
// ],
// ),
// child: new ListView3(),
// child: new GridView3(),
// child: new GridView33(),
 child: new InfiniteGridView(),
 ),
 ),
 );
 }
}
class ListView3 extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
 //下划线widget预定义以供复用。
 Widget divider1 = Divider(
 color: Colors.blue,
 );
 Widget divider2 = Divider(color: Colors.green);
 return ListView.separated(
 itemCount: 100,
 //列表项构造器
 itemBuilder: (BuildContext context, int index) {
 return ListTile(title: Text("$index"));
 },
 //分割器构造器
 separatorBuilder: (BuildContext context, int index) {
 return index % 2 == 0 ? divider1 : divider2;
 },
 );
 }
}
class GridView3 extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
 return GridView(
 gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
 crossAxisCount: 3, //横轴三个子widget
 childAspectRatio: 1.0, //宽高比为1时,子widget
 ),
 children: <Widget>[
 Icon(Icons.ac_unit),
 Icon(Icons.airport_shuttle),
 Icon(Icons.all_inclusive),
 Icon(Icons.beach_access),
 Icon(Icons.cake),
 Icon(Icons.free_breakfast)
 ]);
 }
}
class GridView33 extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
 return GridView(
 padding: EdgeInsets.zero,
 gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
 maxCrossAxisExtent: 120.0, childAspectRatio: 2.0, //宽高比为2
 ),
 children: <Widget>[
 Icon(Icons.ac_unit),
 Icon(Icons.airport_shuttle),
 Icon(Icons.all_inclusive),
 Icon(Icons.beach_access),
 Icon(Icons.cake),
 Icon(Icons.free_breakfast),
 ],
 );
 }
}
class InfiniteGridView extends StatefulWidget {
 @override
 _InfiniteGridViewState createState() => new _InfiniteGridViewState();
}
class _InfiniteGridViewState extends State<InfiniteGridView> {
 List<IconData> _icons = []; //保存Icon数据
 @override
 void initState() {
 // 初始化数据
 _retrieveIcons();
 }
 @override
 Widget build(BuildContext context) {
 return GridView.builder(
 gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
 crossAxisCount: 3, //每行三列
 childAspectRatio: 1.0 //显示区域宽高相等
 ),
 itemCount: _icons.length,
 itemBuilder: (context, index) {
 //如果显示到最后一个并且Icon总数小于200时继续获取数据
 if (index == _icons.length - 1 && _icons.length < 200) {
 _retrieveIcons();
 }
 return Icon(_icons[index]);
 }
 );
 }
 //模拟异步获取数据
 void _retrieveIcons() {
 Future.delayed(Duration(milliseconds: 200)).then((e) {
 setState(() {
 _icons.addAll([
 Icons.ac_unit,
 Icons.airport_shuttle,
 Icons.all_inclusive,
 Icons.beach_access, Icons.cake,
 Icons.free_breakfast
 ]);
 });
 });
 }
}

ListView+GridView图文混合:

import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
//Stateless widgets 是不可变的, 这意味着它们的属性不能改变 - 所有的值都是最终的.
//Stateful widgets 持有的状态可能在widget生命周期中发生变化. 实现一个 stateful widget 至少需要两个类:
class MyApp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
// final wordPair = new WordPair.random();
 return new MaterialApp(
 title: 'ListView+GridView综合布局',
 debugShowCheckedModeBanner: false,
 theme: new ThemeData(
 primarySwatch: Colors.blue,
// fontFamily: 'fontdemo1'
 ),
 home: new Scaffold(
// appBar: new AppBar(
//// title: new Text('图片加载'),
//// ),
 body: new Center(
// child: new ListView(
// shrinkWrap: true,
// padding: const EdgeInsets.all(20.0),
// children: <Widget>[
// const Text('I\'m dedicating every day to you'),
// const Text('Domestic life was never quite my style'),
// const Text('When you smile, you knock me out, I fall apart'),
// const Text('And I thought I was so smart'),
// ],
// ),
// child: new ListView3(),
// child: new GridView3(),
// child: new GridView33(),
 child: new CustomScrollViewTestRoute(),
 ),
 ),
 );
 }
}
class CustomScrollViewTestRoute extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
 //因为本路由没有使用Scaffold,为了让子级Widget(如Text)使用
 //Material Design 默认的样式风格,我们使用Material作为本路由的根。
 return Material(
 child: CustomScrollView(
 slivers: <Widget>[
 //AppBar,包含一个导航栏
 SliverAppBar(
 //标题居中
 centerTitle: true,
 leading: Builder(builder: (context) {
 return IconButton(
 icon: Icon(Icons.arrow_back, color: Colors.white), //自定义图标
 onPressed: () {
 //
 },
 );
 }),
// leading: Icon(
// Icons.arrow_back,
// ),
 //展开高度250
 expandedHeight: 250.0,
 //不随着滑动隐藏标题
 floating: false,
 //固定在顶部
 pinned: true,
 flexibleSpace: FlexibleSpaceBar(
 title: const Text('YUN'),
 background: Image.asset(
 "assets/images/food04.jpeg",
 fit: BoxFit.cover,
 ),
 ),
 ),
 SliverPadding(
 padding: const EdgeInsets.all(8.0),
 sliver: new SliverGrid(
 //Grid
 gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
 crossAxisCount: 2, //Grid按两列显示
 mainAxisSpacing: 10.0,
 crossAxisSpacing: 10.0,
 childAspectRatio: 4.0,
 ),
 delegate: new SliverChildBuilderDelegate(
 (BuildContext context, int index) {
 //创建子widget
 return new Container(
 alignment: Alignment.center,
 color: Colors.cyan[100 * (index % 9)],
 child: new Text('grid item $index'),
 );
 },
 childCount: 20,
 ),
 ),
 ),
 //List
 new SliverFixedExtentList(
 itemExtent: 50.0,
 delegate: new SliverChildBuilderDelegate(
 (BuildContext context, int index) {
 //创建列表项
 return new Container(
 alignment: Alignment.center,
 color: Colors.lightBlue[100 * (index % 9)],
 child: new Text('list item $index'),
 );
 }, childCount: 50 //50个列表项
 ),
 ),
 ],
 ),
 );
 }
}

滚动监听及控制:

import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
//Stateless widgets 是不可变的, 这意味着它们的属性不能改变 - 所有的值都是最终的.
//Stateful widgets 持有的状态可能在widget生命周期中发生变化. 实现一个 stateful widget 至少需要两个类:
class MyApp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
// final wordPair = new WordPair.random();
 return new MaterialApp(
 title: '滚动监听及控制',
 debugShowCheckedModeBanner: false,
 theme: new ThemeData(
 primarySwatch: Colors.blue,
// fontFamily: 'fontdemo1'
 ),
 home: new Scaffold(
 appBar: new AppBar(
 title: new Text('滚动监听及控制'),
 ),
 body: new Center(
// child: new ListView(
// shrinkWrap: true,
// padding: const EdgeInsets.all(20.0),
// children: <Widget>[
// const Text('I\'m dedicating every day to you'),
// const Text('Domestic life was never quite my style'),
// const Text('When you smile, you knock me out, I fall apart'),
// const Text('And I thought I was so smart'),
// ],
// ),
// child: new ListView3(),
// child: new GridView3(),
// child: new GridView33(),
 child: new ScrollControllerTestRoute(),
// child: new ScrollNotificationTestRoute(),
 ),
 ),
 );
 }
}
class ScrollControllerTestRoute extends StatefulWidget {
 @override
 ScrollControllerTestRouteState createState() {
 return new ScrollControllerTestRouteState();
 }
}
class ScrollControllerTestRouteState extends State<ScrollControllerTestRoute> {
 ScrollController _controller = new ScrollController();
 bool showToTopBtn = false; //是否显示“返回到顶部”按钮
 @override
 void initState() {
 //监听滚动事件,打印滚动位置
 _controller.addListener(() {
 print(_controller.offset); //打印滚动位置
 if (_controller.offset < 1000 && showToTopBtn) {
 setState(() {
 showToTopBtn = false;
 });
 } else if (_controller.offset >= 1000 && showToTopBtn == false) {
 setState(() {
 showToTopBtn = true;
 });
 }
 });
 }
 @override
 void dispose() {
 //为了避免内存泄露,需要调用_controller.dispose
 _controller.dispose();
 super.dispose();
 }
 @override
 Widget build(BuildContext context) {
 return Scaffold(
// appBar: AppBar(title: Text("滚动控制")),
 body: Scrollbar(
 child: ListView.builder(
 itemCount: 100,
 itemExtent: 50.0, //列表项高度固定时,显式指定高度是一个好习惯(性能消耗小)
 controller: _controller,
 itemBuilder: (context, index) {
 return ListTile(
 title: Text("$index"),
 );
 }),
 ),
 floatingActionButton: !showToTopBtn
 ? null
 : FloatingActionButton(
 child: Icon(Icons.arrow_upward),
 onPressed: () {
 //返回到顶部时执行动画
 _controller.animateTo(.0,
 duration: Duration(milliseconds: 200), curve: Curves.ease);
 }),
 );
 }
}
class ScrollNotificationTestRoute extends StatefulWidget {
 @override
 _ScrollNotificationTestRouteState createState() =>
 new _ScrollNotificationTestRouteState();
}
class _ScrollNotificationTestRouteState
 extends State<ScrollNotificationTestRoute> {
 String _progress = "0%"; //保存进度百分比
 @override
 Widget build(BuildContext context) {
 return Scrollbar(
 //进度条
 // 监听滚动通知
 child: NotificationListener<ScrollNotification>(
 onNotification: (ScrollNotification notification) {
 double progress = notification.metrics.pixels /
 notification.metrics.maxScrollExtent;
 //重新构建
 setState(() {
 _progress = "${(progress * 100).toInt()}%";
 });
 print("BottomEdge: ${notification.metrics.extentAfter == 0}");
 //return true; //放开此行注释后,进度条将失效
 },
 child: Stack(
 alignment: Alignment.center,
 children: <Widget>[
 ListView.builder(
 itemCount: 100,
 itemExtent: 50.0,
 itemBuilder: (context, index) {
 return ListTile(title: Text("$index"));
 }),
 CircleAvatar(
 //显示进度百分比
 radius: 30.0,
 child: Text(_progress),
 backgroundColor: Colors.black54,
 )
 ],
 ),
 ),
 );
 }
}

总结:学完网络请求,大家把tolist里面改写就可以独立出来不同的样式去加载数据,还是挺方便的,代码精简不少~加油~

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言