Parallel Timer animation in flutter - flutter

I made an automatic scrolling bar in flutter, the way I made it scroll automatically by using a combination of a timer and scroll controller, and then I linked the scroll controller to a regular ListView.builder, blew is the implementation of my way to do it
#override
void initState() {
super.initState();
int _length = widget.items.length;
currentItems = widget.items;
// scroll smothly to the end of the list then reverse the scroll
bool isAscending = true;
_timer = Timer.periodic(const Duration(milliseconds: 3000), (timer) {
if (isAscending) {
_currentIndex++;
if (_currentIndex == currentItems.length) {
isAscending = !isAscending;
}
}
if (!isAscending) {
_currentIndex--;
if (_currentIndex == 0) {
isAscending = !isAscending;
}
}
_scrollController.animateTo(_currentIndex * 304.0,
duration: const Duration(milliseconds: 3000), curve: Curves.linear);
});
}
my problem here is when I navigate to another screen or press the phone's home button and stay away from this widget for a while and then come back, I'd find it scrolling so fast to catch the currentIndex ( which is far away from where I left it ) in a period of time that I specified for the .animateTo method, I'm guessing the solution is to somehow pause the timer when I'm not in the same route, but I didn't find any reference of how to implement that

Related

how to implement lazy loading inside nested scroll view in flutter

i want to add lazy loading for my app but when i put the new controller. the controller didn't work with the NestedScrollView that i've made.
my new controller:
final controller = ScrollController();
in my initstate:
controller.addListener(() {
if (controller.position.maxScrollExtent == controller.offset) {
getStoryUser();
}
and i put the controller into list view but its didn't work with the NestedScrollView that i've mentioned earlier. any solution for this matter? any help will be valuable thank you.
Attach this _scrollController with your scrollview
if ((_scrollController.position.pixels >
_scrollController.position.maxScrollExtent - 20)) {
if (_isLoading || _loadMore || ((_media.media?.length ?? 0) < 30)) {
return;
}
_pageNumber++;
_loadMore = true;
if (mounted) setState(() {});
await _loadData();
_loadMore = false;
if (mounted) setState(() {});
}

Flutter QR Camera is not working when page is changed

i have a screen that scans qr code and sends some informations to my db, when i navigate to camera page first time camera works perfectly but when i navigate to another page then back to camera page again camera is not working
if i save codes, camera works again. i think its about state but i cannot manage to solve this problem.
void initState() {
super.initState();
_animationController =
AnimationController(vsync: this, duration: const Duration(seconds: 1));
_animation = Tween<double>(begin: 0, end: 1).animate(CurvedAnimation(
parent: _animationController, curve: Curves.easeInOutCirc));
_animationController.forward();
}
void dispose() {
try {
qrViewController?.dispose();
} catch (e) {
print("error");
}
super.dispose();
}
Future<void> reassemble() async {
// TODO: implement reassemble
super.reassemble();
if (Platform.isAndroid) {
await qrViewController!.pauseCamera();
}
qrViewController!.resumeCamera();
}
void onQrViewCreated(QRViewController qrViewController) {
setState(() {
this.qrViewController = qrViewController;
});
qrViewController.scannedDataStream.listen((event) async {}
}
I changed my qr_code_scanner package with same publisher's mobile_scanner and this is working well

How to detect device rotation (orientation change) in flutter?

My app has a draggable floating action button that could move everywhere on the screen and stay at that position when being dropped.
The code for the button is from a blogspot and not mine.
The problem is, since everything is set in portrait mode, and there is no detection when rotation occurs, the button could be unreachable when device rotates from portrait mode to landscape mode (if the button was previously on the bottom half of the screen in portrait mode).
Is there anyway to detect previous orientation in order to set the offset for the button again when it rotates?
Here is the code for the floating button class/widget
import 'package:flutter/material.dart';
class DraggableFloatingActionButton extends StatefulWidget {
final Widget child;
final double deviceWidth;
final double deviceHeight;
final Function onPressed;
final GlobalKey parentKey;
DraggableFloatingActionButton({
required this.child,
required this.deviceWidth,
required this.deviceHeight,
required this.onPressed,
required this.parentKey,
});
#override
State<StatefulWidget> createState() => _DraggableFloatingActionButtonState();
}
class _DraggableFloatingActionButtonState extends State<DraggableFloatingActionButton> {
final GlobalKey _key = GlobalKey();
bool _isDragging = false;
late Offset _offset;
late Offset _minOffset;
late Offset _maxOffset;
#override
void initState() {
_offset = Offset(widget.deviceWidth * 0.8, widget.deviceHeight * 0.75);
WidgetsBinding.instance.addPostFrameCallback(_setBoundary);
super.initState();
}
void _setBoundary(_) {
final RenderBox parentRenderBox =
widget.parentKey.currentContext?.findRenderObject() as RenderBox;
final RenderBox renderBox = _key.currentContext?.findRenderObject() as RenderBox;
try {
final Size parentSize = parentRenderBox.size;
final Size size = renderBox.size;
setState(() {
_minOffset = const Offset(0, 0);
_maxOffset = Offset(parentSize.width - size.width, parentSize.height - size.height);
});
} catch (e) {
print('catch: $e');
}
}
void _updatePosition(PointerMoveEvent pointerMoveEvent) {
double newOffsetX = _offset.dx + pointerMoveEvent.delta.dx;
double newOffsetY = _offset.dy + pointerMoveEvent.delta.dy;
if (newOffsetX < _minOffset.dx) {
newOffsetX = _minOffset.dx;
} else if (newOffsetX > _maxOffset.dx) {
newOffsetX = _maxOffset.dx;
}
if (newOffsetY < _minOffset.dy) {
newOffsetY = _minOffset.dy;
} else if (newOffsetY > _maxOffset.dy) {
newOffsetY = _maxOffset.dy;
}
setState(() {
_offset = Offset(newOffsetX, newOffsetY);
});
}
#override
Widget build(BuildContext context) {
return Positioned(
left: _offset.dx,
top: _offset.dy,
child: Listener(
onPointerMove: (PointerMoveEvent pointerMoveEvent) {
_updatePosition(pointerMoveEvent);
setState(() {
_isDragging = true;
});
},
onPointerUp: (PointerUpEvent pointerUpEvent) {
print('onPointerUp');
if (_isDragging) {
setState(() {
_isDragging = false;
});
} else {
widget.onPressed();
}
},
child: Container(
key: _key,
child: widget.child,
),
),
);
}
}
As you can see, it only sets the button's offset based on portrait mode once in initState function, and doesn't deal with rotation.
A walk around that I could think of at this moment is just having another floating button specifically set for landscape mode.
Thank you in advance for any answer.
Ok, so I still don't know how to detect rotation, but my walk around works.
All I do is create another class(widget) for a landscape floating button.
In main, check device orientation to use either the floating button portrait class or landscape class.
The only thing that I change in the landscape button class is
from
_offset = Offset(widget.deviceWidth * 0.8, widget.deviceHeight * 0.75);
to
_offset = Offset(widget.deviceHeight * 1.75, widget.deviceWidth * 0.3);
You shouldn't care about orientation. You should use something like LayoutBuilder to determine your space available, and make breakpoint decisions based on that. LayoutBuilder will update immediately if the device space changes, and you should react to that by doing another layout.

How can I simulate a gesture touch drag on mobile screen?

I'm using the following code, yes its incomplete and pretty little sphagetti as:
WidgetsBinding.instance!.handlePointerEvent(PointerDownEvent(pointer: 0, position: Offset(Get.width/2,Get.height/2)));
WidgetsBinding.instance!.handlePointerEvent(PointerMoveEvent(
pointer: 0,
//timeStamp: Duration(seconds:10),
position: Offset(Get.width/2+10,Get.height/2),
// delta: Offset(-10,Get.height/2),
// distanceMax: 0.05,
));
WidgetsBinding.instance!.handlePointerEvent(PointerUpEvent(pointer: 0),);
I'm trying to simulate a pointer drag on the screen, considering the screen is in landscape mode, from the middle of screen, to probably 10pixels+, to scroll the content a bit on a button-press. But the scroll is happening very fast, and sometimes scrolls with variable speed.
Could anyone recommend something?
Thanks to #pskink, the code he provided has been very helpful, and does answer the question too
late Animation<Offset> animation;
#override
void initState() {
super.initState();
final controller = AnimationController(vsync: this, duration: Duration(milliseconds: 300));
controller.addListener(_listener);
animation = Tween(begin: Offset(100, 100), end: Offset(200, 150)).animate(controller);
print('handle down event');
controller.forward().then((value) => print('handle up event'));
}
_listener() {
print('handle move event ${animation.value}');
}

Timer.periodic flutter,

#override
void initState() {
super.initState();
bool isLastPage = (_currentPage.round() == sliderArrayList.length - 1 );
//Trying to build automatic scrollable
Timer.periodic(Duration(seconds: 5), (Timer timer) {
if (_pageController.hasClients && !isLastPage) {
_pageController.nextPage(
duration: Duration(milliseconds: 200),
curve: Curves.easeIn);}
if(isLastPage){
timer.cancel();
}
});
}
I am trying to build a periodic timer which scrolls pages in pageview, flutter after every 5 seconds, however it keeps on scrolling even after the last page. I have tried to implement the above method if(isLastPage){timer.cancel();} and it doesnt work.
You've to evaluate that expression everytime timer ticks. Also, Put the isLastPage check before the hasClients check.
Timer.periodic(Duration(seconds: 5), (Timer timer) {
final isLastPage = _currentPage.round() == sliderArrayList.length - 1;
if (isLastPage) {
timer.cancel();
return;
}
if (_pageController.hasClients) {
_pageController.nextPage(
duration: Duration(milliseconds: 200),
curve: Curves.easeIn);
}
});