Flutter

GestureDetector で padding を含めた範囲に応答する

Flutter で何らかのタップに応答したい UI を作りたい場合、GestureDetector を使うことがあります。

以下の例は Icon を用意して、それをタップしたら……というケースです。ユーザビリティの観点から、アイコンの見た目よりも実際のタップ範囲を大きくしたいので、Container でラップして、padding を設定してタップに反応する範囲を広げようとしています。

new GestureDetector(
  onTap: () {
    // ここでタップされた場合の動作を実装する
  },
  child: new Container(
    padding: const EdgeInsets.all(16.0),
    child: const Icon(Icons.star, size: 32.0),
  ),
),

ところが、上記のままだと、アイコンの周囲の padding の範囲のタップには反応しません(アイコン自体のタップには反応します)。

HitTestBehavior

GestureDetector の behavior は標準では HitTestBehavior.deferToChild になっており、この状態だと、child である Container の padding 部分には反応してくれないようです。

behavior を明示すれば、padding 部分にも反応するようになります。

new GestureDetector(
  behavior: HitTestBehavior.opaque,
  onTap: () {
    // ここでタップされた場合の動作を実装する
  },
  child: new Container(
    padding: const EdgeInsets.all(16.0),
    child: const Icon(Icons.star, size: 32.0),
  ),
),

decoration

また、別の対策としては、Container に color や decoration を設定します(color は deciration のショートハンドです)。そうすると、padding の部分も含めて「 child の領域だ」ということになるようです。

new GestureDetector(
  onTap: () {
    // ここでタップされた場合の動作を実装する
  },
  child: new Container(
    color: Colors.white, // これがあると反応する
    padding: const EdgeInsets.all(16.0),
    child: const Icon(Icons.star, size: 32.0),
  ),
),