开篇寄语
伯衡君发现总结了有关flutter编程语言以制作全平台的App,通过前一篇梳理Widgets组件和Layouts布局内容,感到思路清晰了不少,这一篇文章继续进行梳理,有关Lists的内容,这个简单来说就是各种行的不同形式,伯衡君希望进行梳理后,有一个整体的认知,让我们开始吧。
前情提要
- 《如何在Mac M1芯片电脑上安装Flutter并建立自己第一个全系统应用》
- 《如何在Windows电脑上安装Flutter并建立自己第一个全系统应用》
- 《Flutter制作自己的第一个全平台APP学习之Widgets篇》
- 《Flutter制作自己的第一个全平台APP学习之Layouts篇》
内容详情
以下内容大多是更改lib下的main.dart文件内容,删掉里面的内容,复制粘贴代码,开启调试就可以出现了。
ListTile
- 单个固定高度的行,通常包含一些文本以及前导或尾部图标,试举一例如下:
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { // This widget is the root // of your application @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: Text('Insert Image Demo'), ), body: Column(children: <Widget>[ Card(child: ListTile(title: Text('Hello World!'))), Card(child: ListTile(title: Text('Hello World!!'))), Card(child: ListTile(title: Text('Hello World!!!'))), ]), ), ); } }
生成效果如下图所示:
ListView.builder
- 简单来说就是批量构建行的函数,试举例如下:
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { List<String> litems = [ "1", "2", "Third", "4", "a", "b", "c", "d", "22", "111" ]; // This widget is the root // of your application @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: Text('Insert Image Demo'), ), body: new ListView.builder( itemCount: 10, itemBuilder: (BuildContext ctxt, int index) { return new Card( child: Text(litems[index])); }), ), ); } }
生成效果如下图所示:
GridList
- 想必大家对于相册并不陌生,这个类就相当于相册的展现形式,试举例如下:
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { List<String> litems = [ "1", "2", "Third", "4", "a", "b", "c", "d", "22", "111" ]; // This widget is the root // of your application @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: Text('Insert Image Demo'), ), body: GridView.count( // Create a grid with 2 columns. If you change the scrollDirection to // horizontal, this produces 2 rows. crossAxisCount: 2, // Generate 100 widgets that display their index in the List. children: List.generate(100, (index) { return Center( child: Container( decoration: BoxDecoration( border: Border.all(color: Colors.grey, width: 3.0), ), padding: const EdgeInsets.all(16.0), child: Text( 'Item $index', style: Theme.of(context).textTheme.headline5, ), ), ); }), ), ), ); } }
生成效果如下图所示:
ExpansionTile
- 这个是点击后展开隐藏内容,相当于Web中点击后出现列表<li></li>这样,试举例如下,首先是在main.dart内输入以下代码:
import 'package:flutter/material.dart'; import 'home.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Expansion View', theme: ThemeData( primarySwatch: Colors.blue, ), home: Home(), ); } }
接着在main.dart文件的文件夹下新建home.dart文件,输入以下代码:
import 'package:flutter/material.dart'; import 'expansionTile.dart'; class Home extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text( 'Flutter Expansion View', ), centerTitle: true, elevation: 0.0, ), body: Padding( padding: const EdgeInsets.symmetric(horizontal: 30.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Row( children: <Widget>[ Expanded( child: TextButton( onPressed: () { Navigator.push( context, MaterialPageRoute( builder: (BuildContext context) => Expansiontile())); }, child: Text('ExpansionTile'), ), ), ], ), ], ), ), ); } }
接着还是在文件夹下,新建一个名为expantionTile.dart文件,输入以下代码:
import 'package:flutter/material.dart'; class Expansiontile extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( centerTitle: true, title: Text('Expansion Tile'), ), body: Padding( padding: const EdgeInsets.symmetric(horizontal: 30.0), child: Column( children: <Widget>[ SizedBox(height: 20.0), ExpansionTile( title: Text( "Title", style: TextStyle(fontSize: 18.0, fontWeight: FontWeight.bold), ), children: <Widget>[ ExpansionTile( title: Text( 'Sub title', ), children: <Widget>[ ListTile( title: Text('data'), ) ], ), ListTile( title: Text('data'), ) ], ), ], ), ), ); } }
生成效果如下图所示:
Swipe to Dismiss
- 左右滑动,删除掉该行,这种方式很常见以在构建App,试举例如下:
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); // ignore: must_be_immutable class MyApp extends StatelessWidget { List<String> items = [ "1", "2", "Third", "4", "a", "b", "c", "d", "22", "111" ]; // This widget is the root // of your application @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: Text('Insert Image Demo'), ), body: ListView.builder( itemCount: items.length, itemBuilder: (context, index) { final item = items[index]; return Dismissible( // Each Dismissible must contain a Key. Keys allow Flutter to // uniquely identify widgets. key: Key(item), // Provide a function that tells the app // what to do after an item has been swiped away. onDismissed: (direction) { // Remove the item from the data source. items.removeAt(index); // Then show a snackbar. ScaffoldMessenger.of(context) .showSnackBar(SnackBar(content: Text('$item dismissed'))); }, // Show a red background as the item is swiped away. background: Container(color: Colors.red), child: ListTile(title: Text('$item')), ); }), )); } }
生成效果如下图所示:
DataTable
- 这个是新建一个交互式或者非交互式的表格,展现更多的信息,试举例如下:
import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); /// This is the main application widget. class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); static const String _title = 'Flutter Code Sample'; @override Widget build(BuildContext context) { return MaterialApp( title: _title, home: Scaffold( appBar: AppBar(title: const Text(_title)), body: const MyStatelessWidget(), ), ); } } /// This is the stateless widget that the main application instantiates. class MyStatelessWidget extends StatelessWidget { const MyStatelessWidget({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return DataTable( columns: const <DataColumn>[ DataColumn( label: Text( 'Name', style: TextStyle(fontStyle: FontStyle.italic), ), ), DataColumn( label: Text( 'Age', style: TextStyle(fontStyle: FontStyle.italic), ), ), DataColumn( label: Text( 'Role', style: TextStyle(fontStyle: FontStyle.italic), ), ), DataColumn( label: Text( 'Ranking', style: TextStyle(fontStyle: FontStyle.italic), ), ), ], rows: const <DataRow>[ DataRow( cells: <DataCell>[ DataCell(Text('MM')), DataCell(Text('20')), DataCell(Text('girl')), DataCell(Text('98')), ], ), DataRow( cells: <DataCell>[ DataCell(Text('MM')), DataCell(Text('20')), DataCell(Text('girl')), DataCell(Text('98')), ], ), DataRow( cells: <DataCell>[ DataCell(Text('MM')), DataCell(Text('20')), DataCell(Text('girl')), DataCell(Text('98')), ], ), DataRow( cells: <DataCell>[ DataCell(Text('MM')), DataCell(Text('20')), DataCell(Text('girl')), DataCell(Text('98')), ], ), ], ); } }
生成效果如下图所示:
ReorderableListView
- 用户可以进行自定义排序的一个类,在App中很常见,试举例如下:
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( // Remove the debug banner debugShowCheckedModeBanner: false, title: 'Kindacode.com', home: HomePage(), ); } } class HomePage extends StatefulWidget { @override _HomePageState createState() => _HomePageState(); } class _HomePageState extends State<HomePage> { // Generate dummy data for the list view List<String> _products = List.generate(100, (index) => "Product ${index.toString()}"); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Reorder Demo'), ), body: ReorderableListView.builder( itemCount: _products.length, itemBuilder: (context, index) { final String productName = _products[index]; return Card( key: ValueKey(productName), color: Colors.amberAccent, elevation: 1, margin: const EdgeInsets.all(10), child: ListTile( contentPadding: EdgeInsets.all(30), title: Text( productName, style: TextStyle(fontSize: 18), ), onTap: () {/* Do something else */}, ), ); }, // The reorder function onReorder: (oldIndex, newIndex) { setState(() { if (newIndex > oldIndex) { newIndex = newIndex - 1; } final element = _products.removeAt(oldIndex); _products.insert(newIndex, element); }); }), ); } } import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( // Remove the debug banner debugShowCheckedModeBanner: false, title: 'Kindacode.com', home: HomePage(), ); } } class HomePage extends StatefulWidget { @override _HomePageState createState() => _HomePageState(); } class _HomePageState extends State<HomePage> { // Generate dummy data for the list view List<String> _products = List.generate(100, (index) => "Product ${index.toString()}"); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Reorder Demo'), ), body: ReorderableListView.builder( itemCount: _products.length, itemBuilder: (context, index) { final String productName = _products[index]; return Card( key: ValueKey(productName), color: Colors.amberAccent, elevation: 1, margin: const EdgeInsets.all(10), child: ListTile( contentPadding: EdgeInsets.all(30), title: Text( productName, style: TextStyle(fontSize: 18), ), onTap: () {/* Do something else */}, ), ); }, // The reorder function onReorder: (oldIndex, newIndex) { setState(() { if (newIndex > oldIndex) { newIndex = newIndex - 1; } final element = _products.removeAt(oldIndex); _products.insert(newIndex, element); }); }), ); } }
生成效果如下图所示:
Slidable list tile
- 这个类似于dismiss,左右滑动,但不是消除,而是出现选项,比如常用的邮箱App,标记已读或者删除等活动行为,就可以用此方法,试举一例:
首先是在pubspec.yaml这个文件添加支持的库,如下所示:
dependencies: flutter: sdk: flutter flutter_slidable: ^0.6.0
之后就可以在main.dart文件中调用了,代码如下:
import 'package:flutter/material.dart'; import 'package:flutter_slidable/flutter_slidable.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(), ); } } class MyHomePage extends StatefulWidget { @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { @override Widget build(BuildContext context) { final List<String> items = new List<String>.generate(10, (i) => "item ${i + 1}"); return Scaffold( appBar: AppBar( title: Text("Flutter Slideable Example"), ), body: ListView.separated( separatorBuilder: (context, index) => Divider( color: Colors.black, ), itemCount: items.length, itemBuilder: (context, int index) { return Slidable( actions: <Widget>[ IconSlideAction( icon: Icons.more, caption: 'MORE', color: Colors.blue, onTap: () { print("More ${items[index]} is Clicked"); }), ], secondaryActions: <Widget>[ IconSlideAction( icon: Icons.clear, color: Colors.red, caption: 'Cancel', onTap: () { print("Cancel ${items[index]} is Clicked"); }) ], child: ListTile( leading: Icon(Icons.message), title: Text("${items[index]}"), subtitle: Text("Slide left or right"), trailing: Icon(Icons.arrow_back), ), actionPane: SlidableDrawerActionPane(), ); }), ); } }
生成效果如下图所示:
- 我的微信
- 微信扫一扫加好友
- 我的微信公众号
- 扫描关注公众号