处理点击
我们不仅希望向用户展示信息,还希望我们的用户与我们的应用进行互动! 那么,我们如何回应基本操作,如点击和拖动? 我们将使用GestureDetector部件!
假设我们想要制作一个自定义按钮,当点击时显示snackbar。 我们如何解决这个问题?
路线
- 创建按钮
- 用onTap回调将其包装在GestureDetector中
// Our GestureDetector wraps our button
new GestureDetector(
// When the child is tapped, show a snackbar
onTap: () {
final snackBar = new SnackBar(content: new Text("Tap"));
Scaffold.of(context).showSnackBar(snackBar);
},
// Our Custom Button!
child: new Container(
padding: new EdgeInsets.all(12.0),
decoration: new BoxDecoration(
color: Theme.of(context).buttonColor,
borderRadius: new BorderRadius.circular(8.0),
),
child: new Text('My Button'),
),
);
笔记
- 如果您想将材质涟漪效果添加到按钮中,请参阅“添加材质涟漪”配方。
- 虽然我们已经创建了一个自定义按钮来演示这些概念,但Flutter包括一些开箱即用的按钮:RaisedButton,FlatButton和CupertinoButton
完整例子
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
final title = 'Gesture Demo';
return new MaterialApp(
title: title,
home: new MyHomePage(title: title),
);
}
}
class MyHomePage extends StatelessWidget {
final String title;
MyHomePage({Key key, this.title}) : super(key: key);
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(title),
),
body: new Center(child: new MyButton()),
);
}
}
class MyButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
// Our GestureDetector wraps our button
return new GestureDetector(
// When the child is tapped, show a snackbar
onTap: () {
final snackBar = new SnackBar(content: new Text("Tap"));
Scaffold.of(context).showSnackBar(snackBar);
},
// Our Custom Button!
child: new Container(
padding: new EdgeInsets.all(12.0),
decoration: new BoxDecoration(
color: Theme.of(context).buttonColor,
borderRadius: new BorderRadius.circular(8.0),
),
child: new Text('My Button'),
),
);
}
}
添加材质涟漪效果
在设计应遵循材质设计指南的应用程序时,我们希望在点击时将涟漪动画添加到部件。
Flutter提供InkWell部件来达到这个效果。
路线
- 创建一个我们想要点击的部件
- 将其包装在InkWell部件中以管理点击回调和涟漪动画
// The InkWell Wraps our custom flat button Widget
new InkWell(
// When the user taps the button, show a snackbar
onTap: () {
Scaffold.of(context).showSnackBar(new SnackBar(
content: new Text('Tap'),
));
},
child: new Container(
padding: new EdgeInsets.all(12.0),
child: new Text('Flat Button'),
),
);
完整例子
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
final title = 'InkWell Demo';
return new MaterialApp(
title: title,
home: new MyHomePage(title: title),
);
}
}
class MyHomePage extends StatelessWidget {
final String title;
MyHomePage({Key key, this.title}) : super(key: key);
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(title),
),
body: new Center(child: new MyButton()),
);
}
}
class MyButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
// The InkWell Wraps our custom flat button Widget
return new InkWell(
// When the user taps the button, show a snackbar
onTap: () {
Scaffold.of(context).showSnackBar(new SnackBar(
content: new Text('Tap'),
));
},
child: new Container(
padding: new EdgeInsets.all(12.0),
child: new Text('Flat Button'),
),
);
}
}
实现划动消除
“划动消除”模式在很多移动应用中很常见。 例如,如果我们正在编写一个电子邮件应用程序,我们可能希望允许我们的用户在列表中划离邮件消息。 当他们这样做时,我们需要将该项目从收件箱移至垃圾箱。
Flutter通过提供Dismissible部件使这项任务变得简单。
路线
- 创建条目列表
- 将每个项目包裹在Dismissible部件中
- 提供“向后消除”指标
1.创建条目列表
这个配方的第一步是创建一个我们可以滑动的项目列表。 有关如何创建列表的更多详细说明,请按照使用长列表配方进行操作。
创建一个数据源
在我们的例子中,我们需要20个样品条目。 为了简单起见,我们将生成一个字符串列表。
final items = new List<String>.generate(20, (i) => "Item ${i + 1}");
将数据源转换为List
首先,我们将简单地在屏幕上的列表中显示每个条目。 用户将无法用这些物品轻轻一扫!
new ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return new ListTile(title: new Text('${items[index]}'));
},
);
2.将每个项目包裹在Dismissible部件中
现在我们正在显示项目列表,我们希望让用户能够将每个项目从列表中移除!
用户将该项目删除后,我们需要运行一些代码以从列表中删除该项目并显示Snackbar。 在真实的应用程序中,您可能需要执行更复杂的逻辑,例如从Web服务或数据库中删除项目。
这是Dismissible部件发挥作用的地方! 在我们的例子中,我们将更新我们的itemBuilder函数以返回一个Dismissible部件。
new Dismissible(
// Each Dismissible must contain a Key. Keys allow Flutter to
// uniquely identify Widgets.
key: new Key(item),
// We also need to provide a function that will tell our app
// what to do after an item has been swiped away.
onDismissed: (direction) {
// Remove the item from our data source
items.removeAt(index);
// Show a snackbar! This snackbar could also contain "Undo" actions.
Scaffold.of(context).showSnackBar(
new SnackBar(content: new Text("$item dismissed")));
},
child: new ListTile(title: new Text('$item')),
);
3.提供“向后消除”指标
就目前来看,我们的应用程序将允许用户从列表中滑动项目,但它可能不会让他们看到他们做什么时会发生什么。 为了提供我们正在移除项目的提示,我们将在屏幕上滑动该项目时显示“划动消除”指示符。 在这种情况下,红色背景!
为此,我们将为Dismissible提供background参数。
new Dismissible(
// Show a red background as the item is swiped away
background: new Container(color: Colors.red),
key: new Key(item),
onDismissed: (direction) {
items.removeAt(index);
Scaffold.of(context).showSnackBar(
new SnackBar(content: new Text("$item dismissed")));
},
child: new ListTile(title: new Text('$item')),
);
完整例子
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
void main() {
runApp(new MyApp(
items: new List<String>.generate(20, (i) => "Item ${i + 1}"),
));
}
class MyApp extends StatelessWidget {
final List<String> items;
MyApp({Key key, @required this.items}) : super(key: key);
@override
Widget build(BuildContext context) {
final title = 'Dismissing Items';
return new MaterialApp(
title: title,
home: new Scaffold(
appBar: new AppBar(
title: new Text(title),
),
body: new ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
final item = items[index];
return new Dismissible(
// Each Dismissible must contain a Key. Keys allow Flutter to
// uniquely identify Widgets.
key: new Key(item),
// We also need to provide a function that will tell our app
// what to do after an item has been swiped away.
onDismissed: (direction) {
items.removeAt(index);
Scaffold.of(context).showSnackBar(
new SnackBar(content: new Text("$item dismissed")));
},
// Show a red background as the item is swiped away
background: new Container(color: Colors.red),
child: new ListTile(title: new Text('$item')),
);
},
),
),
);
}
}