在应用程序中可滑动可用于执行范围广泛的任务,只需在磁贴上向左或向右滑动即可。它不仅使用户界面非常人性化,而且还节省了大量时间来处理琐碎的任务,如果以其他方式完成这些任务,设计可能会很忙且多余。在本文中,我们将研究为您的应用程序设计可滑动的过程。
在这里,我们将使用磁贴构建一个简单的应用程序,当从左到右滑动时会存档磁贴,从右向左滑动时会删除磁贴。为此,请执行以下步骤:
- 将flutter_slidable依赖项添加到pubspec.yaml 文件中。
- 将依赖项导入到 main.js 中。dart文件
- 创建一个StatelessWidget为应用程序提供一个结构
- 使用StateFulWidget向应用程序添加主页
- 使用SlidableCntroller设置滑动动作
- 使用FloatingActionButton将动作分配给滑动磁贴时生成的按钮
- 使用WidgetBuilder在主页上构建图块
让我们详细讨论这些步骤。
添加依赖:
您可以在pubspec.yaml 文件中导入flutter_slidable依赖项,如下所示:
导入依赖:
在 main.js 中导入依赖项。 dart文件使用以下内容:
import 'package:flutter_slidable/flutter_slidable.dart';
创建应用程序结构:
使用StatelessWidget为应用程序提供一个简单的结构,如下所示:
Dart
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Slidable ',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'GeeksForGeeks'),
);
}
}
Dart
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State {
SlidableController slidableController;
final List<_HomeItem> items = List.generate(
20,
(i) => _HomeItem(
i,
'Slide Bar $i',
_getSubtitle(i),
_getAvatarColor(i),
),
);
Dart
Slidable(
actionPane: SlidableDrawerActionPane(),
actionExtentRatio: 0.25,
child: Container(
color: Colors.white,
child: ListTile(
leading: CircleAvatar(
backgroundColor: Colors.indigoAccent,
child: Text('$3'),
foregroundColor: Colors.white,
),
title: Text('Tile $3'),
subtitle: Text('SlidableDrawerDelegate'),
),
),
actions: [
IconSlideAction(
caption: 'Archive',
color: Colors.blue,
icon: Icons.archive,
onTap: () => _showSnackBar('Archive'),
),
IconSlideAction(
caption: 'Share',
color: Colors.indigo,
icon: Icons.share,
onTap: () => _showSnackBar('Share'),
),
],
secondaryActions: [
IconSlideAction(
caption: 'More',
color: Colors.black45,
icon: Icons.more_horiz,
onTap: () => _showSnackBar('More'),
),
IconSlideAction(
caption: 'Delete',
color: Colors.red,
icon: Icons.delete,
onTap: () => _showSnackBar('Delete'),
),
],
);
Dart
@protected
void initState() {
slidableController = SlidableController(
onSlideAnimationChanged: handleSlideAnimationChanged,
onSlideIsOpenChanged: handleSlideIsOpenChanged,
);
super.initState();
}
Animation _rotationAnimation;
Color _fabColor = Colors.blue;
void handleSlideAnimationChanged(Animation slideAnimation) {
setState(() {
_rotationAnimation = slideAnimation;
});
}
void handleSlideIsOpenChanged(bool isOpen) {
setState(() {
_fabColor = isOpen ? Colors.green : Colors.blue;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
backgroundColor: Colors.green,
),
body: Center(
child: OrientationBuilder(
builder: (context, orientation) => _buildList(
context,
orientation == Orientation.portrait
? Axis.vertical
: Axis.horizontal),
),
),
floatingActionButton: FloatingActionButton(
backgroundColor: _fabColor,
onPressed: null,
child: _rotationAnimation == null
? Icon(Icons.add)
: RotationTransition(
turns: _rotationAnimation,
child: Icon(Icons.add),
),
),
);
}
Widget _buildList(BuildContext context, Axis direction) {
return ListView.builder(
scrollDirection: direction,
itemBuilder: (context, index) {
final Axis slidableDirection =
direction == Axis.horizontal ? Axis.vertical : Axis.horizontal;
var item = items[index];
if (item.index < 8) {
return _getSlidableWithLists(context, index, slidableDirection);
} else {
return _getSlidableWithDelegates(context, index, slidableDirection);
}
},
itemCount: items.length,
);
}
Widget _getSlidableWithLists(
BuildContext context, int index, Axis direction) {
final _HomeItem item = items[index];
return Slidable(
key: Key(item.title),
controller: slidableController,
direction: direction,
dismissal: SlidableDismissal(
child: SlidableDrawerDismissal(),
onDismissed: (actionType) {
_showSnackBar(
context,
actionType == SlideActionType.primary
? 'Dismiss Archive'
: 'Dismiss Delete');
setState(() {
items.removeAt(index);
});
},
),
actionPane: _getActionPane(item.index),
actionExtentRatio: 0.25,
child: direction == Axis.horizontal
? VerticalListItem(items[index])
: HorizontalListItem(items[index]),
actions: [
IconSlideAction(
caption: 'Archive',
color: Colors.blue,
icon: Icons.archive,
onTap: () => _showSnackBar(context, 'Archive'),
),
IconSlideAction(
caption: 'Share',
color: Colors.indigo,
icon: Icons.share,
onTap: () => _showSnackBar(context, 'Share'),
),
],
secondaryActions: [
Container(
height: 800,
color: Colors.green,
child: Text('a'),
),
IconSlideAction(
caption: 'More',
color: Colors.grey.shade200,
icon: Icons.more_horiz,
onTap: () => _showSnackBar(context, 'More'),
closeOnTap: false,
),
IconSlideAction(
caption: 'Delete',
color: Colors.red,
icon: Icons.delete,
onTap: () => _showSnackBar(context, 'Delete'),
),
],
);
}
Dart
import 'package:flutter/material.dart';
import 'package:flutter_slidable/flutter_slidable.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Slidable ',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'GeeksForGeeks'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State {
SlidableController slidableController;
final List<_HomeItem> items = List.generate(
20,
(i) => _HomeItem(
i,
'Slide Bar $i',
_getSubtitle(i),
_getAvatarColor(i),
),
);
@protected
void initState() {
slidableController = SlidableController(
onSlideAnimationChanged: handleSlideAnimationChanged,
onSlideIsOpenChanged: handleSlideIsOpenChanged,
);
super.initState();
}
Animation _rotationAnimation;
Color _fabColor = Colors.blue;
void handleSlideAnimationChanged(Animation slideAnimation) {
setState(() {
_rotationAnimation = slideAnimation;
});
}
void handleSlideIsOpenChanged(bool isOpen) {
setState(() {
_fabColor = isOpen ? Colors.green : Colors.blue;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
backgroundColor: Colors.green,
),
body: Center(
child: OrientationBuilder(
builder: (context, orientation) => _buildList(
context,
orientation == Orientation.portrait
? Axis.vertical
: Axis.horizontal),
),
),
floatingActionButton: FloatingActionButton(
backgroundColor: _fabColor,
onPressed: null,
child: _rotationAnimation == null
? Icon(Icons.add)
: RotationTransition(
turns: _rotationAnimation,
child: Icon(Icons.add),
),
),
);
}
Widget _buildList(BuildContext context, Axis direction) {
return ListView.builder(
scrollDirection: direction,
itemBuilder: (context, index) {
final Axis slidableDirection =
direction == Axis.horizontal ? Axis.vertical : Axis.horizontal;
var item = items[index];
if (item.index < 8) {
return _getSlidableWithLists(context, index, slidableDirection);
} else {
return _getSlidableWithDelegates(context, index, slidableDirection);
}
},
itemCount: items.length,
);
}
Widget _getSlidableWithLists(
BuildContext context, int index, Axis direction) {
final _HomeItem item = items[index];
//final int t = index;
return Slidable(
key: Key(item.title),
controller: slidableController,
direction: direction,
dismissal: SlidableDismissal(
child: SlidableDrawerDismissal(),
onDismissed: (actionType) {
_showSnackBar(
context,
actionType == SlideActionType.primary
? 'Dismiss Archive'
: 'Dismiss Delete');
setState(() {
items.removeAt(index);
});
},
),
actionPane: _getActionPane(item.index),
actionExtentRatio: 0.25,
child: direction == Axis.horizontal
? VerticalListItem(items[index])
: HorizontalListItem(items[index]),
actions: [
IconSlideAction(
caption: 'Archive',
color: Colors.blue,
icon: Icons.archive,
onTap: () => _showSnackBar(context, 'Archive'),
),
IconSlideAction(
caption: 'Share',
color: Colors.indigo,
icon: Icons.share,
onTap: () => _showSnackBar(context, 'Share'),
),
],
secondaryActions: [
Container(
height: 800,
color: Colors.green,
child: Text('a'),
),
IconSlideAction(
caption: 'More',
color: Colors.grey.shade200,
icon: Icons.more_horiz,
onTap: () => _showSnackBar(context, 'More'),
closeOnTap: false,
),
IconSlideAction(
caption: 'Delete',
color: Colors.red,
icon: Icons.delete,
onTap: () => _showSnackBar(context, 'Delete'),
),
],
);
}
Widget _getSlidableWithDelegates(
BuildContext context, int index, Axis direction) {
final _HomeItem item = items[index];
return Slidable.builder(
key: Key(item.title),
controller: slidableController,
direction: direction,
dismissal: SlidableDismissal(
child: SlidableDrawerDismissal(),
closeOnCanceled: true,
onWillDismiss: (item.index != 10)
? null
: (actionType) {
return showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('Delete'),
content: Text('Item will be deleted'),
actions: [
FlatButton(
child: Text('Cancel'),
onPressed: () => Navigator.of(context).pop(false),
),
FlatButton(
child: Text('Ok'),
onPressed: () => Navigator.of(context).pop(true),
),
],
);
},
);
},
onDismissed: (actionType) {
_showSnackBar(
context,
actionType == SlideActionType.primary
? 'Dismiss Archive'
: 'Dismiss Delete');
setState(() {
items.removeAt(index);
});
},
),
actionPane: _getActionPane(item.index),
actionExtentRatio: 0.25,
child: direction == Axis.horizontal
? VerticalListItem(items[index])
: HorizontalListItem(items[index]),
actionDelegate: SlideActionBuilderDelegate(
actionCount: 2,
builder: (context, index, animation, renderingMode) {
if (index == 0) {
return IconSlideAction(
caption: 'Archive',
color: renderingMode == SlidableRenderingMode.slide
? Colors.blue.withOpacity(animation.value)
: (renderingMode == SlidableRenderingMode.dismiss
? Colors.blue
: Colors.green),
icon: Icons.archive,
onTap: () async {
var state = Slidable.of(context);
var dismiss = await showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('Delete'),
content: Text('Item will be deleted'),
actions: [
FlatButton(
child: Text('Cancel'),
onPressed: () => Navigator.of(context).pop(false),
),
FlatButton(
child: Text('Ok'),
onPressed: () => Navigator.of(context).pop(true),
),
],
);
},
);
if (dismiss) {
state.dismiss();
}
},
);
} else {
return IconSlideAction(
caption: 'Share',
color: renderingMode == SlidableRenderingMode.slide
? Colors.indigo.withOpacity(animation.value)
: Colors.indigo,
icon: Icons.share,
onTap: () => _showSnackBar(context, 'Share'),
);
}
}),
secondaryActionDelegate: SlideActionBuilderDelegate(
actionCount: 2,
builder: (context, index, animation, renderingMode) {
if (index == 0) {
return IconSlideAction(
caption: 'More',
color: renderingMode == SlidableRenderingMode.slide
? Colors.grey.shade200.withOpacity(animation.value)
: Colors.grey.shade200,
icon: Icons.more_horiz,
onTap: () => _showSnackBar(context, 'More'),
closeOnTap: false,
);
} else {
return IconSlideAction(
caption: 'Delete',
color: renderingMode == SlidableRenderingMode.slide
? Colors.red.withOpacity(animation.value)
: Colors.red,
icon: Icons.delete,
onTap: () => _showSnackBar(context, 'Delete'),
);
}
}),
);
}
static Widget _getActionPane(int index) {
switch (index % 4) {
case 0:
return SlidableBehindActionPane();
case 1:
return SlidableStrechActionPane();
case 2:
return SlidableScrollActionPane();
case 3:
return SlidableDrawerActionPane();
default:
return null;
}
}
static Color _getAvatarColor(int index) {
switch (index % 4) {
case 0:
return Colors.red;
case 1:
return Colors.green;
case 2:
return Colors.blue;
case 3:
return Colors.indigoAccent;
default:
return null;
}
}
static String _getSubtitle(int index) {
switch (index % 4) {
case 0:
return ' ';
case 1:
return ' ';
case 2:
return ' ';
case 3:
return ' ';
default:
return null;
}
}
void _showSnackBar(BuildContext context, String text) {
Scaffold.of(context).showSnackBar(SnackBar(content: Text(text)));
}
}
class HorizontalListItem extends StatelessWidget {
HorizontalListItem(this.item);
final _HomeItem item;
@override
Widget build(BuildContext context) {
return Container(
color: Colors.white,
width: 160.0,
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
Expanded(
child: CircleAvatar(
backgroundColor: item.color,
child: Text('${item.index}'),
foregroundColor: Colors.white,
),
),
Expanded(
child: Center(
child: Text(
item.subtitle,
),
),
),
],
),
);
}
}
class VerticalListItem extends StatelessWidget {
VerticalListItem(this.item);
final _HomeItem item;
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () =>
Slidable.of(context)?.renderingMode == SlidableRenderingMode.none
? Slidable.of(context)?.open()
: Slidable.of(context)?.close(),
child: Container(
color: Colors.white,
child: ListTile(
leading: CircleAvatar(
backgroundColor: item.color,
child: Text('${item.index}'),
foregroundColor: Colors.white,
),
title: Text(item.title),
subtitle: Text(item.subtitle),
),
),
);
}
}
class _HomeItem {
const _HomeItem(
this.index,
this.title,
this.subtitle,
this.color,
);
final int index;
final String title;
final String subtitle;
final Color color;
}
创建主页:
使用StatefulWidget为应用程序设置主页,该主页将来会保存可以向任一方向滑动以执行分配给它们的任务的图块,如下所示:
Dart
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State {
SlidableController slidableController;
final List<_HomeItem> items = List.generate(
20,
(i) => _HomeItem(
i,
'Slide Bar $i',
_getSubtitle(i),
_getAvatarColor(i),
),
);
设计幻灯片:
使用SlidableController为应用程序设置幻灯片。它可以通过使用Slidable Constructor或Slidable.builder Constructor 来完成。我们正在构建的应用程序有 4 个基本组件:
- 滑动动作
- 幻灯片操作面板小部件
- 滑动操作范围和项目范围之间的范围比率。
- 一个孩子
要设计可滑动使用以下内容:
Dart
Slidable(
actionPane: SlidableDrawerActionPane(),
actionExtentRatio: 0.25,
child: Container(
color: Colors.white,
child: ListTile(
leading: CircleAvatar(
backgroundColor: Colors.indigoAccent,
child: Text('$3'),
foregroundColor: Colors.white,
),
title: Text('Tile $3'),
subtitle: Text('SlidableDrawerDelegate'),
),
),
actions: [
IconSlideAction(
caption: 'Archive',
color: Colors.blue,
icon: Icons.archive,
onTap: () => _showSnackBar('Archive'),
),
IconSlideAction(
caption: 'Share',
color: Colors.indigo,
icon: Icons.share,
onTap: () => _showSnackBar('Share'),
),
],
secondaryActions: [
IconSlideAction(
caption: 'More',
color: Colors.black45,
icon: Icons.more_horiz,
onTap: () => _showSnackBar('More'),
),
IconSlideAction(
caption: 'Delete',
color: Colors.red,
icon: Icons.delete,
onTap: () => _showSnackBar('Delete'),
),
],
);
分配动作:
当滑动幻灯片时,会根据幻灯片的方向出现一个FloatingActionButton 。在这两种情况下,每次滑动都会分配两个动作,如下所示:
- 对于从左到右的幻灯片:
- 存档磁贴
- 共享磁贴
- 对于从右到左的幻灯片:
- 删除磁贴
- 更多的
为简单起见,我们将仅将操作分配给存档磁贴按钮和删除磁贴按钮,这将分别存档和删除磁贴。为此,请使用以下命令:
Dart
@protected
void initState() {
slidableController = SlidableController(
onSlideAnimationChanged: handleSlideAnimationChanged,
onSlideIsOpenChanged: handleSlideIsOpenChanged,
);
super.initState();
}
Animation _rotationAnimation;
Color _fabColor = Colors.blue;
void handleSlideAnimationChanged(Animation slideAnimation) {
setState(() {
_rotationAnimation = slideAnimation;
});
}
void handleSlideIsOpenChanged(bool isOpen) {
setState(() {
_fabColor = isOpen ? Colors.green : Colors.blue;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
backgroundColor: Colors.green,
),
body: Center(
child: OrientationBuilder(
builder: (context, orientation) => _buildList(
context,
orientation == Orientation.portrait
? Axis.vertical
: Axis.horizontal),
),
),
floatingActionButton: FloatingActionButton(
backgroundColor: _fabColor,
onPressed: null,
child: _rotationAnimation == null
? Icon(Icons.add)
: RotationTransition(
turns: _rotationAnimation,
child: Icon(Icons.add),
),
),
);
}
Widget _buildList(BuildContext context, Axis direction) {
return ListView.builder(
scrollDirection: direction,
itemBuilder: (context, index) {
final Axis slidableDirection =
direction == Axis.horizontal ? Axis.vertical : Axis.horizontal;
var item = items[index];
if (item.index < 8) {
return _getSlidableWithLists(context, index, slidableDirection);
} else {
return _getSlidableWithDelegates(context, index, slidableDirection);
}
},
itemCount: items.length,
);
}
Widget _getSlidableWithLists(
BuildContext context, int index, Axis direction) {
final _HomeItem item = items[index];
return Slidable(
key: Key(item.title),
controller: slidableController,
direction: direction,
dismissal: SlidableDismissal(
child: SlidableDrawerDismissal(),
onDismissed: (actionType) {
_showSnackBar(
context,
actionType == SlideActionType.primary
? 'Dismiss Archive'
: 'Dismiss Delete');
setState(() {
items.removeAt(index);
});
},
),
actionPane: _getActionPane(item.index),
actionExtentRatio: 0.25,
child: direction == Axis.horizontal
? VerticalListItem(items[index])
: HorizontalListItem(items[index]),
actions: [
IconSlideAction(
caption: 'Archive',
color: Colors.blue,
icon: Icons.archive,
onTap: () => _showSnackBar(context, 'Archive'),
),
IconSlideAction(
caption: 'Share',
color: Colors.indigo,
icon: Icons.share,
onTap: () => _showSnackBar(context, 'Share'),
),
],
secondaryActions: [
Container(
height: 800,
color: Colors.green,
child: Text('a'),
),
IconSlideAction(
caption: 'More',
color: Colors.grey.shade200,
icon: Icons.more_horiz,
onTap: () => _showSnackBar(context, 'More'),
closeOnTap: false,
),
IconSlideAction(
caption: 'Delete',
color: Colors.red,
icon: Icons.delete,
onTap: () => _showSnackBar(context, 'Delete'),
),
],
);
}
完整的源代码:
Dart
import 'package:flutter/material.dart';
import 'package:flutter_slidable/flutter_slidable.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Slidable ',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'GeeksForGeeks'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State {
SlidableController slidableController;
final List<_HomeItem> items = List.generate(
20,
(i) => _HomeItem(
i,
'Slide Bar $i',
_getSubtitle(i),
_getAvatarColor(i),
),
);
@protected
void initState() {
slidableController = SlidableController(
onSlideAnimationChanged: handleSlideAnimationChanged,
onSlideIsOpenChanged: handleSlideIsOpenChanged,
);
super.initState();
}
Animation _rotationAnimation;
Color _fabColor = Colors.blue;
void handleSlideAnimationChanged(Animation slideAnimation) {
setState(() {
_rotationAnimation = slideAnimation;
});
}
void handleSlideIsOpenChanged(bool isOpen) {
setState(() {
_fabColor = isOpen ? Colors.green : Colors.blue;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
backgroundColor: Colors.green,
),
body: Center(
child: OrientationBuilder(
builder: (context, orientation) => _buildList(
context,
orientation == Orientation.portrait
? Axis.vertical
: Axis.horizontal),
),
),
floatingActionButton: FloatingActionButton(
backgroundColor: _fabColor,
onPressed: null,
child: _rotationAnimation == null
? Icon(Icons.add)
: RotationTransition(
turns: _rotationAnimation,
child: Icon(Icons.add),
),
),
);
}
Widget _buildList(BuildContext context, Axis direction) {
return ListView.builder(
scrollDirection: direction,
itemBuilder: (context, index) {
final Axis slidableDirection =
direction == Axis.horizontal ? Axis.vertical : Axis.horizontal;
var item = items[index];
if (item.index < 8) {
return _getSlidableWithLists(context, index, slidableDirection);
} else {
return _getSlidableWithDelegates(context, index, slidableDirection);
}
},
itemCount: items.length,
);
}
Widget _getSlidableWithLists(
BuildContext context, int index, Axis direction) {
final _HomeItem item = items[index];
//final int t = index;
return Slidable(
key: Key(item.title),
controller: slidableController,
direction: direction,
dismissal: SlidableDismissal(
child: SlidableDrawerDismissal(),
onDismissed: (actionType) {
_showSnackBar(
context,
actionType == SlideActionType.primary
? 'Dismiss Archive'
: 'Dismiss Delete');
setState(() {
items.removeAt(index);
});
},
),
actionPane: _getActionPane(item.index),
actionExtentRatio: 0.25,
child: direction == Axis.horizontal
? VerticalListItem(items[index])
: HorizontalListItem(items[index]),
actions: [
IconSlideAction(
caption: 'Archive',
color: Colors.blue,
icon: Icons.archive,
onTap: () => _showSnackBar(context, 'Archive'),
),
IconSlideAction(
caption: 'Share',
color: Colors.indigo,
icon: Icons.share,
onTap: () => _showSnackBar(context, 'Share'),
),
],
secondaryActions: [
Container(
height: 800,
color: Colors.green,
child: Text('a'),
),
IconSlideAction(
caption: 'More',
color: Colors.grey.shade200,
icon: Icons.more_horiz,
onTap: () => _showSnackBar(context, 'More'),
closeOnTap: false,
),
IconSlideAction(
caption: 'Delete',
color: Colors.red,
icon: Icons.delete,
onTap: () => _showSnackBar(context, 'Delete'),
),
],
);
}
Widget _getSlidableWithDelegates(
BuildContext context, int index, Axis direction) {
final _HomeItem item = items[index];
return Slidable.builder(
key: Key(item.title),
controller: slidableController,
direction: direction,
dismissal: SlidableDismissal(
child: SlidableDrawerDismissal(),
closeOnCanceled: true,
onWillDismiss: (item.index != 10)
? null
: (actionType) {
return showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('Delete'),
content: Text('Item will be deleted'),
actions: [
FlatButton(
child: Text('Cancel'),
onPressed: () => Navigator.of(context).pop(false),
),
FlatButton(
child: Text('Ok'),
onPressed: () => Navigator.of(context).pop(true),
),
],
);
},
);
},
onDismissed: (actionType) {
_showSnackBar(
context,
actionType == SlideActionType.primary
? 'Dismiss Archive'
: 'Dismiss Delete');
setState(() {
items.removeAt(index);
});
},
),
actionPane: _getActionPane(item.index),
actionExtentRatio: 0.25,
child: direction == Axis.horizontal
? VerticalListItem(items[index])
: HorizontalListItem(items[index]),
actionDelegate: SlideActionBuilderDelegate(
actionCount: 2,
builder: (context, index, animation, renderingMode) {
if (index == 0) {
return IconSlideAction(
caption: 'Archive',
color: renderingMode == SlidableRenderingMode.slide
? Colors.blue.withOpacity(animation.value)
: (renderingMode == SlidableRenderingMode.dismiss
? Colors.blue
: Colors.green),
icon: Icons.archive,
onTap: () async {
var state = Slidable.of(context);
var dismiss = await showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('Delete'),
content: Text('Item will be deleted'),
actions: [
FlatButton(
child: Text('Cancel'),
onPressed: () => Navigator.of(context).pop(false),
),
FlatButton(
child: Text('Ok'),
onPressed: () => Navigator.of(context).pop(true),
),
],
);
},
);
if (dismiss) {
state.dismiss();
}
},
);
} else {
return IconSlideAction(
caption: 'Share',
color: renderingMode == SlidableRenderingMode.slide
? Colors.indigo.withOpacity(animation.value)
: Colors.indigo,
icon: Icons.share,
onTap: () => _showSnackBar(context, 'Share'),
);
}
}),
secondaryActionDelegate: SlideActionBuilderDelegate(
actionCount: 2,
builder: (context, index, animation, renderingMode) {
if (index == 0) {
return IconSlideAction(
caption: 'More',
color: renderingMode == SlidableRenderingMode.slide
? Colors.grey.shade200.withOpacity(animation.value)
: Colors.grey.shade200,
icon: Icons.more_horiz,
onTap: () => _showSnackBar(context, 'More'),
closeOnTap: false,
);
} else {
return IconSlideAction(
caption: 'Delete',
color: renderingMode == SlidableRenderingMode.slide
? Colors.red.withOpacity(animation.value)
: Colors.red,
icon: Icons.delete,
onTap: () => _showSnackBar(context, 'Delete'),
);
}
}),
);
}
static Widget _getActionPane(int index) {
switch (index % 4) {
case 0:
return SlidableBehindActionPane();
case 1:
return SlidableStrechActionPane();
case 2:
return SlidableScrollActionPane();
case 3:
return SlidableDrawerActionPane();
default:
return null;
}
}
static Color _getAvatarColor(int index) {
switch (index % 4) {
case 0:
return Colors.red;
case 1:
return Colors.green;
case 2:
return Colors.blue;
case 3:
return Colors.indigoAccent;
default:
return null;
}
}
static String _getSubtitle(int index) {
switch (index % 4) {
case 0:
return ' ';
case 1:
return ' ';
case 2:
return ' ';
case 3:
return ' ';
default:
return null;
}
}
void _showSnackBar(BuildContext context, String text) {
Scaffold.of(context).showSnackBar(SnackBar(content: Text(text)));
}
}
class HorizontalListItem extends StatelessWidget {
HorizontalListItem(this.item);
final _HomeItem item;
@override
Widget build(BuildContext context) {
return Container(
color: Colors.white,
width: 160.0,
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
Expanded(
child: CircleAvatar(
backgroundColor: item.color,
child: Text('${item.index}'),
foregroundColor: Colors.white,
),
),
Expanded(
child: Center(
child: Text(
item.subtitle,
),
),
),
],
),
);
}
}
class VerticalListItem extends StatelessWidget {
VerticalListItem(this.item);
final _HomeItem item;
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () =>
Slidable.of(context)?.renderingMode == SlidableRenderingMode.none
? Slidable.of(context)?.open()
: Slidable.of(context)?.close(),
child: Container(
color: Colors.white,
child: ListTile(
leading: CircleAvatar(
backgroundColor: item.color,
child: Text('${item.index}'),
foregroundColor: Colors.white,
),
title: Text(item.title),
subtitle: Text(item.subtitle),
),
),
);
}
}
class _HomeItem {
const _HomeItem(
this.index,
this.title,
this.subtitle,
this.color,
);
final int index;
final String title;
final String subtitle;
final Color color;
}
输出: