マグネテック備忘録

Flutterアプリ開発の備忘録

【Flutter】スマホを振ったことを検知(shake)



準備

  • こちらのshakeパッケージを利用していきます。
  • パッケージを利用するので、いつも通りpubspec.yamlに追加していきます。

# 現時点での最新verを追加
dependencies:
  shake: ^2.2.0





基本

ShakeDetector.autoStart

  • 宣言と同時にシェイクの検知を開始します。
ShakeDetector detector = ShakeDetector.autoStart(
  // 振ったときに呼び出される処理(必須)
  onPhoneShake: () {/* 処理 */},
  // プロパティの設定
);



ShakeDetector.waitForStart

  • 宣言しただけではシェイク検知を開始しません
  • 検知を開始するには、宣言後にstartListening()を呼び出す必要があります。
ShakeDetector detector = ShakeDetector.waitForStart(
  // 振ったときに呼び出される処理(必須)
  onPhoneShake: () {/* 処理 */},
  // プロパティの設定
);

// 検知を開始
detector.startListening();



ShakeDetector.StopListening()

  • StartListening()と反対に検知を中断します
  • autoStartで宣言した場合でも動作してくれます。
  • 検知を再開したい場合は、startListening()を呼びましょう。





プロパティ

設定必須(onPhoneShake)

  • 振ったことを検知した後にする処理/span>。
  • 引数、返り値はない?



読み取りのみ可

mShakeCount
  • 振った回数
  • int型。
mShakeTimestamp
  • 最後に振った時刻(ミリ秒単位)
  • int型。



読み書き可能

minimumShakeCount
  • onPhoneShakeが呼び出されるまでに必要なシェイク数。
  • デフォルト:1回(int)。
  • 「5回以上振ったら特定の処理をする」などの場合に設定するのがおすすめ。



shakeSlopTimeMS
  • 1回振ってから次のシェイクを検知するまでのインターバル(ミリ秒)
  • デフォルト:500[ms](int)。
  • 小さすぎても大きすぎても使いにくいので、拘りがなければデフォルトのままで良い。



shakeThresholdGravity
  • 検知するシェイクの強さの最低値。これより小さい場合は振ったとみなさない。
  • デフォルト:2.7(double)。
  • 小さすぎても大きすぎても使いにくいので、拘りがなければデフォルトのままで良い。



shakeCountResetTime
  • シェイク回数をリセットする時間(ミリ秒)
  • デフォルト:3000[ms](int)。
  • 最後に振った時刻(mShakeTimestamp)からこの時間だけ経過すると、振った回数(mShakeCount)が初期化される。
  • 連続で振る分にはデフォルトのままで問題ないが、インターバルが長いが連続扱いしたいなら大きな値を格納する or mShakeCountではなく変数を自分で用意してそっちでカウントするなどしたほうがよい。





デモアプリ

ソースコード

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

void main() {

  const app = MaterialApp(
    home: MyHomePage(),
  );

  runApp(app);
}

// ミリ秒から日時を取得
String getDateFromMili(int millisecondsSinceEpoch){

  // ミリ秒数をDateTimeオブジェクトに変換
  DateTime dateTime = DateTime.fromMillisecondsSinceEpoch(millisecondsSinceEpoch);

  return dateTime.toString();
}

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

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  late ShakeDetector _detector;

  @override
  void initState() {
    super.initState();
    
    _detector = ShakeDetector.autoStart(
      // 振ったときに呼び出される処理(必須)
      onPhoneShake: () {
        setState(() {});
      },
      // プロパティの設定
      minimumShakeCount: 3 //3回以上振らないとonPhoneShakeが呼び出されない(画面更新されない)
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: const Text('Shake Test'),
      ),

      body: Center(
        child: Column(
          children: <Widget>[
            Text(
              '振った回数:${_detector.mShakeCount}',
            ),
            Text(
              '最後に振った時刻: ${getDateFromMili(_detector.mShakeTimestamp)}'
            ),
            if(_detector.mShakeCount % 2 == 0)...{
              const Text('偶数回振りました!!')
            },

            ElevatedButton(
              onPressed: (){
                _detector.startListening();
              }, 
              child: const Text('StartListening()')
            ),
            ElevatedButton(
              onPressed: (){
                _detector.stopListening();
              }, 
              child: const Text('StopListenning()')
            )
          ],
        ),
      ),
    );
  }
}



実行画面

デモアプリの実行画面