Flutter Transition Animation Issue while pushing new screen on Bottom Navigation Bar - flutter

I have a MaterialApp in which it has an IndexedStack as its homePage, to use it for BottomBarNavigation. Now, in one of the "Tab"s, I want page transitions to be done like it is done in iOS.
Part of the trick can be done using CupertinoPageRoute in Navigator.push as follows:
Navigator.of(context, rootNavigator: true).push(CupertinoPageRoute<bool>(
//fullscreenDialog: true,
builder: (BuildContext context) => new DescriptionPage(),
));
this results the new page to slide from right as an iOS app. But, I also want the first page to be shifted to right with parallax, as it says in the CupertinoPageRoute's documentation:
The page also shifts to the left in parallax when another page enters to cover it.
this will be done if the first page itself is created via "Navigator.push(CupertinoPageRoute ...", but as I mentioned, my first page is one of the main pages of the application's home.
current transition style:
the new page slides in from right, but the current page does not shift to left
as you can see, the current page does not shift to left. There might be a way to make the current page's widget to act as a widget built by a CupertinoPageRoute, so that the current page itself slides to left as the new page comes in.

In the theme: parameter of MaterialApp, try this:
MaterialApp(
theme: ThemeData( //or replace with your custom ThemeData.copywith()
pageTransitionsTheme: PageTransitionsTheme(
builders: {
TargetPlatform.android: CupertinoPageTransitionsBuilder(),
TargetPlatform.iOS: CupertinoPageTransitionsBuilder()
}
),
),
)

If you run the code below, you will see that First Tab is doing what you are seeing and second Tab is what you are expecting.
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: CupertinoStoreHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class CupertinoStoreHomePage extends StatelessWidget {
const CupertinoStoreHomePage({title});
#override
Widget build(BuildContext context) {
return CupertinoTabScaffold(
tabBar: CupertinoTabBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.bell),
title: Text('TAB1'),
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.bell_solid),
title: Text('TAB2'),
),
],
),
tabBuilder: (context, index) {
switch (index) {
case 0:
return CupertinoTabView(builder: (context) {
return CupertinoPageScaffold(
child: TAB1(),
);
});
case 1:
return CupertinoTabView(
builder: (context) {
return CupertinoPageScaffold(
child: TAB2(),
);
},
routes: {
'/screen': (ctx) => NextScreen(),
},
);
default:
return Container();
}
},
);
}
}
class TAB1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("TAB1"),
),
body: Container(
child: FlatButton(
child: Text("Go To Next Screen"),
onPressed: () => Navigator.of(context)
.push(MaterialPageRoute(builder: (_) => NextScreen())),
),
),
);
}
}
class TAB2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("TAB2"),
),
body: Container(
child: FlatButton(
child: Text("Go To Next Screen"),
onPressed: () => Navigator.of(context).pushNamed("/screen"),
)),
);
}
}
class NextScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
child: Scaffold(
appBar: AppBar(
title: Text("NextScreen"),
),
body: Container(
child: Text("NextScreen"),
),
),
);
}
}
When using Navigator.of(ctx).push the app tries to push new screen on root navigator, which in your case is tab bar but it fails to replace the tab bar, hence you see incomplete animation. But with second approach where you have defined route in relevant tab and use Push Named, the app uses navigator assigned to that tab and hence expected result.
Happy Coding!

Related

How can i remove previous route if i navigate from drawer in flutter

When I navigate from drawer to any page and return back the drawer keeps open.
For example:
The drawer contains two-button and if I button one and then back, then second and then back.
Now if I press back button of android it will repeat all activities like in chrome.
Hope you get my point. If you need to know anything else from me. let me know
Hope this helps.
void main() {
runApp(
MaterialApp(
routes: {
"/": (context) => HomePage(),
"/settings": (context) => SettingsPage(),
},
),
);
}
String _currentRoute = "/";
Widget buildDrawer(context) {
return Drawer(
child: SafeArea(
child: Column(
children: <Widget>[
ListTile(
title: Text("Home"),
onTap: () => doRoute(context, '/'),
),
ListTile(
title: Text("Settings"),
onTap: () => doRoute(context, '/settings'),
),
],
),
),
);
}
void doRoute(BuildContext context, String name) {
if (_currentRoute != name)
Navigator.pushReplacementNamed(context, name);
else
Navigator.pop(context);
_currentRoute = name;
}
// Page 1 (HomePage)
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Home")),
body: Container(color: Colors.blue.withOpacity(0.5)),
drawer: buildDrawer(context),
);
}
}
// Page 2 (SettingsPage)
class SettingsPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Settings")),
body: Container(color: Colors.orange.withOpacity(0.5)),
drawer: buildDrawer(context),
);
}
}

Textfield can't delete after page change in Pageview?

Very simple code like this
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: Scaffold(
appBar: AppBar(),
body: PageView(
children: [
Column(
children: [
TextField(),
TextField(),
],
),
Center(child: Text("2")),
Center(child: Text("3")),
Center(child: Text("4")),
],
),
),
);
}
}
Input something on the textfield, then go to the next page, then back. Can't delete anything now, but can input? If click another textfield and then click back, everything is back to normal.
you can clear your controller after clicking back from second screen to first screen, try below code
Navigator.push(
context,
new MaterialPageRoute(
builder: (BuildContext context) =>
new SecondScreen())).then((res) {
yourControllerTextField.clear();
}).catchError((err) {
print(err);
});

Why Flutter Navigator 2.0 API not work with flutter_bloc?

I am trying to make navigation by serving pages via BLoC (flutter_bloc 6.1.1).
main.dart:
class MyApp extends StatelessWidget {
List<MaterialPage> _pages = [
MaterialPage( key: ValueKey('Page1'), child: Page1() ),
];
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: BlocProvider(
create: (BuildContext context) => NavCubit(),
// WHY PAGES NOT UPDATES HERE FROM BLoC?????
child: BlocListener<NavCubit, NavState>(
listener: (context, state) {
_pages = state.pages;
},
child: Navigator(
pages: _pages,
onPopPage: (route, result) {
if ( !route.didPop(result) ) {
return false;
}
return true;
},
)
)
),
);
}
}
The first page (Page 1) has a button, clicking on which should navigate to the second page (Page2)
class Page1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => NavCubit(),
child: Scaffold(
appBar: AppBar( title: Text('Page 1') ),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("page 11111111111"),
RaisedButton(
child: Text('Go to: Page 2', style: TextStyle(fontSize: 20)),
onPressed: () {
print("goto page2 btn");
context.read<NavCubit>().navigateTo();
},
),
],
)
),
),
);
}
}
class NavCubit extends Cubit<NavState> {
...
void navigateTo() {
final navState = NavState([MaterialPage( key: ValueKey('Page2'), child: Page2() )]);
debugPrint(navState.toString());
emit(navState);
}
}
But it doesn't happen!
As far as I can see, the BLoC State are updated good. But no screen changes...
SEE PLS:
Here my full test project: https://github.com/morfair/flutter_test_app/tree/master/lib
In Page1 you are creating another NavCubit in the BlocProvider. Therefore you have 2 NavCubits in total. So when you then call context.read<NavCubit>.navigateTo(), you are calling this method on the wrong NavCubit. Try to remove the creation of a second cubit in the BlocProvider in the Page1 build method.

Flutter Breadcrumbs?

I need a dynamic "back" button on every screen/page that also shows the title of the previous screen.
Navigation is done via global navigatorKey, pushing new routes is not done from a specific screen.
Is this possible with built-in navigator or it needs to be built from scratch?
Just pass the string you want to display to the constructor of the widget which will be your next page.
Example:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
Widget build(context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: FlatButton(
onPressed: () {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) {
return Sec('title1');
}));
},
child: Text('Press here'))));
}
}
Widget backButton(context, t) {
return Row(children: [
Expanded(
child: IconButton(
icon: Icon(Icons.backspace),
onPressed: () => Navigator.pop(context),
),
),
Text(t,style:TextStyle(fontSize:16))
]);
}
class Sec extends StatelessWidget {
String t;
Sec(String x) {
t = x;
}
Widget build(context) {
return Scaffold(
appBar: AppBar(leading: backButton(context, t)),
body: Center(
child: FlatButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Press here to go back'))));
}
}
Output

Flutter not navigating to next page context error?

This is my code what i am doing it that on tap i need to go to another page ,but i am getting an error Navigator operation requested with a context that does not include a Navigator.
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
final title = 'SHA-WAY';
var FirstPage = ['SURGERIES','OPERTAION THEATER TECHNICIAN','DRESSINGS OR BANDAGES','PHYSIOTHERAPY','NURSE MALE|FEMALE',
'HOSPITAL LINEN OR STAFF UNIFORM','MEDICENS(ONLY RARE INJECTIONS)','OPERATION THEATRE INSTRUMENTS|EQUIPEMENTS'];
return MaterialApp(
title: title,
home: Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Container(
child: GridView.count(
// Create a grid with 2 columns. If you change the scrollDirection to
// horizontal, this produces 2 rows.
crossAxisCount: 2,
children: [
Card(
child: InkWell(
onTap: (){
Navigator.push(
context,
MaterialPageRoute(builder: (context) => surgeries()),
);
},
splashColor: Colors.blue,
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Icon(Icons.content_cut,size: 60.0,),
Text(FirstPage[0]),
],
)
),
),
),
This is the class where i want to navigate,
import 'package:flutter/material.dart';
class surgeries extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("SURGERIES"),
),
body: Center(
child: RaisedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Go back!'),
),
),
);
}
}
don't know what i am doing wrong just started FLUTTER and i am stuck
You can use the approach shown in the official doc,
You have to define the routes in the main.dart
MaterialApp(
// Start the app with the "/" named route. In this case, the app starts
// on the FirstScreen widget.
initialRoute: '/',
routes: {
// When navigating to the "/" route, build the FirstScreen widget.
'/': (context) => FirstScreen(),
// When navigating to the "/second" route, build the SecondScreen widget.
'/second': (context) => SecondScreen(),
},
);
Then you can navigate to the First screen to another on onTap or onPressed event like this,
Navigator.pushNamed(context, '/second');
Note: You should only have one MaterialApp in your whole app.
For more head over to official Page
Your all classes should be descendant of MaterialApp widget, to achieve that, wrap your class that placed on runApp method with MaterialApp widget, then remove all of other MaterialApp widgets from your widget tree.
void main() {
runApp(MaterialApp(home:MyApp));
}
Just tried this and work!
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'example',
debugShowCheckedModeBanner: false,
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
buttonTheme: ButtonThemeData(
buttonColor: Colors.blue,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
textTheme: ButtonTextTheme.primary
)
),
home: Esempio1()
);
}
}
class Esempio1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("WAKAWAKA"),
),
body: Container(
child: Column(
children: <Widget>[
RaisedButton(
child: Text("aasdasd"),
onPressed: (){
Navigator.push(context, MaterialPageRoute(builder: (_)=> Esempio2()));
},
)
],
),
),
);
}
}
class Esempio2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("eheh"),
),
body: Container(
child: Text("AAAAA"),
),
);
}
}