📝

flutterアプリ開発においてInkWellとGestureDetectorどちらを採用するか

2024/05/11に公開

はじめに

InkWellとGestureDetectorを使えば、タッチされた時の動きを追加することができます。
iOSのタッチ時の動作で、InkWellとGestureDetectorのどちらを採用するか悩んだので、備考録として残しておきます。

InkWellとGestureDetectorの違い

InkWellは、タッチされた領域全体が押された感じになります。タップや長押しなどのイベントが発生した時にontapの処理を呼び出します。
一方、GestureDetectorは指が触れた点や動きを追跡できます。タップ、ドラッグ、スワイプなどさまざまなジェスチャを判別できます。

InkWell

InkWellのメリット

  • InkWellでタップ時のフィードバックがある
  • エフェクトの色や半径などをカスタマイズできる
  • Material Designに従ったデザインに適している

InkWellの公式

https://api.flutter.dev/flutter/material/InkWell-class.html

InkWellの簡単コード

import 'package:flutter/material.dart';

/// Flutter code sample for [InkWell].

void main() => runApp(const InkWellExampleApp());

class InkWellExampleApp extends StatelessWidget {
  const InkWellExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('InkWell Sample')),
        body: const Center(
          child: InkWellExample(),
        ),
      ),
    );
  }
}

class InkWellExample extends StatefulWidget {
  const InkWellExample({super.key});

  @override
  State<InkWellExample> createState() => _InkWellExampleState();
}

class _InkWellExampleState extends State<InkWellExample> {
  double sideLength = 50;

  @override
  Widget build(BuildContext context) {
    return AnimatedContainer(
      height: sideLength,
      width: sideLength,
      duration: const Duration(seconds: 2),
      curve: Curves.easeIn,
      child: Material(
        color: Colors.yellow,
        child: InkWell(
          onTap: () {
            setState(() {
              sideLength == 50 ? sideLength = 100 : sideLength = 50;
            });
          },
        ),
      ),
    );
  }
}

GestureDetector

GestureDetectorのメリット

  • さまざまなジェスチャ(タップ、ドラッグなど)を検出できる
  • ジェスチャ毎にカスタムして定義可能
  • 複雑な動作が必要な場合に利用されやすい

GestureDetectorの公式

https://api.flutter.dev/flutter/widgets/GestureDetector-class.html

GestureDetectorの簡単コード

import 'package:flutter/material.dart';

/// Flutter code sample for [GestureDetector].

void main() => runApp(const GestureDetectorExampleApp());

class GestureDetectorExampleApp extends StatelessWidget {
  const GestureDetectorExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: GestureDetectorExample(),
    );
  }
}

class GestureDetectorExample extends StatefulWidget {
  const GestureDetectorExample({super.key});

  @override
  State<GestureDetectorExample> createState() => _GestureDetectorExampleState();
}

class _GestureDetectorExampleState extends State<GestureDetectorExample> {
  bool _lightIsOn = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        alignment: FractionalOffset.center,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: Icon(
                Icons.lightbulb_outline,
                color: _lightIsOn ? Colors.yellow.shade600 : Colors.black,
                size: 60,
              ),
            ),
            GestureDetector(
              onTap: () {
                setState(() {
                  // Toggle light when tapped.
                  _lightIsOn = !_lightIsOn;
                });
              },
              child: Container(
                color: Colors.yellow.shade600,
                padding: const EdgeInsets.all(8),
                // Change button text when light changes state.
                child: Text(_lightIsOn ? 'TURN LIGHT OFF' : 'TURN LIGHT ON'),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Github

https://github.com/yuta0403/GestureDetector

InkWellとGestureDetectorのどちらを使うか迷ったら

  • タップや長押しだけを検知する必要がある場合はInkWell
  • 指の動きや位置も追跡したい場合はGestureDetector
  • 複数のジェスチャを区別したい場合はGestureDetector
  • 視覚的な動きが不要であれば軽いGestureDetector

自分で全てカスタマイズできるGestureDetectorも魅力的ですが、個人開発などで気軽に使えるのはInkWellだと思っています。
ご拝読いただきありがとうございました。

Discussion