この記事は全部俺 Advent Calendar 2018の9日目の記事です。
毎回毎回調べ直している気がするので書きました。
やりたいこと
左のようなボタンを押して起きるイベントを、右のように画面のどこをタップしてもできるようにします。
ソースコード
ボタンでイベント発火するソースコード
import 'package:flutter/material.dart';
class FadeInPage extends StatefulWidget {
@override
_FadeInPageState createState() => _FadeInPageState();
}
// The State class is responsible for two things: holding some data we can
// update and building the UI using that data.
class _FadeInPageState extends State<FadeInPage> {
bool _visible = true;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title:Text("Fade in / Fade out by toggle button"),
),
body: Center(
child: AnimatedOpacity(
// If the Widget should be visible, animate to 1.0 (fully visible). If
// the Widget should be hidden, animate to 0.0 (invisible).
opacity: _visible ? 1.0 : 0.0,
duration: Duration(milliseconds: 500),
// The green box needs to be the child of the AnimatedOpacity
child: Container(
width: 200.0,
height: 200.0,
color: Colors.green,
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
// Make sure we call setState! This will tell Flutter to rebuild the
// UI with our changes!
setState(() {
_visible = !_visible;
});
},
tooltip: 'Toggle Opacity',
child: Icon(Icons.flip),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
floatingActionButton
内にonPressed
イベントを定義することでイベントを実行することを可能にしています。
ここでは_visible
のトグルを行っています。
画面全体のどこを押してもイベント発火するサンプルコード
import 'package:flutter/material.dart';
class FadeInPage extends StatefulWidget {
@override
_FadeInPageState createState() => _FadeInPageState();
}
// The State class is responsible for two things: holding some data we can
// update and building the UI using that data.
class _FadeInPageState extends State<FadeInPage> {
// Whether the green box should be visible or invisible
bool _visible = true;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Fade in / Fade out by whole screen"),
),
body: GestureDetector(
behavior: HitTestBehavior.opaque,
child: Center(
child: AnimatedOpacity(
// If the Widget should be visible, animate to 1.0 (fully visible). If
// the Widget should be hidden, animate to 0.0 (invisible).
opacity: _visible ? 1.0 : 0.0,
duration: Duration(milliseconds: 500),
// The green box needs to be the child of the AnimatedOpacity
child: Container(
width: 200.0,
height: 200.0,
color: Colors.green,
),
),
),
onTap: () {
setState(() {
_visible = !_visible;
});
}));
}
}
body
部分全体をGestureDetector
で囲い、先程のソースコード内のonPressed
に定義されていた内容をonTap
に記載します。
肝になるのが、behavior: HitTestBehavior.opaque
という部分です。
ここを記載しない場合、GestureDetector
のデフォルトのbehavior
が使用されますが、デフォルトではbehavior: HitTestBehavior.deferToChild
という挙動になります。
このデフォルト挙動は、子要素がタップされたときにイベントを発火させるというものなので、デフォルトでは画面全体をタップしてもイベント発火はしません。(画面上の緑色四角部分をタップするとイベント発火します。)
ソースコード全体はここにおいてあります。