Flutter устройство встряхнуть iOS плагин
Вечерние ребята,
Я смотрю на создание плагина для Flutter, который определяет, дрожит ли устройство. Теперь я нашел, как технически сделать это в Swift ( Обнаружение жеста встряхивания IOS Swift), но я застрял на том, как подключить его как плагин Flutter, потому что у меня нет прямого доступа к событиям жизненного цикла контроллера представления.
Нужен способ подключить
- viewDidLoad
- canBecomeFirstResponder
- motionEnded
Кто-нибудь может подтолкнуть меня в правильном направлении?
2 ответа
Команда Flutter уже опубликовала плагин под названиемsensors
, который может быть использован для обнаружения движения от акселерометра (и гироскопа).
import 'package:sensors/sensors.dart';
accelerometerEvents.listen((AccelerometerEvent event) {
// "calculate" "shakes" here
});
event
содержит x
, y
а также z
ценности. Комбинируя это со временем, можно будет проверять наличие сотрясений.
Я просто указываю на это, потому что это гораздо меньше, чем создание полноценного плагина с нуля.
Вы можете попробовать этот плагин: shake_event
С ним довольно просто работать, и он работает как для iOS, так и для Android.
Я столкнулся с той же проблемой, поэтому я решил, Reactive Programming
а также RxDart
мог бы помочь.
Вы можете создать BLoC
(Компонент бизнес-логики) называется sensor_bloc.dart
:
import 'dart:async';
import 'dart:math';
import 'package:rxdart/rxdart.dart';
import 'package:sensors/sensors.dart';
class SensorBloc {
StreamSubscription<dynamic> _accelerometerStream;
//INPUT
final _thresholdController = StreamController<int>();
Sink<int> get threshold => _thresholdController.sink;
// OUTPUT
final _shakeDetector = StreamController<bool>();
Stream<bool> get shakeEvent => _shakeDetector.stream.transform(ThrottleStreamTransformer(Duration(seconds: 2)));
SensorBloc() {
const CircularBufferSize = 10;
double detectionThreshold = 70.0;
List<double> circularBuffer = List.filled(CircularBufferSize,0.0);
int index = 0;
double minX=0.0, maxX=0.0;
_thresholdController.stream.listen((value){
// safety
if (value > 30) detectionThreshold = value*1.0;
});
_accelerometerStream = accelerometerEvents.listen((AccelerometerEvent event){
index = (index == CircularBufferSize -1 ) ? 0: index+1;
var oldX = circularBuffer[index];
if (oldX == maxX) {
maxX = circularBuffer.reduce(max);
}
if (oldX == minX) {
minX = circularBuffer.reduce(min);
}
circularBuffer[index] = event.x;
if (event.x < minX ) minX=event.x;
if (event.x> maxX) maxX = event.x;
if (maxX-minX>detectionThreshold)
{
_shakeDetector.add(true);
circularBuffer.fillRange(0, CircularBufferSize, 0.0);
minX=0.0;
maxX=0.0;
}
});
}
void dispose() {
_shakeDetector.close();
_accelerometerStream.cancel();
_thresholdController.close();
}
}
Затем просто подпишитесь на его события в вашем виджете: StreamSubscription<bool> shakeSubscriber ;
в вашем состоянии, и подключиться к событиям жизненного цикла
(Примечание: я использую InheritedWidget, который дает мне доступ к зонтичному BLoC через статическую функцию MainWidget.bloc(context)
):
StreamSubscription<bool> shakeSubscriber ;
@override
Widget build(BuildContext context) {
if(shakeSubscriber == null ) {
MainWidget.bloc(context).sensorBloc.shakeEvent.listen((_){
print("SHAKE ! *************************");
});
}
return _buildMainScaffold();
}
@override
void dispose() {
if(shakeSubscriber != null ) shakeSubscriber.cancel();
super.dispose();
}