I'm building a simple ordering app with a splash screen , and i'm having trouble on making the app to not go back on the splash screen ,I have tried a conditional operator to solve the problem, but its not doing anything, is there any other alternatives to achieve that??
import "package:flutter/material.dart";
import 'package:propapp/tabs/main.dart';
import 'dart:async';
bool loaded = false;
void main() => runApp(new MaterialApp(
theme: ThemeData(
primaryColor: Colors.amber,
accentColor: Colors.amberAccent,
),
debugShowCheckedModeBanner: false,
home: loaded == true ? Menu() : SplashScreen()));
class SplashScreen extends StatefulWidget {
#override
_SplashScreenState createState() => new _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
#override
void initState() {
super.initState();
new Future.delayed(
const Duration(seconds: 3),
() => Navigator.push(
context,
MaterialPageRoute(builder: (context) => Menu()),
));
loaded = true;
}
}
You can use Navigator.pushReplacement. Remove your condition again:
...
home: SplashScreen()));
And the only other change will be replacing Navigator.push with pushReplacement:
... => Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => Menu()),
)
This will remove the SplashScreen route from the navigator stack and thus never go back to it.
There is a useful plugin in https://pub.dartlang.org called SplashScreen will offer you this functionality and other ones like a splash timer, here's the link:
https://pub.dartlang.org/packages/splashscreen
Related
Managed to create a simple reproduction of an error I've come across in my real program, and I'm not sure why this kind of a thing happens. I think if I can understand this, it might help me.
The key here is that I HAVE to have the two pieces of the program separated in this manner, and they need to communicate, but that communication isn't happening the way I would expect. (So please don't suggest I put the timer function inside the rest of the program).
import 'package:flutter/material.dart';
import 'dart:async';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool textBool = false;
void textChanger() {
if (textBool) {
setState(() {
textBool = false;
});
} else {
setState(() {
textBool = true;
});
}
}
Text myText() {
if (textBool) {
Text newText = new Text('Original Text');
return newText;
} else {
Text newText = new Text('New Text');
return newText;
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: myText(),
),
floatingActionButton: FloatingActionButton(
onPressed: stateModify,
tooltip: 'Change Text',
),
);
}
}
Future<void> stateModify() {
Duration waitTimer = new Duration(seconds: 5);
new Timer.periodic(waitTimer, (timer) {
_MyHomePageState().textChanger();
timer.cancel();
});
}
Expected functionality: Click the button and 5 seconds later it should change to the second set of text. Then I should be able to click the button again and switch it back.
Instead in this example I receive the following error:
[VERBOSE-2:ui_dart_state.cc(157)] Unhandled Exception: setState() called in constructor: _MyHomePageState#a5177(lifecycle state: created, no widget, not mounted)
And google doesn't seem to be super helpful on this particular issue.
Any suggestions?
Your stateModify function is not a method of _MyHomePageState. Also when you are accessing the _MyHomePageState().textChanger() in stateModify you are eventually creating a new object of _MyHomePageState() but not inserting in render tree.
You should use Timer instead of Timer.periodic. The Timer.periodic will repeat the task until the Timer.cancel is called. Timer will do a callback after the given time period which you require.
Pass the function textChanger when you are calling stateModify that way you will be able to call the function of _MyHomePageState without creating a new object.
Do the following changes.
floatingActionButton: FloatingActionButton(
onPressed: ()=> stateModify(textChanger),
tooltip: 'Change Text',
),
stateModify(dynamic function) {
Timer(Duration(seconds: 5), function);
}
I am creating an app using Flutter.
On iOS however (you can also test it on Android), dark theme is not applied.
Using Android widgets, it is working fine tho.
How can I make the Cupertino widgets using the dark theme? Especially for the popups.
I am using Flutter 1.9.1+hotfix6
E.g. the Cupertino "ActionSheet":
import 'package:flutter/material.dart';
import 'home.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData.dark(),
darkTheme: ThemeData.dark(),
home: Home(),
);
}
}
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class Home extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Center(
child: RaisedButton(
child: Text('test'),
onPressed: () {
Widget secondaryButton, confirmButton, popup;
secondaryButton = CupertinoActionSheetAction(
child: Text('secundary'),
onPressed: () {},
);
confirmButton = CupertinoActionSheetAction(
child: Text('test'),
onPressed: () {},
);
popup = CupertinoActionSheet(
title: Text('Title'),
message: Text('Content'),
cancelButton: secondaryButton,
actions: [confirmButton],
);
showCupertinoModalPopup(
context: context, builder: (context) => popup);
},
),
);
}
}
Screenshot:
Check this repo, you can create platform specific layouts only using a single widget that does all the platform specific boilerplate for you.
Also have support for dark mode, at least in iOS.
it is showing this error
Could not find a generator for route in the _WidgetsAppState.
How can I navigate if my app has two MaterialApp widgets?
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primaryColor: Colors.brown,
accentColor: Colors.blue,
),
debugShowCheckedModeBanner: false,
home: SplashScreen(),
routes: <String, WidgetBuilder>{
'/HomeScreen': (BuildContext context) => new HomeScreen(),
},
);
}
}
Can you provide more code showing how you triggering that route? Seems like you're using the first screen as a splash screen. If you navigate to HomeScreen() when some button is pressed then try using MaterialPageRoute() without using routes.
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => new HomeScreen()))
It would be better if you provided some code but you can use GlobalKey.
I have three screens. A, B and C. I push A, B, and C by using the following code. A is the first screen of the app.
class FadeInSlideOutRoute<T> extends MaterialPageRoute<T> {
FadeInSlideOutRoute({WidgetBuilder builder, RouteSettings settings})
: super(builder: builder, settings: settings);
#override
Widget buildTransitions(BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child) {
if (settings.isInitialRoute)
return child;
// Fades between routes. (If you don't want any animation,
// just return child.)
return new FadeTransition(opacity: animation, child: child);
}
}
Screen declare in build method.
#override
Widget build(BuildContext context) {
return new MaterialApp(
debugShowCheckedModeBanner: false,
theme: new ThemeData(
primarySwatch: Colors.blue,
),
onGenerateRoute: (RouteSettings settings) {
switch (settings.name) {
case '/B':
return new FadeInSlideOutRoute(
builder: (_) => new LoginScreen(),
settings: settings,
);
case '/C':
return new FadeInSlideOutRoute(
builder: (_) => new ForgotPasswordScreen(),
settings: settings,
);
}
assert(false);
},
home: _LandingScreen(),
);
}
Now, I'm calling the following method to push new screens.
Navigator.pushNamed(context, '/B');
After that
Navigator.pushNamed(context, '/C');
issue is
when I'm pressing back of Android device from screen C it's come to screen A directly. But it should on screen B. Please help guys.
I encountered a problem when I set the SystemUiOverlay.bottom on my appbarwidget using SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.bottom]) and noticed that status bar is hidden but once I pull down upper side of the screen it shows and doesn't disappear again. So I came up with the idea to add a gesture detector for the whole widget app to hide it all the time when you press anywhere on the screen. And I am wondering if this is the best solution and there will not be any issues with the performance or whatever. Any thoughts?
void main() => runApp(PlanetsApp());
class PlanetsApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new GestureDetector(
onTap: () => SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.bottom]),
child: new MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Planets App',
color: Colors.purple,
home: HomeScreen(),
),
);
}
}
After switching to Flutter I also noticed this behavior :(
I dont want to use GestureDetector, and I am not sure where to place SystemChrome.setEnabledSystemUIOverlays so it hides the bar properly...
Instead, I did this: in the Android styles.xml where the App theme is I've added:
<item name="android:windowNoTitle">true</item>
<item name="android:windowFullscreen">true</item>
This makes the sys-bar to always disappear when the app gets clicked
change your code to this.
SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values);
For the issue (https://github.com/flutter/flutter/issues/14432) mentioned in comment, I've found a temporary solution. When you hide status bar or bottom bar, Appbar's height remains same and it takes too much space, especially when you are using landscape mode. To fix this, set "primary" property of Scaffold and Appbar false.
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
void initState() {
SystemChrome.setEnabledSystemUIOverlays([]);
super.initState();
}
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
primary: false,
appBar: AppBar(
primary: false,
backgroundColor: Colors.blue,
),
body: Center(child: Text("It works!")),
),
);
}
}
Hope it helps!
There is not fix for this as of right now. When status bar is hidden, app bar's height remains the same.
See the github issue: https://github.com/flutter/flutter/issues/14432