咱们不只但愿向用户展现信息,还但愿咱们的用户与咱们的应用进行互动! 那么,咱们如何回应基本操做,如点击和拖动? 咱们将使用GestureDetector部件!html
假设咱们想要制做一个自定义按钮,当点击时显示snackbar。 咱们如何解决这个问题?java
路线数据库
// 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'), ), );
笔记app
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'), ), ); } }
在设计应遵循材质设计指南的应用程序时,咱们但愿在点击时将涟漪动画添加到部件。less
Flutter提供InkWell部件来达到这个效果。ide
路线函数
// 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部件使这项任务变得简单。ui
路线this
这个配方的第一步是建立一个咱们能够滑动的项目列表。 有关如何建立列表的更多详细说明,请按照使用长列表配方进行操做。
建立一个数据源
在咱们的例子中,咱们须要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]}')); }, );
如今咱们正在显示项目列表,咱们但愿让用户可以将每一个项目从列表中移除!
用户将该项目删除后,咱们须要运行一些代码以从列表中删除该项目并显示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')), );
就目前来看,咱们的应用程序将容许用户从列表中滑动项目,但它可能不会让他们看到他们作什么时会发生什么。 为了提供咱们正在移除项目的提示,咱们将在屏幕上滑动该项目时显示“划动消除”指示符。 在这种状况下,红色背景!
为此,咱们将为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')), ); }, ), ), ); } }