Flutter device shake iOS 插件
Flutter device shake iOS plugin
晚上的伙计们,
我正在考虑为 Flutter 构建一个插件来检测设备是否在摇晃。现在我已经在 Swift (Detect shake gesture IOS Swift) 中找到了如何在技术上做到这一点,但我仍然坚持如何将它连接为 Flutter 插件,因为我无法直接访问视图控制器生命周期事件。
需要一种连接方式
- viewDidLoad
- 可以成为第一响应者
- 动作结束
任何人都可以在正确的方向推动我吗?
Flutter 团队 已经发布了 a plugin called sensors
,可用于检测来自 加速度计(和陀螺仪)的运动).
import 'package:sensors/sensors.dart';
accelerometerEvents.listen((AccelerometerEvent event) {
// "calculate" "shakes" here
});
event
包含 x
、y
和 z
值。将其与时间相结合将可以检查抖动。
我只是指出这一点,因为它比从头开始创建完整插件要简单得多.
我 运行 遇到了同样的问题,所以我认为 Reactive Programming
和 RxDart
可以提供帮助。
您可以创建一个名为 sensor_bloc.dart
的 BLoC
(业务逻辑组件):
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,让我可以通过静态函数 MainWidget.bloc(context)
访问 umbrella BLoC):
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();
}
你可以试试这个插件:shake_event
使用起来非常简单,并且适用于 iOS 和 Android。
晚上的伙计们,
我正在考虑为 Flutter 构建一个插件来检测设备是否在摇晃。现在我已经在 Swift (Detect shake gesture IOS Swift) 中找到了如何在技术上做到这一点,但我仍然坚持如何将它连接为 Flutter 插件,因为我无法直接访问视图控制器生命周期事件。
需要一种连接方式
- viewDidLoad
- 可以成为第一响应者
- 动作结束
任何人都可以在正确的方向推动我吗?
Flutter 团队 已经发布了 a plugin called sensors
,可用于检测来自 加速度计(和陀螺仪)的运动).
import 'package:sensors/sensors.dart';
accelerometerEvents.listen((AccelerometerEvent event) {
// "calculate" "shakes" here
});
event
包含 x
、y
和 z
值。将其与时间相结合将可以检查抖动。
我只是指出这一点,因为它比从头开始创建完整插件要简单得多.
我 运行 遇到了同样的问题,所以我认为 Reactive Programming
和 RxDart
可以提供帮助。
您可以创建一个名为 sensor_bloc.dart
的 BLoC
(业务逻辑组件):
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,让我可以通过静态函数 MainWidget.bloc(context)
访问 umbrella BLoC):
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();
}
你可以试试这个插件:shake_event
使用起来非常简单,并且适用于 iOS 和 Android。