咱們不只但願向用戶展現信息,還但願咱們的用戶與咱們的應用進行互動! 那麼,咱們如何迴應基本操做,如點擊和拖動? 咱們將使用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')), ); }, ), ), ); } }