Why I can't switch pages by navigator in flutter? - flutter

What I want to do is switch between my pages by using BottomAppBar in my app but it doesn't work. what make it worse is that it doesn't show me any error so I don't know where is the problem.
Thank you for your help :)
import 'package:flutter/material.dart';
import 'package:testing/SecondPage.dart';
void main() {
runApp(const MaterialApp(
title: 'MyApp',
home: MyApp(),
));
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: DefaultTabController(
length: 5,
child: Scaffold(
body: Icon(Icons.rice_bowl,size:100,color: Colors.blue,),
floatingActionButton: FloatingActionButton(
hoverElevation: 50,
onPressed: () {},
child: const Icon(Icons.mic),
),
floatingActionButtonLocation:
FloatingActionButtonLocation.centerDocked,
bottomNavigationBar: BottomAppBar(
//color: Colors.blue,
notchMargin: 10,
shape: const CircularNotchedRectangle(),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
IconButton(
onPressed: () {},
icon: const Icon(
Icons.contact_mail_outlined,
color: Colors.grey,
)),
IconButton(
onPressed: () {},
icon: const Icon(
Icons.local_activity,
color: Colors.grey,
)),
Container(
height: 1,
),
IconButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => secondPage()));
},
icon: const Icon(
Icons.safety_check,
color: Colors.grey,
)),
IconButton(
onPressed: () {},
icon: const Icon(
Icons.read_more,
color: Colors.grey,
)),
],
),
)),
),
);
}
}
here is second page:
import 'package:flutter/material.dart';
class secondPage extends StatefulWidget {
const secondPage({Key? key}) : super(key: key);
#override
State<secondPage> createState() => _secondPageState();
}
class _secondPageState extends State<secondPage> {
#override
Widget build(BuildContext context) {
return Container(
child: Icon(Icons.rice_bowl,size: 200,),
);
}
}
I did everything I found in flutter docs but still doesn't work.

I am able to navigate to a new page. However, I am not able to go back (pop) to the previous page.
Since you're pushing a completely new page, you should use a Scaffold() with an AppBar which will provide you with an option to go back to the previous screen.
You're secondPage Widget should look like this:
class secondPage extends StatefulWidget {
const secondPage({Key? key}) : super(key: key);
#override
State<secondPage> createState() => _secondPageState();
}
class _secondPageState extends State<secondPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Container(
child: Text("second page"),
),
);
}
}

Use Scaffold() Widget
Your Problem Will be Solved .

Related

My screen doesn't reflect the changes in my app though the setState method works well

I'm trying to call a StatefulWidget(i.e FirstPage()) within a MaterialApp. I'm pretty much new to flutter and I don't know where I went wrong. According to my knownledge I've used StatefulWidget to tell flutter my screen on that page is going to encounter some changes in UI. But I got no idea to fix this error.
main.dart file:
import 'package:flutter/material.dart';
import 'package:flutter_project/main.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: FirstPage());
}
}
class FirstPage extends StatefulWidget {
const FirstPage({Key? key}) : super(key: key);
#override
State<FirstPage> createState() => _FirstPageState();
}
class _FirstPageState extends State<FirstPage> {
#override
Widget build(BuildContext context) {
String buttonName = "Click";
int currentIndex = 0;
return Scaffold(
appBar: AppBar(
title: const Text("App title "),
),
body: Center(
child: currentIndex == 0
? Container(
width: double.infinity,
height: double.infinity,
color: Colors.blueAccent,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(
width: 280,
height: 80,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
side: BorderSide.none,
borderRadius: BorderRadius.circular(18),
),
backgroundColor: const Color.fromRGBO(9, 8, 99, 90),
foregroundColor: Colors.red,
),
onPressed: () {
setState(() {
buttonName = "Clicked";
//print(buttonName0);
});
},
child: Text(buttonName),
),
),
ElevatedButton(
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) {
//'BuildContext' - datatype and 'context' - variable name
return const SecondPage();
},
),
);
},
child: const Text("Move to new page"),
),
],
),
)
: Image.asset("images/img.png"),
),
bottomNavigationBar: BottomNavigationBar(
items: const [
BottomNavigationBarItem(label: "Home", icon: Icon(Icons.home)),
BottomNavigationBarItem(label: "Settings", icon: Icon(Icons.settings))
],
currentIndex: currentIndex,
onTap: (int index) {
//index value here is returned by flutter by the function 'onTap'
setState(() {
currentIndex = index;
//print(currentIndex);
});
},
),
); //Scaffold represents the skeleton of the app(displays white page)
}
}
class SecondPage extends StatelessWidget {
const SecondPage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
);
}
}
Images:
Before pressing Click and Settings button
After pressing Click and Settings looks the same
I want the screen to change the ElevatedButton Click to Clicked when onPressed() is triggered and also, the app should be able to switch settings page when the onTap() method is triggered in the bottom navigation bar.
The code worked initially when I refrained from calling an entire page of Scaffold from Material app, but as soon as I changed the part
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: FirstPage()); //<-- this part
}
}
I'm getting this error.
Put your variables outside the build method.Else it will reset to default on every build.
It will be like
class _FirstPageState extends State<FirstPage> {
//here
String buttonName = "Click";
int currentIndex = 0;
#override
Widget build(BuildContext context) {
// Not here
return Scaffold(
appBar: AppBar(
More about StatefulWidget

Close Multiple Bottom Sheet Modals in Flutter

I have two bottom sheet modals on a page. In the second modal, I do an action with cubit. On the main page, I listen to the event emitted from cubit, I want to close those two modals from the main page. I have tried these ways:
context.popRoute();
return context.read<BillCubit>().fetch();
or
context
..popRoute()
..popRoute();
return context.read<BillCubit>().fetch();
Both of those codes only close the second modal (last modal).
How to deal with it?
Just use Navigator.of(context).popUntil(ModalRoute.withName('/')); where '/' is the page route before the modals. This is going to pop all modals until it reaches the specified route.
Check out below a minimal reproducible example (also the live demo on DartPad)
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
debugShowCheckedModeBanner: false,
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
void _showModalBottomSheet({int count = 1}) {
showModalBottomSheet(
context: context,
builder: (context) {
return Container(
color: Colors.amber,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('ModalBottomSheet $count'),
const SizedBox(height: 8),
ElevatedButton(
onPressed: () => _showModalBottomSheet(count: count + 1),
child: const Text('+1'),
),
const SizedBox(height: 8),
ElevatedButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text('Close this'),
),
const SizedBox(height: 8),
ElevatedButton(
onPressed: () {
// Pop until the initial page... in that case the root page
Navigator.of(context).popUntil(ModalRoute.withName('/'));
},
child: const Text('Close all'),
),
],
),
);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Text(
'Click + to show ModalBottomSheet',
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _showModalBottomSheet,
tooltip: 'Show ModalBottomSheet',
child: const Icon(Icons.add),
),
);
}
}

How to implement modal bottom sheet with fab similar to flutter_speed_dial?

Can someone tel me how to implement modal bottom sheet with fab similar to flutter_speed_dial (https://pub.dev/packages/flutter_speed_dial). To show the bottom sheet instead of icons while fab is animated
You can try doing it like this
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
_MyHomePageState createState() {
return _MyHomePageState();
}
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Flutter Bottom Sheet"),
),
body: const Center(
child: Text("Show Bottom Sheet"),
),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add),
onPressed: () {
_showModalBottomSheet();
},
),
);
}
_showModalBottomSheet() {
showModalBottomSheet(
context: context,
builder: (context) {
return Wrap(
children: const [
ListTile(
leading: Icon(Icons.share),
title: Text('Share'),
),
ListTile(
leading: Icon(Icons.copy),
title: Text('Copy Link'),
),
ListTile(
leading: Icon(Icons.edit),
title: Text('Edit'),
),
],
);
},
);
}
}

Bounce Dismissible for helping the user

So we have a Dismissible for confirming/denying a item.
However we have some users that are trying to click/tap on the item.
Our UX team suggested that we then "bounce" the item to show that they have to swipe (and reveal the action fields).
But I don't see any option to do so.
Does anybody have a suggestion what might work for this?
The code I have for now is shown below:
Dismissible(
key: const ValueKey(0),
direction: DismissDirection.horizontal,
child: Container(
margin: EdgeInsets.symmetric(horizontal: 3, vertical: 3),
child: card(),
),
confirmDismiss: (direction) async {
var newStatus = direction == DismissDirection.startToEnd
? OkNokNvt.OK
: OkNokNvt.NOK;
_changeStatus(newStatus);
return false;
},
background: ok(),
secondaryBackground: nok(),
),
The Dismissable doesn't seeem to have this functionality.
Instead, you could use the flutter_slidable package.
Here, you can programmatically open the underlying actions by calling Slideable.of(context)?.open(). No fancy bounce-animation though.
Here's the code:
import 'package:flutter/material.dart';
import 'package:flutter_slidable/flutter_slidable.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark(),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Bouncing Widget Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Slidable(
key: const Key('key'),
actionPane: const SlidableDrawerActionPane(),
actionExtentRatio: 0.25,
child: Builder(
builder: (context) => GestureDetector(
onTap: () {
Slidable.of(context)
?.open(actionType: SlideActionType.primary);
},
child: Container(
color: Colors.grey,
height: 50,
child: const Center(child: Text('Tap me')),
),
),
),
actions: [
IconSlideAction(
caption: 'Delete',
color: Colors.red,
icon: Icons.delete,
onTap: () => print('remove me from list'),
),
],
dismissal: SlidableDismissal(
onDismissed: (_) => print('remove me from list'),
dragDismissible: true,
child: const SlidableDrawerDismissal(),
),
),
],
),
),
);
}
}
Here is my minimal example which does what you are looking for.
Basically, the GestureDetector onTap callback triggers the animation which has a bouncing-like effect by using a sin function on the _animation.value. The behaviour can be tweeked by changing the parameters cyclesPerAnimation and bounceOffset.
Simply put your Dismissible in the place of the Container and you should be good to go.
environment:
sdk: ">=2.12.0 <3.0.0"
import 'dart:math';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark(),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
late final AnimationController _animation = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 500),
);
Offset _bounceOffset(double animationValue) {
const cyclesPerAnimation = 2;
const bounceOffset = 10;
return Offset(
0,
sin(animationValue * pi * 2 * cyclesPerAnimation) * bounceOffset,
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Bouncing Widget Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
AnimatedBuilder(
animation: _animation,
builder: (context, widget) => Transform.translate(
offset: _bounceOffset(_animation.value),
child: GestureDetector(
onTap: () {
_animation.reset();
_animation.forward();
},
child: Container(
color: Colors.grey,
height: 50,
width: 200,
child: const Center(child: Text('Tap to bounce')),
),
),
),
),
],
),
),
);
}
}

Missing concrete implementation of StatelessWidget

This page is my PhotoPreviewScreen where I send the photo that comes from the camera screen to the home page after clicking the button in the code below.
I am getting some interesting errors, that I have not seen before with very little in the docs, which are in the screenshot.
Has anyone seen these before? How can I rectify?
import 'package:flutter/material.dart';
import 'dart:io';
class PhotoPreviewScreen extends StatelessWidget {
Function setData;
PhotoPreviewScreen({Key key, this.setData}) : super(key: key);
}
class _PhotoPreviewScreenState extends State<PhotoPreviewScreen> {
final String imagePath;
var image;
Future _openGallery() async {}
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () => Navigator.pop(
context), // Go back to the camera to take the picture again
child: Icon(Icons.camera_alt),
),
appBar: AppBar(title: Text('Photo Preview')),
body: Column(children: [
Expanded(child: Image.file(File(imagePath))),
const SizedBox(height: 16.0),
OutlineButton(
onPressed: () {
_openGallery();
Navigator.pop(context);
},
child: Text('Okay'),
borderSide: BorderSide(
color: Color(
0xff33333D)),
),
]),
);
}
}
errors
class PhotoPreviewScreen extends StatefulWidget {Function setData; PhotoPreviewScreen({Key key, this.setData}) : super(key: key); }
I guess it should be "StatefulWidget" instead of "StatelesWidget".
Try the below code snippets:
import 'package:flutter/material.dart';
import 'dart:io';
class PhotoPreviewScreen extends StatefulWidget {
Function setData;
PhotoPreviewScreen({Key key, this.setData}) : super(key: key);
_PhotoPreviewScreenState createState() => _PhotoPreviewScreenState();
}
class _PhotoPreviewScreenState extends State<PhotoPreviewScreen> {
final String imagePath = ' ';
var image;
Future _openGallery() async {}
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () => Navigator.pop(
context), // Go back to the camera to take the picture again
child: Icon(Icons.camera_alt),
),
appBar: AppBar(title: Text('Photo Preview')),
body: Column(children: [
Expanded(child: Image.file(File(imagePath))),
const SizedBox(height: 16.0),
OutlineButton(
onPressed: () {
_openGallery();
Navigator.pop(context);
},
child: Text('Okay'),
borderSide: BorderSide(
color: Color(
0xff33333D)),
),
]),
);
}
}