My application takes some time to load to the home screen, and also takes time to fetch all the data from the API. so I need a splash screen for the application. but it should wait for 3 seconds (the time that takes to load the home screen). so I want to cover the waiting time with a splash screen.
How do I achieve this?
You can also have a minimal Flutter app running while you await the more expensive initialization. Just call runApp twice!
void main () async {
runApp(SomethingAnimated());
await longTaskOne();
await longTaskTwo();
await longTaskThree();
runApp(MyRealTopLevel();
}
Yes this is perfectly legal and documented.
EDIT: I made a video about this, and also about warming up RiverPod pre-fetched data, at https://youtu.be/ob8M9c-6III.
Use you own custom image of splashscreen or design new one here.increase or decrease time but less time is better
class SplashScreen extends StatefulWidget {
#override
_SplashScreenState createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
#override
void initState() {
// TODO: implement initState
super.initState();
startTime();
}
#override
Widget build(BuildContext context) {
// TODO: implement build
Size size = MediaQuery.of(context).size;
return SafeArea(
child: Scaffold(
body: new Stack(
alignment: Alignment.center,
children: <Widget>[
Center(
child: new Image.asset(
'assets/images/splash.png',
width: size.width,
height: size.height,
fit: BoxFit.fill,
),
),
],
),
),
);
}
startTime() async {
var _duration = new Duration(seconds: 5);
return new Timer(_duration, navigationPage);
}
void navigationPage() {
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => DashBoardScreen()),
ModalRoute.withName("/login"));
}
}
You can add a image as a splashscreen using this method,
class SplashScreen extends StatefulWidget {
#override
_SplashScreenState createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
#override
void initState() {
super.initState();
Timer(
Duration(seconds: 5),
() => Navigator.pushReplacement(
context, MaterialPageRoute(builder: (context) => Home())));
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
fit: StackFit.expand,
children: <Widget>[
Container(
decoration: BoxDecoration(
color: Color.fromRGBO(20, 172, 168, 1),
),
),
Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Expanded(
flex: 2,
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CircleAvatar(
backgroundColor: Colors.white,
radius: 60.0,
child: new Image.asset(
'assets/images/tree.jpg',
width: 70,
height: 90,
)),
Padding(
padding: EdgeInsets.only(top: 10.0),
),
Text(
'Your Text here!!',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 24.0),
)
],
),
),
),
Expanded(
flex: 1,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CircularProgressIndicator(),
Padding(
padding: EdgeInsets.only(top: 20.0),
),
Text(
'Your Text here!!',
softWrap: true,
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 18.0,
color: Colors.white),
)
],
),
)
],
)
],
),
);
}
}
And if you want to increase or decrease the time span then you can change this
Timer(const Duration(seconds: 3).
Related
**
Hello I am trying to build a quiz app and I want the quiz question and the options be shown after the video is ended completely.
I tried putting a condition for the text as
_videoPlayerController.value.position == _videoPlayerController.value.duration
Here there are 2 problems occurring,
For some reason the text is not getting shown after the video is ended
When I restart the app or go to the next question the text is getting shown at the start only before even the video starts playing.
Can anyone please help me with this, I'm really confused.
**
class QuestionPage extends StatefulWidget {
final Question question;
// ignore: prefer_typing_uninitialized_variables
const QuestionPage(
{super.key,
required this.question,
required String videoPlayerController});
#override
State<QuestionPage> createState() => _QuestionPageState();
}
class _QuestionPageState extends State<QuestionPage> {
late VideoPlayerController _videoPlayerController;
ChewieController? chewieController;
#override
void initState() {
super.initState();
_initPlayer();
}
void _initPlayer() async {
_videoPlayerController =
VideoPlayerController.network(widget.question.video);
_videoPlayerController.initialize();
if (_videoPlayerController.value.position ==
_videoPlayerController.value.duration) {
print('Video Ended');
}
chewieController = ChewieController(
aspectRatio: 16 / 9,
zoomAndPan: true,
videoPlayerController: _videoPlayerController,
autoPlay: true,
looping: false,
);
}
#override
void dispose() {
_videoPlayerController.dispose();
chewieController?.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
var state = Provider.of<QuizState>(context);
return Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Expanded(
child: Container(
padding: const EdgeInsets.all(16),
alignment: Alignment.center,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(
child: SizedBox(
height: 200,
width: MediaQuery.of(context).size.width,
child: Chewie(
controller: chewieController!,
),
)),
if (_videoPlayerController.value.position ==
_videoPlayerController.value.duration)
QuestionContainer(context),
],
),
),
),
Container(
padding: const EdgeInsets.all(20),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: widget.question.options.map((opt) {
return Container(
height: 90,
margin: const EdgeInsets.only(bottom: 10),
color: Colors.black26,
child: InkWell(
onTap: () {
state.selected = opt;
_bottomSheet(context, opt, state);
},
child: Container(
padding: const EdgeInsets.all(16),
child: Row(
children: [
Icon(
state.selected == opt
? FontAwesomeIcons.circleCheck
: FontAwesomeIcons.circle,
size: 30),
Expanded(
child: Container(
margin: const EdgeInsets.only(left: 16),
child: Text(
opt.value,
style: Theme.of(context).textTheme.bodyMedium,
),
),
)
],
),
),
),
);
}).toList(),
),
)
],
);
}
_bottomSheet(BuildContext context, Option opt, QuizState state) {
bool correctAnswer = opt.correct;
showModalBottomSheet(
context: context,
builder: (BuildContext context) {
return Container(
height: 250,
padding: const EdgeInsets.all(16),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(correctAnswer ? 'Good Job! Correct Answer' : 'Wrong Answer'),
Text(
opt.detail,
style: const TextStyle(fontSize: 18, color: Colors.white54),
),
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: correctAnswer ? Colors.green : Colors.red),
child: Text(
correctAnswer ? 'Next' : 'Try Again',
style: const TextStyle(
color: Colors.white,
letterSpacing: 1.5,
fontWeight: FontWeight.bold,
),
),
onPressed: () {
if (correctAnswer) {
state.nextPage();
}
Navigator.pop(context);
},
),
],
),
);
},
);
}
QuestionContainer(BuildContext context) {
return Container(
child: Text(widget.question.text),
);
}
}
Reposting this query, Please let me know if anyone can find a solution.
I'm not 100% sure, but I think it's because you only check the video's position once, and nothing is causing the app to recheck the position once the video has completed. It looks like VideoPlayerController is a ChangeNotifier though, so you can build your widget to react to changes in the state of VideoPlayerController. One option is to use AnimatedBuilder. This answer has a good description of that and other ways to leverage a ChangeNotifier.
I want the second screen to get only the text size from the first screen and apply it to its text. The font size increases or decreases as a user pinch the screen. So I want to get the desire font size and apply it to the text in the second screen so that the user wouldn't have to pinch the screen anytime he navigate to another screen. How do I do it?
class One extends StatefulWidget {
#override
_OneState createState() => _OneState();
}
class _OneState extends State<One> {
double _prevScale;
double _scale;
#override
void initState() {
super.initState();
_prevScale = _scale = 1.0;
}
#override
Widget build(BuildContext context) {
return GestureDetector(
onScaleUpdate: (ScaleUpdateDetails details) {
setState(() {
_scale = (_prevScale * (details.scale));
});
},
onScaleEnd: (ScaleEndDetails details) {
setState(() {
_prevScale = _scale;
});
},
child: Scaffold(
body: ListView(
children: [
Container(
height: MediaQuery.of(context).size.height/15,
width:MediaQuery.of(context).size.width,
child: Card (
elevation: 0.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
IconButton( icon:Icon(Icons.arrow_back), iconSize: 20.0,
padding: EdgeInsets.only(left: 15.0), onPressed: (){
Navigator.of(context).pop();
},
),
IconButton( icon:Icon(Icons.share), iconSize: 20.0,
padding: EdgeInsets.only(right: 10.0), onPressed: (){
},
),
],
),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
IconButton( icon:Icon(Icons.arrow_back_ios), iconSize: 20.0,
padding: EdgeInsets.only(left: 10.0),
),
Text("Selfless", style: TextStyle(fontSize: 20.0, fontFamily:"CrimsonText" ), ),
IconButton( icon:Icon(Icons.arrow_forward_ios), iconSize: 20.0,
padding: EdgeInsets.only(right: 10.0), onPressed: (){
Navigator.of(context).push(MaterialPageRoute(builder: (_)=>Two()));
},
),
],
),
Card(
// shadowColor: Colors.transparent,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)),
elevation: 5.0,
margin: EdgeInsets.all(10.0),
child: Padding(
padding: const EdgeInsets.all(15.0),
child: Column(
children: [
Text("-1-", style: TextStyle(fontSize: (25.0*_scale).clamp(20.0, 70.0), fontFamily:"CrimsonText" )),
Row(
children: [
Expanded(
child: Text("At Wandsworth Prison the Master, ‘Abdu’l-Baha, wrote in the visitors’ book: "
"‘The greatest prison is the prison of self.’",
style: TextStyle(fontSize: (25.0*_scale).clamp(20.0, 70.0), fontFamily:"CrimsonText", height: 1.4 ), ),
),
],
)
],
),
)
)
],
),
),
);
}
}
You can pass the font size (or the scale) from the first page to the second like this.
Then, you can simply use it on the second screen.
In a new stateful widget where you need the textSize, do something like this
class TwoState extends StatefulWidget {
double size;
TwoState(this.size);
#override
_TwoStateState createState() => _TwoStateState(size);
}
class _TwoStateState extends State<TwoState> {
double size;
_TwoStateState(this.size);
#override
Widget build(BuildContext context) {
return Container(
child: Text("",style:TextStyle(fontSize: 25*size)),
);
}
}
And push it like
Navigator.push(context, MaterialPageRoute(builder: (context)=>TwoState(size)))
But this only works from parent to child. You can try to do something like this
Size.dart
class Sizing{
double size;
Sizing(this.size);
}
Then in the home page, create a new variable like
Sizing size = Sizing(25);
And then instead of size variable use size.size and pass it around like the previous example. This way, it will work from parent to child and from child to parent
auto_size_text: ^2.1.0.
AutoSizeText() instead of Text()
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
void main() {
runApp(App());
}
class App extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: SizedBox(
width: 200.0,
height: 140.0,
child: AutoSizeText(
'This string will be automatically resized to fit in two lines.',
style: TextStyle(fontSize: 30.0),
maxLines: 2,
),
),
),
),
);
}
}
I have been reading solutions for making my screen scroll without success. Below is my code:
'''
class WelcomeScreen extends StatefulWidget {
static const String id = 'welcome_screen';
#override
_WelcomeScreenState createState() => _WelcomeScreenState();
}
class _WelcomeScreenState extends State<WelcomeScreen>
with SingleTickerProviderStateMixin {
AnimationController controller;
Animation animation;
#override
void initState() {
super.initState();
controller =
AnimationController(duration: Duration(seconds: 1), vsync: this);
animation = ColorTween(begin: Colors.blueGrey, end: Colors.white)
.animate(controller);
controller.forward();
controller.addListener(() {
setState(() {});
});
}
#override
void dispose() {
controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: animation.value,
body: Padding(
padding: EdgeInsets.symmetric(horizontal: 24.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Row(
children: <Widget>[
Hero(
tag: 'logo',
child: Container(
child: Image.asset('images/logo.png'),
height: 60.0,
),
),
TypewriterAnimatedTextKit(
text: ['Tonnah'],
textStyle: TextStyle(
fontSize: 45.0,
fontWeight: FontWeight.w900,
),
),
],
),
SizedBox(
height: 48.0,
),
RoundedButton(
title: 'Log In',
colour: Colors.lightBlueAccent,
onPressed: () {
Navigator.pushNamed(context, LoginScreen.id);
},
),
RoundedButton(
title: 'Register',
colour: Colors.blueAccent,
onPressed: () {
Navigator.pushNamed(context, RegistrationScreen.id);
},
),
],
),
),
);
}
}
'''
I have tried ListView and SingleChildScrollView but nothing works. This is a registration page that I will use to capture information about the user. I don't know if this is the best way of doing this or if I should be getting the user to fill out a profile after they register with their email and password.
I am new to flutter and mobile app development so please help?
TIA
Just wrap your Column with SingleChildScrollView()
STREAMBUILDER
Did not update.
I already tried to work with initState.
On another page the data changes and when you go back to this HOMEPAGE the Streambuilder did not update.
I would be really happy, when you can give me an advice.
I think thats right to use a stateful widget isn't it.
........................................................................................................................................................................skldladlkjsdlkjslkdjsdklsdjlkasjdlajdljasldjjlkadjaskdjlkasjdlkjasdjlsajdlaskjdasdlkasjkdasjkdlkasjdskajdlsajdlsajdlkasjlkJLADJLKASJDJalksjjfaskldjfkdfjdslkfjlksdafjlködsfjdjflkdsjfjljfldskjfldskflksfljsdfj
class Homepage extends StatefulWidget {
#override
HomepageState createState() => _HomepageState();
}
class _HomepageState extends State<Homepage> {
UserLevelStandGrossKlein lus = UserLevelStandGrossKlein();
SharedPreferences prefs;
UserLevelStand usl = UserLevelStand();
String name = 'Tom';
#override
void initState() {
super.initState();
}
#override
void dispose() {
lus.startWork();
usl.startWork();
super.dispose();
}
#override
Widget build(BuildContext context) {
setState(() {
lus.startWork();
usl.startWork();
});
return Scaffold(
backgroundColor: Colors.white,
body: SafeArea(
child: Column(
children: [
Row(children: [
Padding(
padding: const EdgeInsets.fromLTRB(30, 60, 0, 0),
child: RichText(
text: TextSpan(
style: TextStyle(
fontSize: 25,
color: Colors.black
),
children: <TextSpan>[
TextSpan(text: 'Guten Tag,', style: TextStyle(fontWeight: FontWeight.normal)),
TextSpan(text:'\n'+ name, style: TextStyle(fontWeight: FontWeight.bold)),
],
),
), ),
Spacer(),
GestureDetector(
onTap: (){
Navigator.push(context, MaterialPageRoute(builder: (context) => Profil()));
},
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 60, 40, 0),
child: Image.asset("assets/pic.jpg",
width: 80,),
),
)
]
),
StreamBuilder(
initialData:User(1, 'Lädt'),
stream: usl.stream(),
builder: (BuildContext context, AsyncSnapshot snapchot){
User lus = snapchot.data;
String stand2 = lus.userD <=25 ? 'Beginner': 'Fortgeschritten';
return
Padding(
padding: const EdgeInsets.fromLTRB(30, 0, 0, 0),
child: Stack(
alignment: Alignment.topLeft,
children: [Container(
height: 6,
width: 150,
decoration: BoxDecoration(
color: Colors.grey,
borderRadius: BorderRadius.all(Radius.circular(9)),
Container(color: Colors.black,),
AnimatedContainer(
duration: Duration(seconds: 5),
width: lus.userD,
height: 6,
decoration:
BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.all(Radius.circular(9)))
)],
),
);
}
I am new to Flutter. I know how to navigate from a page to another page, but the problem is, my navigation does not work. In my short experience, I realized that you cannot navigate from the stateless to the stateful widget or the opposite one.
I will share my code below. So could you please tell me what kind of mistake I am making?
Thank you. :)
Actually I was planning to remove the button because this page could be the intro page like it could show the image and text I want and after 3 seconds it could go to the MainApp() page. Maybe if you have any idea how to do it. I would like to hear that too.:)
void main() {
runApp(Intro());
}
class Intro extends StatefulWidget {
#override
_IntroState createState() => _IntroState();
}
class _IntroState extends State<Intro> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.yellow.shade300,
body: SafeArea(
child: (Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Image.asset(
'assets/dinoapp2.png',
height: 200.0,
width: 200.0,
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.only(top: 40.0),
child: Text(
'Big Title',
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'Russo One Regular',
fontSize: 30.0,
color: Colors.blueAccent),
),
),
),
Container(
margin: EdgeInsets.fromLTRB(120.0, 20, 120, 100),
child: RaisedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => MainApp()),
);
},
padding: EdgeInsets.all(20.0),
textColor: Colors.black,
color: Colors.white,
child: Text(
"Start",
style: TextStyle(fontSize: 20.0),
),
),
)
],
)),
),
),
);
}
}
class MainApp extends StatefulWidget {
#override
_MainAppState createState() => _MainAppState();
}
class _MainAppState extends State<MainApp> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.blue,
body: SafeArea(
child: Center(
child: Text('This page I want to go after I press Start button'),
),
),
),
);
}
}
Try This
void main() {
runApp(MaterialApp(
home: Intro(),
));
}
class Intro extends StatefulWidget {
#override
_IntroState createState() => _IntroState();
}
class _IntroState extends State<Intro> {
#override
void initState() {
Future.delayed(Duration(seconds: 3), () {
Route route = MaterialPageRoute(builder: (context) => MainApp());
Navigator.push(context, route);
});
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.yellow.shade300,
body: SafeArea(
child: (Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Image.asset(
'assets/dinoapp2.png',
height: 200.0,
width: 200.0,
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.only(top: 40.0),
child: Text(
'Big Title',
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'Russo One Regular',
fontSize: 30.0,
color: Colors.blueAccent),
),
),
),
Center(
child: CircularProgressIndicator(),
)
],
)),
),
);
}
}
class MainApp extends StatefulWidget {
#override
_MainAppState createState() => _MainAppState();
}
class _MainAppState extends State<MainApp> {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.blue,
body: SafeArea(
child: Center(
child: Text('This page I want to go after I press Start button'),
),
),
);
}
}
Just Add this function in your intro class
#override
void initState() {
super.initState();
Future.delayed(const Duration(seconds: 2), () {
Navigator.push( context, MaterialPageRoute(builder: (context) =>
MainApp()),
); });
}
I don't know why but I copied your code into Intro class. It didn't work. :(