how to display an image in flutter after every 5 seconds? - flutter

i am new at flutter and building a project in which a distractor appears after every 5 sec on the the screen. i am using timer periodic but it the picture does not appears after 5 seconds rather it get displayed randomly after a few times. it starts to flash the image on the screen rather then keeping it displayed. also pictures doesnt appear after set time rather it changes its time itself. please help me. i am sad.
...
import 'dart:async';
import 'dart:math';
import 'package:flutter/material.dart';
class adhd1 extends StatefulWidget {
const adhd1({Key? key}) : super(key: key);
#override
State<adhd1> createState() => _adhd1State();
}
class _adhd1State extends State<adhd1> {
int a = 4;
bool distractor1 = false;
bool? distractor2 = false;
bool? distractor3 = false;
bool? distractor4 = false;
late Duration tt;
late Duration ff;
#override
Widget build(BuildContext context) {
showD1() {
Timer.periodic(
tt = Duration(seconds: 4),
(Timer t) => setState(() {
distractor1 = true;
t.cancel();
}));
Timer.periodic(
ff = Duration(seconds: 5),
(Timer d) => setState(() {
distractor1 = false;
d.cancel();
}));
if (distractor1) {
return SizedBox(
height: 200,
child: Image.asset(
"assets/images/character_robot_attack0.png",
fit: BoxFit.contain,
));
} else {
return const SizedBox(
height: 200,
);
}
}
return Scaffold(
backgroundColor: Colors.white,
body: Center(
child: Column(
children: [showD1()],
)));
}
}
...

To show for 2 second and hide 5sec, I am using AnimationController
class AnimeTestW extends StatefulWidget {
AnimeTestW({Key? key}) : super(key: key);
#override
State<AnimeTestW> createState() => _AnimeTestWState();
}
class _AnimeTestWState extends State<AnimeTestW>
with SingleTickerProviderStateMixin {
late AnimationController controller;
#override
void initState() {
super.initState();
controller = AnimationController(
vsync: this,
duration: const Duration(seconds: 2),
reverseDuration: const Duration(seconds: 5),
)
..addListener(() {
print(controller.status);
if (controller.status == AnimationStatus.completed) {
controller.reverse();
}
if (controller.status == AnimationStatus.dismissed) {
controller.forward();
}
setState(() {});
})
..forward();
}
#override
void dispose() {
controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(onPressed: () {
controller.reverse();
}),
body: Column(
children: [
Text("A"),
if (controller.status == AnimationStatus.forward)
Container(
width: 100,
height: 100,
color: Colors.red,
)
],
),
);
}
}
Use initState with a state bool
class _adhd1State extends State<adhd1> {
Timer? timer;
bool showImage = false;
#override
void initState() {
super.initState();
timer = Timer.periodic(Duration(seconds: 5), (timer) {
setState(() {
showImage = !showImage;
});
});
}
#override
void dispose() {
timer?.cancel();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Center(
child: Column(
children: [
if (showImage)
Image.asset(
"assets/images/character_robot_attack0.png",
fit: BoxFit.contain,
)
],
),
),
);
}
}

Related

flutter: convert splash screen from image to video

I have the following splash screen and I want to insert an animated video instead of the logo image.
I tried to follow this tutorial https://www.youtube.com/watch?v=ySaVFCpK4M8&t=102s
and it made me change the whole code but I ended up stuck with a black screen.
so i need to modify the code below to view the video instead of the image.
any help will be appreciated thank you.
import 'package:cirilla/constants/assets.dart';
import 'package:cirilla/constants/constants.dart';
import 'package:flutter/material.dart';
import 'package:ui/painter/zoom_painter.dart';
import 'widgets/zoom_animation.dart';
class SplashScreen extends StatefulWidget {
const SplashScreen({Key? key, this.color, this.loading}) : super(key: key);
final Color? color;
final bool? loading;
#override
State<SplashScreen> createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> with SingleTickerProviderStateMixin {
Size size = Size.zero;
late AnimationController _controller;
late ZoomAnimation _animation;
AnimationStatus _status = AnimationStatus.forward;
#override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(milliseconds: 2500),
vsync: this,
)
..addStatusListener((AnimationStatus status) {
setState(() {
_status = status;
});
})
..addListener(() {
setState(() {});
});
_animation = ZoomAnimation(_controller);
}
#override
void didChangeDependencies() {
setState(() {
size = MediaQuery.of(context).size;
});
super.didChangeDependencies();
}
#override
void didUpdateWidget(covariant SplashScreen oldWidget) {
super.didUpdateWidget(oldWidget);
if (!widget.loading! && _controller.status != AnimationStatus.forward) {
_controller.forward();
}
}
#override
Widget build(BuildContext context) {
if (_status == AnimationStatus.completed) return Container();
return Stack(children: [
SizedBox(
width: double.infinity,
height: double.infinity,
child: CustomPaint(
painter: ZoomPainter(color: widget.color!, zoomSize: _animation.zoomSize.value * size.width),
),
),
Padding(
padding: const EdgeInsets.only(bottom: itemPaddingExtraLarge),
child: Align(
alignment: Alignment.center,
child: Opacity(
opacity: _animation.textOpacity.value,
child: Image.asset(Assets.logo, width: 200, height: 200, fit: BoxFit.fitWidth),
),
),
)
]);
}
#override
void dispose() {
super.dispose();
_controller.dispose();
}
}

Pass the context to the showdialog so that it is not lost when the start page loads

I am trying to display an information dialog when starting an application.
After closing, another window appears asking for permission. I call it all in the initState function. It works, but I noticed that this first info dialog also closes on its own when 15 seconds have elapsed. As I understand, this is because the application has loaded and the context is lost.
And when I change runApp(MyApp()) to runApp(MaterialApp(home: MyApp())). It works, the popup doesn't dissapear. But the other showdialogs on other pages didn't close automatically (Navigator.of(context).pop() and Navigator.pop(context) doesnt work.
How do I properly pass context to my initial showdialog so that it doesn't disappear when the start page loads?
void main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp());
}
class MyApp extends StatefulWidget {
static final navKey = new GlobalKey<NavigatorState>();
const MyApp({Key navKey}) : super(key: navKey);
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) async {
final context = MyApp.navKey.currentState.overlay.context;
await showDialogIfFirstLoaded(context);
await initPlatformState();
});
}
showDialogIfFirstLoaded(BuildContext context, prefs) async {
bool isFirstLoaded = prefs.getBool(keyIsFirstLoaded);
if (isFirstLoaded == null) {
return showDialog(
context: context,
builder: (BuildContext context) {
// return object of type Dialog
return new AlertDialog(
// title: new Text("title"),
content: new Text("//"),
actions: <Widget>[
new FlatButton(
child: new Text(".."),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
}
#override
Widget build(BuildContext context) {
return MaterialApp(
navigatorKey:MyApp.navKey,
home: new SplashScreen(),}
class SplashScreen extends StatefulWidget {
#override
_SplashScreenState createState() => new _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> with SingleTickerProviderStateMixin {
Timer _timer;
bool _visible = true;
startTime() async {
_timer = Timer(new Duration(seconds: 5), navigationPage);
}
void navigationPage() {
Navigator.of(context).pushReplacementNamed('/home');
}
#override
void initState() {
_timer = Timer(Duration(seconds: 4),
() => setState(
() {
_visible = !_visible;
},
),
);
startTime();
super.initState();
}
#override
void dispose() {
_timer.cancel();
super.dispose();
}
#override
Widget build(BuildContext context) {
return new Stack(
children: <Widget>[
Container(
width: double.infinity,
child: Image.asset('images/bg.jpg',
fit: BoxFit.cover,
height: 1200,
),
),
Container(
width: double.infinity,
height: 1200,
color: Color.fromRGBO(0, 0, 0, 0.8),
),
Container(
alignment: Alignment.center,
child: Row(
children: <Widget>[
Expanded(
flex: 2,
child: Container(
child: Text(''),
),
),
],
),
),
],
);
}
}

Add 30 seconds more to the timer

Hello I am doing a flutter app , and I want to use a button to add 30s more to the time when it's pressed. The timer starts with 60 seconds , but I want the user to be able to add 30 seconds more if he needs . I only find at the controller(of time) the options like: reverse() , reset() , resync() but nothing to add the time. This is what I used in the beginning of the code ( I will post only some paths because the code is very big)
class _CountDownTimerState extends State<CountDownTimer>
with TickerProviderStateMixin {
AnimationController controller;
String get timerString {
Duration duration = controller.duration * controller.value;
return '${duration.inMinutes}:${(duration.inSeconds % 60).toString().padLeft(2, '0')}';
}
#override
void initState() {
super.initState();
controller = AnimationController(
vsync: this,
duration: Duration(seconds: 60),
);
}
and this is how I write my code for the button with +30s but it only reset the time to 00:30seconds.
child: RaisedButton(
onPressed: () {
if (controller.isAnimating)
controller.duration = Duration(seconds: 30);
},
color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30),
),
textColor: Colors.black,
child: Text("Give player +30s ")),
),
Here is a Solution using an AnimationController combined with a Timer. I used an initial time of 10 seconds and a time increase of 5 seconds for a faster demo.
import 'dart:async';
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Timer Demo',
home: HomePage(),
),
);
}
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
bool done = false;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: done
? Text('TIME OUT')
: CountDownTimer(
onCompleted: () => setState(() => done = true),
),
),
);
}
}
class CountDownTimer extends StatefulWidget {
final VoidCallback onCompleted;
const CountDownTimer({
Key key,
this.onCompleted,
}) : super(key: key);
#override
_CountDownTimerState createState() => _CountDownTimerState();
}
class _CountDownTimerState extends State<CountDownTimer>
with TickerProviderStateMixin {
AnimationController _controller;
Timer _timer;
int _elapsed;
#override
void initState() {
super.initState();
// AnimationController
_controller = AnimationController(vsync: this, duration: kInitialTime);
_controller.addListener(() => setState(() {}));
_controller.addStatusListener(
(AnimationStatus status) {
if (status == AnimationStatus.completed) {
_timer.cancel();
widget.onCompleted();
}
},
);
// Elapsed Counter
_elapsed = 0;
_timer = Timer.periodic(
Duration(seconds: 1),
(_) => setState(() => _elapsed++),
);
// Launch the Controller
_controller.forward();
}
void increaseTime([int extraTime = kExtraTime]) {
_controller.duration =
Duration(seconds: _controller.duration.inSeconds + extraTime);
_controller.reset();
_controller.forward(from: _elapsed / _controller.duration.inSeconds);
}
#override
void dispose() {
_controller.dispose();
_timer.cancel();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircularProgressIndicator(
value: _controller.value,
backgroundColor: Colors.black12,
),
const SizedBox(height: 12.0),
Text('$_elapsed / ${_controller.duration.inSeconds}'),
const SizedBox(height: 24.0),
ElevatedButton(
onPressed: () => increaseTime(),
child: Text('MORE TIME'),
),
],
);
}
}
// CONFIGURATION
const Duration kInitialTime = Duration(seconds: 10);
const int kExtraTime = 5;
You are setting the duration to 30 seconds, what you need to do instead is add to the remaining duration. You can probably use the + operator of the Duration class: https://api.dart.dev/stable/2.10.5/dart-core/Duration/operator_plus.html
Something like this:
onPressed: () {
if (controller.isAnimating) {
controller.duration += Duration(seconds: 30);
}
},
Not sure if the controller actually supports this.

How to make a text become clickable after 30 secs in flutter?

I am making a login app where by i have created an OTP validation page. In this page i want to make a resend option which is clickable only after 30 seconds of page loading and once clicked becomes unclickable for ever.
I am new to flutter so I am sorry if this seems trivial.
You can follow this code.
class TestButton extends StatefulWidget {
#override
_TestButtonState createState() => _TestButtonState();
}
class _TestButtonState extends State<TestButton> {
bool firstStateEnabled = false;
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
Timer(Duration(milliseconds: 30000), () {
setState(() {
firstStateEnabled = true;
});
});
return Scaffold(
body: Container(
child: firstStateEnabled
? Center(
child: Container(
width: 200,
height: 55,
child: RaisedButton(
onPressed: () {},
child: Text("Resend OTP"),
),
),
)
: Center(child: Container()),
),
);
}
}
Or if you need only one time the button than you can follow below codes.
Install timer_count_down.
Then, below code.
class TestButton extends StatefulWidget {
#override
_TestButtonState createState() => _TestButtonState();
}
class _TestButtonState extends State<TestButton> {
bool firstStateEnabled = false;
final CountdownController controller = CountdownController();
final int seconds = 30;
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Container(
child: firstStateEnabled
? Center(
child: Container(
width: (200),
height: 55,
child: RaisedButton(
onPressed: () {
setState(() {
firstStateEnabled = false;
});
},
child: Text("Resend OTP"),
),
),
)
: Center(child: Container()),
),
Countdown(
controller: controller,
seconds: seconds,
build: (context, double time) {
return Container();
},
interval: Duration(milliseconds: 100),
onFinished: () {
setState(() {
firstStateEnabled = true;
;
});
},
)
],
),
);
}
}

Flutter Reworked question: Issue sharing states between widget with button and widget with countdown timer

I am trying since some days to connect an animated stateful child widget with a countdown timer to the parent stateful widget with the user interaction. I found this answer from Andrey on a similar question (using Tween which I do not) that already helped a lot, but I still don't get it to work. My assumption is, the child's initState could be the reason. The timer's code comes from here.
I have removed quite some code including some referenced functions/classes. This should provide a clearer picture on the logic:
In MainPageState I declare and init the _controller of the animation
In MainPageState I call the stateless widget CreateKeypad hosting among others the "go" key
When go is clicked, this event is returned to MainPageState and _controller.reverse(from: 1.0); executed
In MainPageState I call the stateful widget CountDownTimer to render the timer
In _CountDownTimerState I am not sure if my initState is correct
In _CountDownTimerState I build the animation with CustomTimerPainter from the timer code source
The animation shall render a white donut and a red, diminishing arc on top. However, I only see the white donut, not the red timer's arc. Any hint is highly appreciated.
class MainPage extends StatefulWidget {
MainPage({Key key, this.title}) : super(key: key);
final String title;
#override
_MainPageState createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> with TickerProviderStateMixin {
AnimationController _controller;
var answer="0", correctAnswer = true, result = 0;
#override
void initState() {
super.initState();
_controller = AnimationController(vsync: this, duration: Duration(seconds: 7));
}
#override
void dispose() {
_controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
),
child: SafeArea(
child: Container(
child: Column(
children: <Widget>[
CreateKeypad( // creates a keypad with a go button. when go is clicked, countdown shall start
prevInput: int.parse((answer != null ? answer : "0")),
updtedInput: (int val) {
setState(() => answer = val.toString());
},
goSelected: () {
setState(() {
if (answer == result.toString()) {
correctAnswer = true;
}
final problem = createProblem();
result = problem.result;
});
_controller.reverse(from: 1.0); // start the countdown animation
Future.delayed(const Duration(milliseconds: 300,),
() => setState(() => correctAnswer = true));
},
),
CountDownTimer(_controller), // show countdown timer
]
),
),
)
);
}
}
// CREATE KEYPAD - all keys but "1! and "go" removed
class CreateKeypad extends StatelessWidget {
final int prevInput;
final VoidCallback goSelected;
final Function(int) updtedInput;
CreateKeypad({#required this.prevInput, #required this.updtedInput, this.goSelected});
#override
Widget build(BuildContext context) {
return Row(
children: <Widget> [
Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(2.0),
child: SizedBox(
width: 80.0, height: 80.0,
child: CupertinoButton(
child: Text("1", style: TextStyle(color: CupertinoColors.black)),
onPressed: () {
updtedInput(1);
},
),
),
),
Padding(
padding: const EdgeInsets.all(2.0),
child: SizedBox(
width: 80.0, height: 80.0,
child: CupertinoButton(
child: Text("Go!", style: TextStyle(color: CupertinoColors.black)),
onPressed: () => goSelected(),
),
),
),
],
),
]
);
}
}
// CREATE COUNTDOWN https://medium.com/flutterdevs/creating-a-countdown-timer-using-animation-in-flutter-2d56d4f3f5f1
class CountDownTimer extends StatefulWidget {
CountDownTimer(this._controller);
final AnimationController _controller;
#override
_CountDownTimerState createState() => _CountDownTimerState();
}
class _CountDownTimerState extends State<CountDownTimer> with TickerProviderStateMixin {
#override
void initState() {
super.initState(); // here I have some difference to Andrey's answer because I do not use Tween
}
String get timerString {
Duration duration = widget._controller.duration * widget._controller.value;
return '${duration.inMinutes}:${(duration.inSeconds % 60)
.toString()
.padLeft(2, '0')}';
}
#override
Widget build(BuildContext context) {
return Container(
child: AnimatedBuilder(
animation: widget._controller,
builder:
(BuildContext context, Widget child) {
return CustomPaint(
painter: CustomTimerPainter( // this draws a white donut and a red diminishing arc on top
animation: widget._controller,
backgroundColor: Colors.white,
color: Colors.red,
));
},
),
);
}
}
You can copy paste run full code below
Step 1: You can put controller inside CountDownTimerState
Step 2: Use GlobalKey
CountDownTimer(key: _key)
Step 3: Call function start() inside _CountDownTimerState with _key.currentState
goSelected: () {
setState(() {
...
_controller.reverse(from: 10.0); // start the countdown animation
final _CountDownTimerState _state = _key.currentState;
_state.start();
...
class _CountDownTimerState extends State<CountDownTimer>
with TickerProviderStateMixin {
AnimationController _controller;
#override
void initState() {
_controller =
AnimationController(vsync: this, duration: Duration(seconds: 7));
super
.initState(); // here I have some difference to Andrey's answer because I do not use Tween
}
...
void start() {
setState(() {
_controller.reverse(from: 1.0);
});
}
working demo
full code
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'dart:math' as math;
class MainPage extends StatefulWidget {
MainPage({Key key, this.title}) : super(key: key);
final String title;
#override
_MainPageState createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> with TickerProviderStateMixin {
AnimationController _controller;
var answer = "0", correctAnswer = true, result = 0;
GlobalKey _key = GlobalKey();
#override
void initState() {
super.initState();
_controller =
AnimationController(vsync: this, duration: Duration(seconds: 7));
}
#override
void dispose() {
_controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
//navigationBar: CupertinoNavigationBar(),
child: SafeArea(
child: Container(
color: Colors.blue,
child: Column(children: <Widget>[
CreateKeypad(
// creates a keypad with a go button. when go is clicked, countdown shall start
prevInput: int.parse((answer != null ? answer : "0")),
updtedInput: (int val) {
setState(() => answer = val.toString());
},
goSelected: () {
setState(() {
if (answer == result.toString()) {
correctAnswer = true;
}
/*final problem = createProblem();
result = problem.result;*/
});
print("go");
_controller.reverse(from: 10.0); // start the countdown animation
final _CountDownTimerState _state = _key.currentState;
_state.start();
/* Future.delayed(
const Duration(
milliseconds: 300,
),
() => setState(() => correctAnswer = true));*/
},
),
Container(
height: 400,
width: 400,
child: CountDownTimer(key: _key)), // show countdown timer
]),
),
));
}
}
// CREATE KEYPAD - all keys but "1! and "go" removed
class CreateKeypad extends StatelessWidget {
final int prevInput;
final VoidCallback goSelected;
final Function(int) updtedInput;
CreateKeypad(
{#required this.prevInput, #required this.updtedInput, this.goSelected});
#override
Widget build(BuildContext context) {
return Row(children: <Widget>[
Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(2.0),
child: SizedBox(
width: 80.0,
height: 80.0,
child: CupertinoButton(
child:
Text("1", style: TextStyle(color: CupertinoColors.black)),
onPressed: () {
updtedInput(1);
},
),
),
),
Padding(
padding: const EdgeInsets.all(2.0),
child: SizedBox(
width: 80.0,
height: 80.0,
child: CupertinoButton(
child:
Text("Go!", style: TextStyle(color: CupertinoColors.black)),
onPressed: () => goSelected(),
),
),
),
],
),
]);
}
}
// CREATE COUNTDOWN https://medium.com/flutterdevs/creating-a-countdown-timer-using-animation-in-flutter-2d56d4f3f5f1
class CountDownTimer extends StatefulWidget {
CountDownTimer({Key key}) : super(key: key);
//final AnimationController _controller;
#override
_CountDownTimerState createState() => _CountDownTimerState();
}
class _CountDownTimerState extends State<CountDownTimer>
with TickerProviderStateMixin {
AnimationController _controller;
#override
void initState() {
_controller =
AnimationController(vsync: this, duration: Duration(seconds: 7));
super
.initState(); // here I have some difference to Andrey's answer because I do not use Tween
}
String get timerString {
Duration duration = _controller.duration * _controller.value;
return '${duration.inMinutes}:${(duration.inSeconds % 60).toString().padLeft(2, '0')}';
}
void start() {
setState(() {
_controller.reverse(from: 1.0);
});
}
#override
Widget build(BuildContext context) {
return Container(
color: Colors.green,
child: AnimatedBuilder(
animation: _controller,
builder: (BuildContext context, Widget child) {
return CustomPaint(
painter: CustomTimerPainter(
// this draws a white donut and a red diminishing arc on top
animation: _controller,
backgroundColor: Colors.green,
color: Colors.red,
));
},
),
);
}
}
class CustomTimerPainter extends CustomPainter {
CustomTimerPainter({
this.animation,
this.backgroundColor,
this.color,
}) : super(repaint: animation);
final Animation<double> animation;
final Color backgroundColor, color;
#override
void paint(Canvas canvas, Size size) {
Paint paint = Paint()
..color = backgroundColor
..strokeWidth = 10.0
..strokeCap = StrokeCap.butt
..style = PaintingStyle.stroke;
canvas.drawCircle(size.center(Offset.zero), size.width / 2.0, paint);
paint.color = color;
double progress = (1.0 - animation.value) * 2 * math.pi;
//print("progress ${progress}");
canvas.drawArc(Offset.zero & size, math.pi * 1.5, -progress, false, paint);
}
#override
bool shouldRepaint(CustomTimerPainter old) {
//print(animation.value);
return true;
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MainPage(),
);
}
}