說明:
Flutter的手勢系統分為兩層,第一層是觸控原事件(指標),有相應的四種事件型別:
第二層就是我們可以檢測到的手勢,主要分為三大類,包括輕擊、拖動和縮放。
下面,我們來學習GestureDetector(進行手勢檢測)、Dismissible(實現滑動刪除)
手勢事件以及描述表:
事件名 | 描述 |
---|---|
onTapDown | 點選螢幕立即觸發此方法 |
onTapUp | 手指離開螢幕 |
onTap | 點選螢幕 |
onTapCancel | 此次點選事件結束,onTapDown不會再產生點選事件 |
onDoubleTap | 使用者快速連續兩次在同一位置點選螢幕 |
onLongPress | 長時間保持與相同位置的螢幕接觸 |
onVerticalDragStart | 與螢幕接觸,可能會開始垂直移動 |
onVerticalDragUpdate | 與螢幕接觸並垂直移動的指標在垂直方向上移動 |
onVerticalDragEnd | 之前與螢幕接觸並垂直移動的指標不再與螢幕接觸,並且在停留接觸控螢幕幕時以特定的速度移動垂直拖動 |
onHorizontalDragStart | 與螢幕接觸,可能開始水平移動 |
onHorizontalDragUpdate | 與螢幕接觸並水平移動的指標在水平方向上移動 |
onHorizontalDragEnd | 先前與螢幕接觸並且水平移動的指標不再與螢幕接觸,並且當它停止接觸控螢幕幕時以特定速度移動水平拖動 |
例子:製作一個自定義的按鈕,當點選時顯示文字「你已按下」
程式碼:
main.dart
import 'package:flutter/material.dart';
import 'package:route_page/route/page_jumps.dart';
import 'package:route_page/route/return_message.dart';
import 'package:route_page/route/send_message.dart';
import 'gesture/test_button.dart';
void main() {
runApp(
// new MaterialApp(
// title: "導航頁面範例",
// home: new FirstScreen(),
// )
// new MaterialApp(
// title: "傳遞資料範例",
// home: new ProductList(
// products:
// new List.generate(20, (i) => new Product('商品 $i', "這是一個商品詳情 $i"))),
// )
// new MaterialApp(
// title: '頁面跳轉發、返回資料',
// home: new FirstPage(),
// )
new MaterialApp(
title: '頁面跳轉發、返回資料',
home: new MyButton(),
)
);
}
test_button.dart
import 'package:flutter/material.dart';
class MyButton extends StatelessWidget{
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text("按下處理Demo"),
),
// 注意:在同一個函數中實際建立了Scaffold時,該build函數的context引數不能用於查詢Scaffold
// (因為它在小部件樹返回的小部件上方)。在這種情況下,可以使用帶有Builder來提供一個行的作用域,該作用域具有位於Scaffold下方的BuildContext.
body: Builder(
builder: (BuildContext context){
return new Center(
// 一定要把被觸控的元件放在GestureDetector中
child: GestureDetector(
onTap: (){
// 底部資訊揭示
final snackBar = new SnackBar(content: new Text("你已按下按鈕"));
Scaffold.of(context).showSnackBar(snackBar);
},
// 容器接收觸控動作
child: new Container(
child: new Text("測試按鈕"),
padding: EdgeInsets.all(12.0),
decoration: BoxDecoration(
color: Theme.of(context).buttonColor,
borderRadius: new BorderRadius.circular(10.0)
),
),
),
);
},
)
);
}
}
Dismissible元件屬性及描述表
屬性名 | 型別 | 說明 |
---|---|---|
onDismissed | DismissDirectionCallback | 當包裹的元件消失後回撥的函數 |
movementDuration | Duration | 定義元件訊息的時長 |
onResize | VoidCallback | 元件大小改變時回撥的函數 |
resizeDuration | Duration | 元件大小改變時長 |
child | Widget | 元件包裹的子元素,即被隱藏的對像 |
例子:實現滑動列表中的某一項資料,就可以刪除的效果
main.dart
iimport 'package:flutter/material.dart';
import 'package:route_page/route/page_jumps.dart';
import 'package:route_page/route/return_message.dart';
import 'package:route_page/route/send_message.dart';
import 'gesture/dismissible.dart';
import 'gesture/test_button.dart';
void main() {
runApp(
// new MaterialApp(
// title: "導航頁面範例",
// home: new FirstScreen(),
// )
// new MaterialApp(
// title: "傳遞資料範例",
// home: new ProductList(
// products:
// new List.generate(20, (i) => new Product('商品 $i', "這是一個商品詳情 $i"))),
// )
// new MaterialApp(
// title: '頁面跳轉發、返回資料',
// home: new FirstPage(),
// )
// new MaterialApp(
// title: '頁面跳轉發、返回資料',
// home: new MyButton(),
// )
new MaterialApp(
title: ' 滑動刪除範例',
home: new MyApp(),
)
);
}
dismissible.dart
import 'package:flutter/material.dart';
class MyApp extends StatelessWidget{
List<String> items = new List<String>.generate(30, (i) => "列表項 ${i+1}");
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text("滑動刪除範例"),
),
// 使用ListView.builder生成列表,將列表中的每一項子項(ListTile)包裝在Dismissible中;
// 在onDismissed執行真正的刪除操作
body: new ListView.builder(
itemCount: items.length,//決定itemBuilder回撥函數的次數
itemBuilder: (context,index){
final item = items[index];
// 對需要實現滑動清除的Widget包裝在child中
return new Dismissible(
key: new Key(item),//key是widget的唯一標示,因為有了key,widget tree才知道我們刪除了什麼widget
// 可以被刪除的元件
child: new ListTile(title: new Text('$item'),),
// 完成清除後,進行的操作
onDismissed: (direction){
// 刪除後重新整理列表,已到達真正的刪除
items.removeAt(index);
Scaffold.of(context).showSnackBar(new SnackBar(content: new Text("$item 被刪除來")));
},
);
},
)
);
}
}