How to make this page transaction effect on flutter - flutter

How to make this page transaction effect on flutter
Example:
instagram stories

Edit
With package https://pub.dev/packages/swipedetector, you can detect SwipeDown
and In OnSwipeDown() execute your route change logical with PageRouteBuilder
SwipeDetector(
child: ... //You Widget Tree here
),
onSwipeUp: () {
setState(() {
_swipeDirection = "Swipe Up";
});
},
onSwipeDown: () {
setState(() {
_swipeDirection = "Swipe Down";
});
},
onSwipeLeft: () {
setState(() {
_swipeDirection = "Swipe Left";
});
},
onSwipeRight: () {
setState(() {
_swipeDirection = "Swipe Right";
});
},
)
please use PageRouteBuilder to build animation
full code
import 'package:flutter/material.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(
// 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,
),
home: HomePage(),
onGenerateRoute: (RouteSettings settings) {
switch (settings.name) {
case '/':
return SlideRightRoute(widget:HomePage());
break;
case '/second':
return SlideRightRoute(widget:SecondHome());
break;
}
}
);
}
}
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home'),
),
body: new Center(
child: RaisedButton(
onPressed: () {
Navigator.pushNamed(context, '/second');
},
child: Text('Second Home'),
),
),
);
}
}
class SecondHome extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Second Home'),
),
body: new Center(
child: RaisedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Go Back'),
),
),
);
}
}
class SlideRightRoute extends PageRouteBuilder {
final Widget widget;
SlideRightRoute({this.widget})
: super(
pageBuilder: (BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) {
return widget;
},
transitionsBuilder: (BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child) {
return new SlideTransition(
position: new Tween<Offset>(
begin: const Offset(1.0, 0.0),
end: Offset.zero,
).animate(animation),
child: child,
);
},
);
}

Related

Handle Android system back button in Flutter app with nested navigators

I have a Flutter app composed of "sub-apps" with different theme colors.
In a sub-app, the AppBar's back button is working as expected: it navigates back to the previous sub-app page.
However the Android system's back button is NOT working as expected: it navigates directly to the root app.
The expected back navigation in the following example should be: B3 B2 B1 A3 A2 A1. But it's B3 A3 A2 A1.
In other words, I want the Android back button to work the same way as the Flutter back button.
The same problem happens with iOS "back swipe" gesture (iosPageTransition = true).
Please try the following code on an Android device or emulator and test with the system's back button.
Note that I use multiple MaterialApps to apply a color theme to all screens of a sub-app.
Also note that WillPopScope doesn't work since it's not triggered by the system's back button.
import 'package:flutter/material.dart';
void main() {
runApp(_AppA(_PageA(1)));
}
class _ColoredApp extends StatelessWidget {
final Color color;
final Widget home;
final iosPageTransition = false;
_ColoredApp(this.color, this.home);
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
colorScheme: ColorScheme.light(primary: color),
pageTransitionsTheme: iosPageTransition
? PageTransitionsTheme(
builders: Map.fromIterable(
TargetPlatform.values,
value: (_) => const CupertinoPageTransitionsBuilder(),
),
)
: null,
),
home: home,
);
}
}
class _AppA extends _ColoredApp {
_AppA(Widget home) : super(Colors.red, home);
}
class _AppB extends _ColoredApp {
_AppB(Widget home) : super(Colors.green, home);
}
class _PageA extends StatelessWidget {
final int number;
const _PageA(this.number);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('A$number')),
body: Center(
child: ElevatedButton(
child: Text('Next'),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (context) {
if (number > 2) return _AppB(_PageB(1));
return _PageA(number + 1);
}));
},
),
),
);
}
}
class _PageB extends StatelessWidget {
final int number;
const _PageB(this.number);
#override
Widget build(BuildContext context) {
var scaffold = Scaffold(
appBar: AppBar(
leading: number == 1 ? BackButton(onPressed: () => Navigator.of(context, rootNavigator: true).pop()) : null,
title: Text('B$number'),
),
body: Center(
child: ElevatedButton(
child: Text('Next'),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (context) {
return _PageB(number + 1);
}));
},
),
),
);
return scaffold;
}
}
First of all you can't set two MaterialApp in single flutter app its wrong way to use it, in your code it initialize 2 times.Just change your theme from the page you want to update,
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
final iosPageTransition = false;
#override
Widget build(BuildContext context) {
return MaterialApp(
home: _PageA(1),
);
}
}
class _PageA extends StatelessWidget {
final int number;
const _PageA(this.number);
#override
Widget build(BuildContext context) {
return
Theme(
data: ThemeData(
colorScheme: ColorScheme.light(primary: Colors.red),
),
child: Builder(
builder: (context) {
return Scaffold(
appBar: AppBar(title: Text('A$number')),
body: Center(
child: ElevatedButton(
child: Text('Next'),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (context) {
if (number > 2) return _PageB(1);
return _PageA(number + 1);
}));
},
),
),
);
}
),
);
}
}
class _PageB extends StatelessWidget {
final int number;
const _PageB(this.number);
#override
Widget build(BuildContext context) {
return
Theme(
data: ThemeData(
colorScheme: ColorScheme.light(primary: Colors.blue),
),
child: Builder(
builder: (context) {
return Scaffold(
appBar: AppBar(
leading: BackButton(onPressed: () => Navigator.pop(context)) ,
title: Text('B$number'),
),
body: Center(
child: ElevatedButton(
child: Text('Next'),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (context) {
return _PageB(number + 1);
}));
},
),
),
);
}
),
);
}
}
As Dharini said you cannot use 2 material apps, but if you really want to, then here is the workaround for you
Issue: When you try to B(n) it pops the B as it is new material app.
|
|_ A
|_ A1
|_ A2
|_ B
|_ B1
|_B2
Resolution: Pass the BuildContext and Route from B to A and remove route on back tap of icon or android back key.
Navigator.removeRoute(context, route);
Workaround
import 'package:flutter/material.dart';
void main() {
runApp(_AppA(_PageA(1)));
}
class _ColoredApp extends StatelessWidget {
final Color color;
final Widget home;
final iosPageTransition = false;
const _ColoredApp(this.color, this.home);
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
colorScheme: ColorScheme.light(primary: color),
pageTransitionsTheme: iosPageTransition
? PageTransitionsTheme(
builders: Map.fromIterable(
TargetPlatform.values,
value: (_) => const CupertinoPageTransitionsBuilder(),
),
)
: null,
),
home: home,
);
}
}
class _AppA extends _ColoredApp {
const _AppA(Widget home) : super(Colors.red, home);
}
class _AppB extends _ColoredApp {
const _AppB(Widget home) : super(Colors.green, home);
}
class _PageA extends StatelessWidget {
final int number;
_PageA(this.number);
final bRoutes = <BuildContext, Route>{};
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('A$number')),
body: Center(
child: ElevatedButton(
child: const Text('Next'),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (context) {
if (number > 2) {
return WillPopScope(
onWillPop: () async {
if (number > 2 && bRoutes.isNotEmpty) {
Navigator.removeRoute(bRoutes.entries.last.key, bRoutes.entries.last.value);
bRoutes.remove(bRoutes.entries.last.key);
return false;
} else {
return true;
}
},
child: _AppB(_PageB(1, bRoutes)),
);
}
return _PageA(number + 1);
}));
},
),
),
);
}
}
class _PageB extends StatelessWidget {
final int number;
final Map<BuildContext, Route> bRoutes;
const _PageB(this.number, this.bRoutes);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
leading: BackButton(onPressed: () {
if (bRoutes.isNotEmpty) {
final context = bRoutes.entries.last.key;
final route = bRoutes.entries.last.value;
bRoutes.remove(bRoutes.entries.last.key);
Navigator.removeRoute(context, route);
}
})
,
title: Text('B$number'),
),
body: Center(
child: ElevatedButton(
child: const Text('Next'),
onPressed: () {
final route = MaterialPageRoute(builder: (context) {
return _PageB(number + 1, bRoutes);
});
bRoutes[context] = route;
Navigator.push(context, route);
},
),
),
);
}
}

transition animation problem in flutter when using TextField

My transition animation doesn't apply to pages that have TextField.
when I remove TextField the animation works properly.
anybody know what's wrong?
this is my slider animation:
class SlideLeftRoute extends PageRouteBuilder {
final Widget page;
SlideLeftRoute({this.page})
: super(
pageBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) =>
page,
transitionsBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) =>
SlideTransition(
position: Tween<Offset>(
begin: const Offset(1, 0),
end: Offset.zero,
).animate(animation),
child: child,
),
);
}
this is my page:
class VerifyAuthPage extends StatelessWidget {
final String phone;
final int expTime;
VerifyAuthPage({Key key, #required this.phone, #required this.expTime});
#override
Widget build(BuildContext context) {
return Scaffold(body: Container(color: Colors.red,
child: TextField(),
),);
}
this is my root app:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
statusBarColor: BanijetColors.PRIMARY,
statusBarBrightness: Brightness.light,
));
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
fontFamily: 'IranSanse',
primaryColor: Colors.PRIMARY,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: Splash(),
initialRoute: 'splash',
onGenerateRoute: (RouteSettings setting) {
return mapNamesToRoutes(setting);
},
);
}
}
this is mapNamesToRoute function:
SlideLeftRoute mapNamesToRoutes(RouteSettings setting) {
Widget destination;
final requestAuthCubit = sl<RequestAuthCubit>();
final verifyAuthCubit = sl<VerifyAuthCubit>();
switch (setting.name) {
case 'splash':
destination = Splash();
break;
case 'auth/request':
destination = MultiBlocProvider(providers: [
BlocProvider(
create: (_) => InputValidationCubit(
inputType: InputType.Phone,
inputValidator: sl<InputValidator>())),
BlocProvider.value(value: requestAuthCubit)
], child: RequestAuthPage());
break;
case 'auth/verify':
final Map<String, Object> bundle = setting.arguments;
destination = MultiBlocProvider(providers: [
BlocProvider(
create: (_) => InputValidationCubit(
inputType: InputType.VerificationCode,
inputValidator: sl<InputValidator>())),
BlocProvider.value(value: requestAuthCubit),
BlocProvider.value(value: verifyAuthCubit),
BlocProvider.value(value: sl<TimerCubit>()),
], child: VerifyAuthPage(phone: bundle['phone'], expTime: bundle['exp']));
break;
default:
destination = null;
}
return SlideLeftRoute(page: destination);
}
and this is my Splash page:
class Splash extends StatelessWidget {
#override
Widget build(BuildContext context) {
return StatefulWrapper(
onInit: () async {
Future.delayed(const Duration(milliseconds: 2000), () {
Navigator.pushReplacementNamed(context, 'auth/verify',
arguments: {'phone': '**********', 'exp': 120});
});
},
child: Scaffold(
body: Container(
child: Center(child: Text('Splash Screen')
// child: Text('Splash Screen'),
),
),
));
}
}

Flutter: How to combine PageRoute Animation with Navigator.of(context).pushNamed

I want to use animated page route on my flutter project. Now all of my routes are Named Route and I don't wanna change them. Is there any way I can use Page Route Animation with named route? Like: If I am going from PageOne() to PageTwo() using Navigator.of(context).pushNamed(PageTwo.routename), I don't wanna see default transition, May be I want to use scale animation or fade animation. Is there any way to do that?
onTap: () {
Navigator.of(context).pushNamed(
ProductsSearch.routeName,
arguments: ScreenArguments(null, null, null, null, null, null, true, false),
);
},
As your Question I have solved this demo answer try once it will work .
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
home: HomePage(),
onGenerateRoute: (RouteSettings settings) {
final SecondHome args = settings.arguments;
switch (settings.name) {
case '/':
return SlideRightRoute(widget:HomePage());
break;
case '/second':
return
SlideRightRoute(widget:SecondHome(args.data1,args.data2,args.boolvalue));
break;
}
},
),
);
}
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home'),
),
body: new Center(
child: RaisedButton(
onPressed: () {
Navigator.of(context).pushNamed(
'/second',
arguments:SecondHome("data1","data2",true),
);
},
child: Text('Second Home'),
),
),
);
}
}
class SecondHome extends StatelessWidget {
String data1;
String data2;
bool boolvalue;
SecondHome(this.data1,this.data2,this.boolvalue);
#override
Widget build(BuildContext context) {
print("Secoendhomedata${data1}");
return Scaffold(
appBar: AppBar(
title: Text('Second Home'),
),
body: new Center(
child: RaisedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Go Back'),
),
),
);
}
}
class SlideRightRoute extends PageRouteBuilder {
final Widget widget;
SlideRightRoute({this.widget})
: super(
pageBuilder: (BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) {
return widget;
},
transitionsBuilder: (BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child) {
return new SlideTransition(
position: new Tween<Offset>(
begin: const Offset(1.0, 0.0),
end: Offset.zero,
).animate(animation),
child: child,
);
},
);
}

Flutter navigation

Can someone explain why not printing efeioi when it is back from pageE?
Page A
Navigator.pushNamed(context, PageB.ROUTE).then((onValue) {
print("efeioi");
});
Page B
Navigator.of(context)
.pushReplacementNamed(PageC.ROUTE, arguments: onValue);
PageC
Navigator.pushNamed(context, PageD.ROUTE,
arguments: onValue);
PageD
Navigator.pop(context); // back to Page C
Page C
Navigator.pushNamed(context, PageE.ROUTE,
arguments: onValue);
Page E
Navigator.of(context).popUntil(ModalRoute.withName(PageA.ROUTE));
I can't use Navigator.pop in Page E because it will back to Page C!
I have uploaded full code here
https://github.com/tony123S/navigation
As per your requirement I have implemented as below
main.dart
initState : this will be called when you navigate from E to A
refreshPage : it will not called as you already popped before returning to A Page
import 'package:flutter/material.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(
primarySwatch: Colors.blue,
),
home: A(),
routes: <String, WidgetBuilder>{
'/A': (BuildContext context) => new A(),
'/B': (BuildContext context) => new B(),
'/C': (BuildContext context) => new C(),
'/D': (BuildContext context) => new D(),
'/E': (BuildContext context) => new E(),
},
);
}
}
class A extends StatefulWidget {
#override
_FirstRouteState createState() => _FirstRouteState();
}
class _FirstRouteState extends State<A> {
final String fromPage;
_FirstRouteState({Key key, #required this.fromPage});
#override
void initState() {
// TODO: implement initState
super.initState();
print("Called askdfjaksdfj");
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Page A'),
),
body: Center(
child: RaisedButton(
child: Text('Open B'),
onPressed: () {
// Navigate to second route when tapped.
// Navigator.push(
// context,
// MaterialPageRoute(builder: (context) => B()),
// );
Navigator.push(
context,
MaterialPageRoute(builder: (context) => B()),
).then((res) => refreshPage());
},
),
),
);
}
refreshPage() {
print("refresh page is called");
}
}
class B extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("B Page"),
),
body: Center(
child: RaisedButton(
onPressed: () {
// Navigate back to first route when tapped.
Navigator.of(context).pushNamed(
"/C",
);
},
child: Text('Go to C'),
),
),
);
}
}
class C extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("C Page"),
),
body: Center(
child: Column(
children: <Widget>[
RaisedButton(
onPressed: () {
// Navigate back to first route when tapped.
Navigator.pushNamed(
context,
"/D",
);
},
child: Text('Go to D'),
),
RaisedButton(
onPressed: () {
// Navigate back to first route when tapped.
Navigator.pushNamed(
context,
"/E",
);
},
child: Text('Go to E'),
),
],
),
),
);
}
}
class D extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("D Page"),
),
body: Center(
child: RaisedButton(
onPressed: () {
// Navigate back to first route when tapped.
Navigator.pop(context);
},
child: Text('Go back to C'),
),
),
);
}
}
class E extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("E Page"),
),
body: Center(
child: RaisedButton(
onPressed: () {
// Navigator.pop(context);
// Navigator.of(context).pushNamed("/A");
// Navigator.of(context).popUntil(ModalRoute.withName('/A'));
Navigator.of(context)
.pushNamedAndRemoveUntil('/A', (Route<dynamic> route) => false,);
},
child: Text('Go to A'),
),
),
);
}
}
Please run code for better understanding and reply if you found any difficulty

Navigating between Cupertino routes not working

I have a simple app that uses the Cupertino App. I have four tabs at the bottom that allows me to navigate between pages. on the last tab AddCashPage I've added on button on the page that will allow me to navigate to the second page CalendarPage
The app is only one page so I'll post the entire thing
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
// import 'styles.dart';
import 'pages/summary_page.dart';
import 'pages/calendar_page.dart';
import 'pages/remove_cash_page.dart';
final scakey = new GlobalKey<_BottomState>();
class CashOnHandApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Cash on Hand',
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: const Text('Cash on Hand'),
),
child: Bottom(key: scakey),
),
);
}
}
class Bottom extends StatefulWidget {
Bottom({Key key}) : super(key: key);
#override
_BottomState createState() => _BottomState();
}
class _BottomState extends State<Bottom> {
final myKey = new GlobalKey<_BottomState>();
int _selectedIndex = 0;
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
print(_selectedIndex);
});
}
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return CupertinoTabScaffold(
key: myKey,
tabBar: CupertinoTabBar(
onTap: _onItemTapped,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.home),
title: Text('Summary Page'),
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.clock_solid),
title: Text('Calendar'),
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.minus_circled),
title: Text('Remove Cash'),
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.plus_circled),
title: Text('Add Cash'),
),
],
),
tabBuilder: (context, index) {
switch (index) {
case 0:
return CupertinoTabView(builder: (context) {
return CupertinoPageScaffold(
child: SummaryPage(),
);
});
case 1:
return CupertinoTabView(builder: (context) {
return CupertinoPageScaffold(
child: CalendarPage(),
);
});
case 2:
return CupertinoTabView(builder: (context) {
return CupertinoPageScaffold(
child: RemoveCashPage(),
);
});
case 3:
return CupertinoTabView(builder: (context) {
return CupertinoPageScaffold(
child: AddCashPage(),
);
});
}
},
);
}
}
class AddCashPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CupertinoButton(
onPressed: () {
scakey.currentState._onItemTapped(1);
},
child: Text('data'),
),
],
),
);
}
}
I was able to use scakey.currentState._onItemTapped(1); on material app before so I thought it would work the same on a Cupertino App
According to official document https://api.flutter.dev/flutter/cupertino/CupertinoTabScaffold/tabBar.html
providing a different CupertinoTabBar.currentIndex does not affect the scaffold or the tab bar's active tab index. To programmatically change the active tab index, use a CupertinoTabController.
You need to use tab controller
code snippet
final CupertinoTabController _controller = CupertinoTabController();
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
_controller.index = index;
print(_selectedIndex);
});
}
working demo
full code
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.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(
// 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,
),
home: HomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.
// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
// This call to setState tells the Flutter framework that something has
// changed in this State, which causes it to rerun the build method below
// so that the display can reflect the updated values. If we changed
// _counter without calling setState(), then the build method would not be
// called again, and so nothing would appear to happen.
_counter++;
});
}
#override
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: Center(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
child: Column(
// Column is also a layout widget. It takes a list of children and
// arranges them vertically. By default, it sizes itself to fit its
// children horizontally, and tries to be as tall as its parent.
//
// Invoke "debug painting" (press "p" in the console, choose the
// "Toggle Debug Paint" action from the Flutter Inspector in Android
// Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
// to see the wireframe for each widget.
//
// Column has various properties to control how it sizes itself and
// how it positions its children. Here we use mainAxisAlignment to
// center the children vertically; the main axis here is the vertical
// axis because Columns are vertical (the cross axis would be
// horizontal).
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
final scakey = new GlobalKey<_BottomState>();
class CashOnHandApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Cash on Hand',
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: const Text('Cash on Hand'),
),
child: Bottom(key: scakey),
),
);
}
}
class Bottom extends StatefulWidget {
Bottom({Key key}) : super(key: key);
#override
_BottomState createState() => _BottomState();
}
class _BottomState extends State<Bottom> {
final myKey = new GlobalKey<_BottomState>();
int _selectedIndex = 0;
final CupertinoTabController _controller = CupertinoTabController();
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
_controller.index = index;
print(_selectedIndex);
});
}
#override
void initState() {
super.initState();
}
#override
void dispose() {
_controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return CupertinoTabScaffold(
controller: _controller,
key: myKey,
tabBar: CupertinoTabBar(
onTap: _onItemTapped,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.home),
title: Text('Summary Page'),
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.clock_solid),
title: Text('Calendar'),
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.minus_circled),
title: Text('Remove Cash'),
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.plus_circled),
title: Text('Add Cash'),
),
],
),
tabBuilder: (context, index) {
switch (index) {
case 0:
return CupertinoTabView(builder: (context) {
return CupertinoPageScaffold(
child: SummaryPage(),
);
});
case 1:
return CupertinoTabView(builder: (context) {
return CupertinoPageScaffold(
child: CalendarPage(),
);
});
case 2:
return CupertinoTabView(builder: (context) {
return CupertinoPageScaffold(
child: RemoveCashPage(),
);
});
case 3:
return CupertinoTabView(builder: (context) {
return CupertinoPageScaffold(
child: AddCashPage(),
);
});
}
},
);
}
}
class AddCashPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CupertinoButton(
onPressed: () {
scakey.currentState._onItemTapped(1);
},
child: Text('data'),
),
],
),
);
}
}
class SummaryPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Text("Summary");
}
}
class CalendarPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Text("Calendar");
}
}
class RemoveCashPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Text("RemoveCash");
}
}