Flutterでシェイク機能を実装する（Provider + ChangeNotifier）

#はじめに
この記事では、Flutterでシェイク機能を実装するための手順を解説します。
シェイク機能のみの簡単なアプリを作りながら、実装をしていきます。
※ Android端末での動作確認のみとなります。

###筆者のレベル
・Flutterを始めて、約2ヶ月
・普段は、Javaのエンジニア(実務経験1年ほど)
・「ー」←このキーのブラインドタッチができない。。

#前提条件
・Flutterの環境構築が完了していること
 参考記事 → [Flutterの環境構築(Mac編)](https://zenn.dev/kboy/books/ca6a9c93fd23f3/viewer/5232dc)

・Providerのパッケージ導入が完了していること
 参考記事 → [provider | Flutter Package - Pub.Dev](https://pub.dev/packages/provider)

#shakeパッケージの導入

参考記事 → [shake | Flutter Package - Pub.Dev](https://pub.dev/packages/shake)

```dart:pubspec.yaml
dependencies:
  shake:
```
↓
`flutter pub get`

#完成コード
```dart:main.dart
import 'package:flutter/material.dart';

import 'home_page.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'シェイクアプリ',
      home: HomePage(),
    );
  }
}
```
```dart:home_page.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

import 'home_model.dart';

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<HomeModel>(
      create: (_) => HomeModel()..shakeGesture(context),
      child: Consumer<HomeModel>(builder: (context, model, child) {
        return Scaffold(
          appBar: AppBar(
            title: Text('シェイクアプリ'),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text('端末を振ってください'),
              ],
            ),
          ),
        );
      }),
    );
  }
}

```
```dart:home_model.dart
import 'package:flutter/material.dart';
import 'package:shake/shake.dart';

class HomeModel extends ChangeNotifier {
  shakeGesture(BuildContext context) {
    ShakeDetector.autoStart(onPhoneShake: () {
      showDialog(
          context: context,
          builder: (_) {
            return AlertDialog(
              title: Text('正常にシェイクを検知しました。'),
              actions: [
                FlatButton(
                  child: Text('OK'),
                  onPressed: () => Navigator.pop(context),
                ),
              ],
            );
          });
    });
  }
}

```

#画面作成
![Screenshot_1608358582.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/714109/ef83ae46-f66b-1e76-0c54-22c1334285b5.png)

```dart:home_page.dart
class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('シェイクアプリ'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('端末を振ってください'),
          ],
        ),
      ),
    );
  }
}
```
#モデル作成

###メソッド作成
```dart
class HomeModel extends ChangeNotifier {
  shakeGesture(BuildContext context) {
    // シェイク処理実装
  }
}
```

###シェイク処理実装
```dart
class HomeModel extends ChangeNotifier {
  shakeGesture(BuildContext context) {
    // 端末のシェイクを検知
    ShakeDetector.autoStart(onPhoneShake: () {
      // 端末がシェイクされた時の処理
      showDialog(
          context: context,
          builder: (_) {
            return AlertDialog(
              title: Text('正常にシェイクを検知しました。'),
              actions: [
                FlatButton(
                  child: Text('OK'),
                  onPressed: () => Navigator.pop(context),
                ),
              ],
            );
          });
    });
  }
}
```

#home_page.dartの編集

```dart:home_page.dart
class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // ChangeNotifierProviderを追加
    return ChangeNotifierProvider<HomeModel>(
      // ここでHomeModelのシェイク機能メソッドを呼び出す。
      create: (_) => HomeModel()..shakeGesture(context),
      child: Consumer<HomeModel>(builder: (context, model, child) {
        return Scaffold(
          appBar: AppBar(
            title: Text('シェイクアプリ'),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text('端末を振ってください'),
              ],
            ),
          ),
        );
      }),
    );
  }
}
```

#実機でテストする

Androidの実機でテストする方法は、下記の記事を参考にしていただければと思います。

参考記事 → [[Flutter]実機でデバッグしてみる(Android編)](https://crowd37.com/flutter-zikkidedebug-android/)

![Screenshot_20201219_154311_com.rrraibuuu.shake_gesture_app.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/714109/37f01bc3-7a0e-d6ef-ed5c-fec2aa146033.jpeg)


#終わりに
僕自身、Flutterでシェイク機能を実装する際に躓いたので、メモ感覚で書いてみました。
参考になれば幸いです。