I'm using Shake Flutter package in order to detect shakes on my application, but it doesn't seem to work either on my physical device (Samsung Galaxy A71) or on my Android Emulator.
Here is how I initialise the ShakeDetector:
class _HomePageState extends State<HomePage> {
bool _hasShaked;
ShakeDetector _shakeDetector;
#override
void initState() {
super.initState();
_hasShaked = false;
_shakeDetector = ShakeDetector.autoStart(
onPhoneShake: () {
print('shake')
setState(() {
_hasShaked = true;
_shakeDetector.stopListening();
});
},
);
}
#override
Widget build(BuildContext context) {
// ...
}
}
I tried to use ShakeDetector#waitForStart() instead but it doesn't work either:
class _HomePageState extends State<HomePage> {
bool _hasShaked;
ShakeDetector _shakeDetector;
#override
void initState() {
super.initState();
_hasShaked = false;
_shakeDetector = ShakeDetector.waitForStart(
onPhoneShake: () {
print('shake')
setState(() {
_hasShaked = true;
_shakeDetector.stopListening();
});
},
);
_shakeDetector.startListening();
}
#override
Widget build(BuildContext context) {
// ...
}
}
Here is my dependencies in my pubspec.yaml:
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^0.1.3
shake: ^0.1.0
Thanks for the help.
Related
I have a flutter app with redux state management.
In my app, I want to refetch some data from server when some other data in other screen changed. But in my case, I navigate from screen1 to screen2, and some data chaned in screen 2. I use a boolean flag needUpdate saved to redux and set to true after changes on screen 2.
But when I navigate back to screen1, I need to refetch data if the flag is true. But it did not work and data didnt refetch.
Here is some code:
class FirstScreen extends StatefulWidget {
const FirstScreen({Key? key}) : super(key: key);
#override
State<StatefulWidget> createState() => _FirstScreenState();
}
class _FirstScreenState extends State<FirstScreen> {
#override
void initState() {
super.initState();
}
#override
void didChangeDependencies() async {
final store = StoreProvider.of<AppState>(context);
var needUpdate = store.state.commonState?.needUpdate.value ?? false;
if (needUpdate) {
await store.dispatch(prepareData(context));
}
}
#override
Widget build(BuildContext context) {}
}
class SecondScreen extends StatefulWidget {
const SecondScreen({Key? key}) : super(key: key);
#override
State<SecondScreen> createState() => _SecondScreenState();
}
class _SecondScreenState extends State<SecondScreen> {
#override
void initState() {
super.initState();
}
void onPress() async {
await store.dispatch(ChangeNeedUpdatePortfolio(true));
Navigator.pop(context);
}
#override
Widget build(BuildContext context) {}
}
and Here is my action:
ThunkAction<AppState> updatePortfolioData(BuildContext context) {
return (Store<AppState> store) async {
bool needUpdate = store.state.commonState?.needUpdate.value ?? false;
if (needUpdate) {
...
await store.dispatch(ChangeNeedUpdatePortfolio(false));
...
return;
}
};
}
I'm working on a launcher app with gestures settings and I'm looking for a way to achieve two-finger swipe up and down gestures, i found out that it can be achieved by using RawGestureDetector and MultiDragGestureRecognizer , but I have no idea how to do it, can anyone share a code example or explain how to do it
i tried this code sample but it doesn't seem to work :
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
class TwoFingerPointerWidget extends StatelessWidget {
final Widget child;
final OnUpdate onUpdate;
TwoFingerPointerWidget({required this.child, required this.onUpdate});
#override
Widget build(BuildContext context) {
return RawGestureDetector(
gestures: <Type, GestureRecognizerFactory>{
CustomVerticalMultiDragGestureRecognizer:
GestureRecognizerFactoryWithHandlers<
CustomVerticalMultiDragGestureRecognizer>(
() => CustomVerticalMultiDragGestureRecognizer(debugOwner: null),
(CustomVerticalMultiDragGestureRecognizer instance) {
instance.onStart = (Offset position) {
return CustomDrag(events: instance.events, onUpdate: onUpdate);
};
},
),
},
child: child,
);
}
}
typedef OnUpdate(DragUpdateDetails details);
class CustomDrag extends Drag {
final List<PointerDownEvent> events;
final OnUpdate onUpdate;
CustomDrag({required this.events, required this.onUpdate});
#override
void update(DragUpdateDetails details) {
super.update(details);
final delta = details.delta;
if (delta.dy.abs() > 0 && events.length == 2) {
onUpdate.call(DragUpdateDetails(
sourceTimeStamp: details.sourceTimeStamp,
delta: Offset(0, delta.dy),
primaryDelta: details.primaryDelta,
globalPosition: details.globalPosition,
localPosition: details.localPosition,
));
}
}
#override
void end(DragEndDetails details) {
super.end(details);
}
}
class CustomVerticalMultiDragGestureRecognizer
extends MultiDragGestureRecognizer {
final List<PointerDownEvent> events = [];
CustomVerticalMultiDragGestureRecognizer({required Object? debugOwner})
: super(debugOwner: debugOwner);
#override
createNewPointerState(PointerDownEvent event) {
events.add(event);
return _CustomVerticalPointerState(event.position, onDisposeState: () {
events.remove(event);
});
}
#override
String get debugDescription => 'custom vertical multidrag';
}
typedef OnDisposeState();
class _CustomVerticalPointerState extends MultiDragPointerState {
final OnDisposeState onDisposeState;
_CustomVerticalPointerState(Offset initialPosition,
{required this.onDisposeState})
: super(initialPosition, PointerDeviceKind.touch, null);
#override
void checkForResolutionAfterMove() {
if (pendingDelta!.dy.abs() > kTouchSlop) {
resolve(GestureDisposition.accepted);
}
}
#override
void accepted(GestureMultiDragStartCallback starter) {
starter(initialPosition);
}
#override
void dispose() {
onDisposeState.call();
super.dispose();
}
}
So i just found a solution , not the best one but it still works ,for anyone looking
you have to work around the listener class , here is my code :
final events = [];
Listener(
onPointerDown: (event) {
events.add(event.pointer);
},
onPointerUp: (event) {
events.clear();
},
onPointerMove: (event) {
if (events.length == 2) {
int sensitivity = 8;
if (event.delta.dy > sensitivity) {
// code for two finger swipe up event
} else if (event.delta.dy < -sensitivity) {
// code for two finger swipe down event
}
}
},
i tried to get run the ShakeDetector in my Flutter app. I got a sample app here. Can somebody help me to fix the problem?
This codesample below is from the shake.dart github example. I dont get it why it is not working.
import 'package:flutter/material.dart';
import 'package:shake/shake.dart';
void main() {
runApp(DemoPage());
}
class DemoPage extends StatefulWidget {
#override
_DemoPageState createState() => _DemoPageState();
}
var phoneShakes;
class _DemoPageState extends State<DemoPage> {
#override
void initState() {
super.initState();
ShakeDetector detector = ShakeDetector.autoStart(onPhoneShake: () {
print('shaking');
});
// To close: detector.stopListening();
// ShakeDetector.waitForStart() waits for user to call detector.startListening();
phoneShakes = detector.mShakeCount;
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: AppBar(
title: Text(phoneShakes.toString()),
),
);
}
}
It's because there was no call to setState. Try this code:
class _DemoPageState extends State<DemoPage> {
late ShakeDetector _detector;
#override
void initState() {
super.initState();
_detector = ShakeDetector.autoStart(onPhoneShake: () {
setState(() {}); // Call setState every time phone shakes.
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text('Count: ${_detector.mShakeCount}'),
),
);
}
}
I always get the following error message when I try to run my flutter app:
* What went wrong:
Execution failed for task ':firebase_core:generateDebugRFile'.
> Could not resolve all files for configuration ':firebase_core:debugCompileClasspath'.
> Could not find com.google.firebase:firebase-common:.
Required by:
project :firebase_core
This is my code:
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:travel_games/loading_screen.dart';
import 'tg_theme.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(App());
}
class App extends StatefulWidget {
_AppState createState() => _AppState();
}
class _AppState extends State<App> {
// Set default `_initialized` and `_error` state to false
bool _initialized = false;
bool _error = false;
var msg;
// Define an async function to initialize FlutterFire
void initializeFlutterFire() async {
try {
// Wait for Firebase to initialize and set `_initialized` state to true
await Firebase.initializeApp();
setState(() {
_initialized = true;
});
} catch(e) {
// Set `_error` state to true if Firebase initialization fails
setState(() {
_error = true;
msg = e;
});
}
}
#override
void initState() {
initializeFlutterFire();
super.initState();
}
#override
Widget build(BuildContext context) {
// Show error message if initialization failed
if(_error) {
print('error');
print(msg);
return MaterialApp(home: LoadingScreen());
}
// Show a loader until FlutterFire is initialized
if (!_initialized) {
print('wait');
return MaterialApp(home: LoadingScreen());
}
return MaterialApp(home: Home());
}
}
class Home extends StatefulWidget {
// This widget is the root of your application.
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
FirebaseAuth auth = FirebaseAuth.instance;
//Future<UserCredential> userCredential = FirebaseAuth.instance.signInAnonymously();
#override
void initState() {
super.initState();
// waitForAuth();
}
void waitForAuth() async {
//UserCredential user = await userCredential;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: TgAppBar('Reisespiele'),
body: Container(
color: TgTheme.getHeaderBackgroundColor(),
),
);
}
}
My dependencies on pubspec.yaml:
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.2
firebase_core: ^1.3.0
firebase_auth: ^1.4.1
cloud_firestore: ^2.2.2
I followed the guide on https://firebase.flutter.dev/docs/overview, but it does not work.
It looks like there is something in the .gradle missing, but I could not figure it out :(
Has somebody an idea where my mistake is?
I want to automatically hide the status bar after 3 seconds of scrolling it down.
currently, I'm doing this.
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
void initState() {
super.initState();
Timer.periodic(const Duration(seconds: 3), (timer) {
SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.bottom]);
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: HomeScreen();
);
}
}
I want the timer to begin as soon as the user scrolls the the status bar.
Is there any better way to do that?
You may face existing issue on SystemChrome.
When setting System UI Overlays to bottom or top only, the status bar/bottom will show persistently after clicking.
Flutter problem full-screen on android #23913
SystemChrome.setEnabledSystemUIOverlays isn't sticky on android when only disable top #28426
I provide a workaround solution that detect status bar appear and react to it by using WidgetsBindingObserver
class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
var count = 0;
#override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
...
#override void didChangeMetrics() {
count++;
Future.delayed(const Duration(seconds: 3), () {
if(count == 1) {
SystemChrome.restoreSystemUIOverlays();
}
count --;
});
}
...
#override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}