Flutter のウィジェットにはタップ時の処理などが予め用意されている場合がありますが、用意されていない場合や、ドラッグ/ピンチ/回転/指圧(筆圧?)など様々なジェスチャー操作に対応したい場合、GestureDetector ウィジェットで大体のジェスチャーに対応することができます。
今回はこのウィジェットについてまとめてみました。
※最後にドラッグと拡大縮小回転のサンプルコードを載せておきます。
GestureDetector
タップやドラッグなどを処理する場合は GestureDetector ウィジェットを使います。
GestureDetector(
onTap: () {
print('onTap');
},
child: Container(
color: Colors.blue,
width: 100,
height: 100,
),
},
GestureDetector で定義されている各ジェスチャーについて以下に記載します。
タップ
普通のタップです。
onTap: () {
print('onTap');
},
onTapDown: (TapDownDetails details) {
print('onTapDown - ${details.toString()}');
},
onTapUp: (TapUpDetails details) {
print('onTapUp - ${details.toString()}');
},
onTapCancel: () {
print('onTapCancel');
},
ダブルタップ
ダブルタップです。
onDoubleTap: () {
print('onDoubleTap');
},
ロングプレス
いわゆる長押しです。
onLongPress: () {
print('onLongPress');
},
onLongPressUp: () {
print('onLongPressUp');
},
onLongPressStart: (LongPressStartDetails details) {
print('onLongPressStart - ${details.toString()}');
},
onLongPressEnd: (LongPressEndDetails details) {
print('onLongPressEnd - ${details.toString()}');
},
// 長押し中の移動ポジションも取得できます
onLongPressMoveUpdate: (LongPressMoveUpdateDetails details) {
print('onLongPressMoveUpdate - ${details.toString()}');
// details.globalPosition; 移動中のグローバルポジション
},
垂直方向のドラッグ
垂直方向のドラッグ操作です。(水平方向ならこのジェスチャーはキャンセルされます)
// ドラッグ中に呼ばれる
onVerticalDragUpdate: (DragUpdateDetails details) {
print('onVerticalDragUpdate - ${details.toString()}');
// details.globalPosition; //グローバル座標
// details.localPosition; //ローカル座標
// details.delta; //前回からの移動量
},
onVerticalDragDown: (DragDownDetails details) {
print('onVerticalDragDown - ${details.toString()}');
},
onVerticalDragStart: (DragStartDetails details) {
print('onVerticalDragStart - ${details.toString()}');
},
onVerticalDragEnd: (DragEndDetails details) {
print('onVerticalDragEnd - ${details.toString()}');
},
onVerticalDragCancel: () {
print('onVerticalDragCancel');
},
水平方向のドラッグ
水平方向のドラッグ操作です。(垂直方向ならこのジェスチャーはキャンセルされます)
// ドラッグ中に呼ばれる
onHorizontalDragUpdate: (DragUpdateDetails details) {
print('onHorizontalDragUpdate - ${details.toString()}');
// details.globalPosition; //グローバル座標
// details.localPosition; //ローカル座標
// details.delta; //前回からの移動量
},
onHorizontalDragDown: (DragDownDetails details) {
print('onHorizontalDragDown - ${details.toString()}');
},
onHorizontalDragStart: (DragStartDetails details) {
print('onHorizontalDragStart - ${details.toString()}');
},
onHorizontalDragEnd: (DragEndDetails details) {
print('onHorizontalDragEnd - ${details.toString()}');
},
onHorizontalDragCancel: () {
print('onHorizontalDragCancel');
},
パン(ドラッグ操作)
垂直や水平に依らないドラッグ操作です。(XY座標でグリグリ動かしたい時はこれ)
// ドラッグ中に呼ばれる
onPanUpdate: (DragUpdateDetails details) {
print('onPanUpdate - ${details.toString()}');
// details.globalPosition; //グローバル座標
// details.localPosition; //ローカル座標
// details.delta; //前回からの移動量
},
onPanDown: (DragDownDetails details) {
print('onPanDown - ${details.toString()}');
},
onPanStart: (DragStartDetails details) {
print('onPanStart - ${details.toString()}');
},
onPanEnd: (DragEndDetails details) {
print('onPanEnd - ${details.toString()}');
},
onPanCancel: () {
print('onPanCancel');
},
スケール(ピンチ操作)
いわゆる2本指のピンチイン/アウト(と回転)の操作です。
// スケール操作時に呼ばれる
onScaleUpdate: (ScaleUpdateDetails details) {
print('onScaleUpdate - ${details.toString()}');
// details.scale; //スケール
// details.rotation; //回転
},
onScaleStart: (ScaleStartDetails details) {
print('onScaleStart - ${details.toString()}');
},
onScaleEnd: (ScaleEndDetails details) {
print('onScaleEnd - ${details.toString()}');
},
フォースプレス(押し込みの強さ)
タップ中の押し込みの強さです。iOSで言うところの3D Touchですね。
// フォースプレス中に呼ばれる
onForcePressUpdate: (ForcePressDetails details) {
print('onForcePressUpdate - ${details.toString()}');
// details.pressure; //押し込みの強さ
},
onForcePressStart: (ForcePressDetails details) {
print('onForcePressStart - ${details.toString()}');
},
onForcePressEnd: (ForcePressDetails details) {
print('onForcePressEnd - ${details.toString()}');
},
// 押し込みの強さが最大になった時に呼ばれる
onForcePressPeak: (ForcePressDetails details) {
print('onForcePressPeak - ${details.toString()}');
},
サンプルコード
ドラッグ操作(Pan)と拡大縮小回転(Scale)のサンプルコードです。

緑のボックスはドラッグで移動、オレンジのボックスはピンチ操作で回転/拡大/縮小できます。
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
// MyAppウィジェットクラス
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(title: 'GestureDetector'),
);
}
}
// MyHomePageウィジェットクラス
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
// MyHomePageステートクラス
class _MyHomePageState extends State<MyHomePage> {
Offset _offset = Offset(10,10); //Panドラッグ時のポジション
double _radians = 0.0; //Scaleの回転値
double _scale = 1.0; //Scaleのスケール値
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Stack(
children: <Widget>[
// Panテスト用のウィジェット
Positioned(
left: _offset.dx, // 移動の値(x)
top: _offset.dy, // 移動の値(y)
child: GestureDetector(
// ドラッグの移動を更新
onPanUpdate: (DragUpdateDetails details) {
setState(() {
_offset += details.delta;
});
},
child: Container(
color: Colors.green,
width: 100,
height: 100,
child: Center(child:Text('Pan\nx:${_offset.dx.toInt()}\ny:${_offset.dy.toInt()}'),),
),
),
),
// Scale用のウィジェット
Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
GestureDetector(
// 回転とスケールの値を更新
onScaleUpdate: (ScaleUpdateDetails details) {
setState(() {
_radians = details.rotation;
_scale = details.scale;
});
},
child: Transform.rotate(
angle: _radians, // 回転の値
child: Transform.scale(
scale: _scale, // スケールの値
child: Container(
height: 300,
width: 300,
color: Colors.amber,
child: Center(child:Text('rotation:\n$_radians\nscale:\n$_scale'),),
),
),
),
),
],
),
),
],
),
);
}
}
コメント