列表是APP的核心功能,目前这个库不算完善,之后国外的大神应该会补全,如今的样式就是很基础的东西,解决一些经常使用的加载,至于后面的自定义tag须要一个过程,混合布局能够参考flutter_staggered_grid_view,下面是基础的写法:
java
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个列表项 ), ), ], ), ); } }
滚动监听及控制:
app
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里面改写就能够独立出来不一样的样式去加载数据,仍是挺方便的,代码精简很多~加油~
less