Flutter Custom SideBar Not Taking Full Height - flutter

I am working on a custom sidebar for my app since I dont like the default drawer that flutter comes with.
Everything works fine, that is, the sidebar takes the entire height of the mobile phone
until I render the page contents along the sidebar as shown below
Here's the Main contents code:
import 'package:api_example_app/LandingScreen/components/control_button.dart';
import 'package:api_example_app/LandingScreen/components/default_button.dart';
import 'package:api_example_app/SensorScreen/charts/GasChart.dart';
import 'package:api_example_app/SensorScreen/charts/HumChart.dart';
import 'package:api_example_app/SensorScreen/charts/MoisChart.dart';
import 'package:api_example_app/SensorScreen/charts/NurChart.dart';
import 'package:api_example_app/SensorScreen/charts/PhChart.dart';
import 'package:api_example_app/SensorScreen/charts/TemChart.dart';
import 'package:api_example_app/SensorScreen/charts/chartComponents/HumCard.dart';
import 'package:api_example_app/SensorScreen/components/sensor_screen.dart';
import 'package:api_example_app/constants.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
class LandingScreenBody extends StatefulWidget {
#override
_LandingScreenBodyState createState() => _LandingScreenBodyState();
}
class _LandingScreenBodyState extends State<LandingScreenBody> {
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Padding(
padding: EdgeInsets.symmetric(horizontal: size.width * 0.05),
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
SizedBox(height: size.height * 0.1),
Center(
child: Text(
'ngDAQ',
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black,
fontSize: 25,
),
),
),
SizedBox(height: size.height * 0.01),
Center(
child: Text(
'The ngDAQ is a Smart Agriculture solution based on IoT, seeking to increase farm productivity by automation and monitoring.',
textAlign: TextAlign.center,
style: TextStyle(color: kDarkGreyColor, fontSize: 12),
),
),
SizedBox(height: size.height * 0.05),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
CardsParent(
size: size,
icon: FontAwesomeIcons.temperatureHigh,
title: 'Tem',
subtitle: '33C',
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => new TemChart()));
},
),
CardsParent(
size: size,
title: 'Hum ',
subtitle: '75%',
icon: FontAwesomeIcons.cloudShowersHeavy,
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => new HumChart()));
},
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
CardsParent(
size: size,
icon: FontAwesomeIcons.hourglass,
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => new MoisChart()));
},
title: 'Mos',
subtitle: '40',
),
CardsParent(
size: size,
title: 'PH ',
subtitle: '14',
icon: FontAwesomeIcons.meteor,
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => new PhChart()));
},
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
CardsParent(
size: size,
icon: FontAwesomeIcons.leaf,
title: 'Nur',
subtitle: 'Good',
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => new NurChart()));
},
),
CardsParent(
size: size,
title: 'Gas ',
subtitle: 'Good',
icon: FontAwesomeIcons.flask,
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => new GasChart()));
},
),
],
),
SizedBox(height: size.height * 0.05),
// DefaultButton(
// size: size,
// title: "Next",
// press: () {
// Navigator.push(
// context,
// CupertinoPageRoute(
// builder: (context) => SensorScreen(),
// ),
// );
// },
// ),
],
),
),
);
}
}
Heres' the Sidebar Code:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:rxdart/rxdart.dart';
// import 'package:rxdart/rxdart.dart';
import '../../constants.dart';
class SideBar extends StatefulWidget {
// const SideBar({Key ? key}) : super(key: key);
#override
_SideBarState createState() => _SideBarState();
}
class _SideBarState extends State<SideBar>
with SingleTickerProviderStateMixin<SideBar> {
AnimationController _animationController;
StreamController<bool> isSidebarOpenedStreamController;
Stream<bool> isSidebarOpenedStream;
StreamSink<bool> isSidebarOpenedSink;
// final bool isSidebarOpened = true;
final _animationDuration = const Duration(milliseconds: 500);
#override
void initState() {
super.initState();
_animationController =
AnimationController(vsync: this, duration: _animationDuration);
isSidebarOpenedStreamController = PublishSubject<bool>();
isSidebarOpenedStream = isSidebarOpenedStreamController.stream;
isSidebarOpenedSink = isSidebarOpenedStreamController.sink;
}
#override
void dispose() {
_animationController.dispose();
isSidebarOpenedStreamController.close();
isSidebarOpenedSink.close();
super.dispose();
}
void onIconPressed() {
final animationStatus = _animationController.status;
final isAnimationCompleted = animationStatus == AnimationStatus.completed;
if (isAnimationCompleted) {
isSidebarOpenedSink.add(false);
_animationController.reverse();
} else {
isSidebarOpenedSink.add(true);
_animationController.forward();
}
}
#override
Widget build(BuildContext context) {
final screenWidth = MediaQuery.of(context).size.width;
return StreamBuilder<bool>(
initialData: false,
stream: isSidebarOpenedStream,
builder: (context, isSideBarOpenedAsync) {
return AnimatedPositioned(
duration: _animationDuration,
top: 0,
bottom: 0,
left: isSideBarOpenedAsync.data ? 0 : 0,
right: isSideBarOpenedAsync.data ? 0 : screenWidth - 45,
child: Row(
children: <Widget>[
Expanded(
child: Container(
color: kOrangeColor,
child: Column(
children: <Widget>[],
),
),
),
Align(
alignment: Alignment(0, -0.9),
child: GestureDetector(
onTap: () {
onIconPressed();
},
child: Container(
width: 35,
height: 80,
color: kOrangeColor,
alignment: Alignment.centerLeft,
child: AnimatedIcon(
progress: _animationController.view,
icon: AnimatedIcons.menu_close,
color: Colors.white,
size: 30,
),
),
),
),
],
),
);
},
);
}
}
The Layout Where the render is done:
import 'package:api_example_app/LandingScreen/components/body.dart';
import 'package:flutter/material.dart';
import '../../constants.dart';
import 'sidebar.dart';
class SideBarLayout extends StatelessWidget {
// const SideBarLayout({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
LandingScreenBody(),
SideBar(),
],
),
);
}
}
I dont know what I did wrong.

Inside SideBar, you need to surround it with Container widget, and set its height to double.infinity;
//Inside SideBar
return Container(
width: 200,
height: double.infinity,
child: StreamBuilder<bool> (
...
);
);

I solved it, thanks to #eyoeldefare.
From the main home, where I returned padding, I [return container instead, then, add:
return Container(
height: double.infinity,
(
...
),
);

Related

Flutter ListView doesn't get constrained by wrapping it in Expanded

I'm struggling hard with Flutter's sizing constraints.
I'm trying to make a custom scaffold like screen with a custom appbar and a stack below it with the lowest layer being a listview, and then maybe floating buttons on top if that.
I can't figure out what the proper solution would be to make the listview not throw "vertical viewport was given unbounded height" error.
Here's my code:
import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/container.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:my/model.dart';
import 'package:my/widgets/menucard.dart';
import 'package:my/screens/my1.dart';
import 'package:my/screens/my2.dart';
import 'package:my/screens/my3.dart';
import 'package:my/provider.dart';
class myAppBar extends StatelessWidget {
myAppBar(
{super.key,
required double height,
required String title,
bool autoImplyBack = true})
: _height = height,
_title = title,
_autoback = autoImplyBack;
#override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
height: _height,
color: Colors.pink,
child: SizedBox(
width: double.infinity,
height: _height,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(
width: _height,
height: _height,
child: Navigator.canPop(context) && _autoback
? IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(Icons.arrow_back),
)
: null,
),
Center(
child: Text(_title),
),
SizedBox(
width: _height,
height: _height,
child: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(Icons.close),
),
),
],
),
),
);
}
double _height;
String _title;
bool _autoback;
}
class myMenu extends StatelessWidget {
const myMenu({super.key});
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
myAppBar(height: 100, title: 'Menu'),
Container(
color: Colors.teal,
child: Expanded(
child: //Stack(
//children: [
ListView(
children: [
MenuCard(
icondata: Icons.circle,
subMenu: 'my1',
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const my1()),
);
}),
MenuCard(
icondata: Icons.circle,
subMenu: 'my2',
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const my2()),
);
}),
MenuCard(
icondata: Icons.circle,
subMenu: 'my3',
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const my3()),
);
}),
MenuCard(
icondata: Icons.circle,
subMenu: 'log out',
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const my1()),
);
}),
],
),
//],
),
),
//),
],
),
);
}
}
I've tried setting the listview's shrinkwrap property to true, but that turned out to be ugly as well as not so much performant according to other threads regarding this topic.
I've also tried wrapping the listview in Expanded and Flexible, but to no avail.
You can shift the Expanded widget on top of Container.
body: Column(
children: [
myAppBar(height: 100, title: 'Menu'),
Expanded(
child: Container(
Also while you are trying to create custom AppBar, you can implements PreferredSizeWidget
class myAppBar extends StatelessWidget implements PreferredSizeWidget {
.... //get height using constructor.
#override
Widget build(BuildContext context) {
return Container(height:);
}
#override
Size get preferredSize => Size.fromHeight(height);
}

Will Pop Scope is not working on video player screen in flutter

I applied will pop scope on that screen it didn't work me its YouTube video player screen. I define all the routes in main.dart is that problem will pop scope is not working Let me know where I am going wrong
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:stocker/models/YouTubeStateModel.dart';
import 'package:youtube_player_flutter/youtube_player_flutter.dart';
class VideoPlayer extends StatefulWidget {
const VideoPlayer({
Key? key,
required this.videoID,
required this.data,
}) : super(key: key);
static const routeName = '/videoPlayer';
final YouTubeState data;
final String videoID;
#override
State<VideoPlayer> createState() => _VideoPlayerState();
}
class _VideoPlayerState extends State<VideoPlayer> {
late YoutubePlayerController _controller;
#override
void initState() {
super.initState();
_controller = YoutubePlayerController(
initialVideoId: widget.videoID,
flags: const YoutubePlayerFlags(
autoPlay: true,
mute: false,
),
);
Future.delayed(
const Duration(milliseconds: 300),
).then((value) {
_controller.toggleFullScreenMode();
_controller.setSize(Size(1.sw, 1.sh));
});
}
#override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;
final width = size.width;
final height = size.height;
_controller.setSize(
width > height
? Size(1.sw - ScreenUtil().statusBarHeight, 1.sh)
: Size(1.sw, 1.sh - ScreenUtil().statusBarHeight),
);
return WillPopScope(
onWillPop: () async {
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
]);
Navigator.of(context).pop();
return false;
},
child: Stack(
children: [
YoutubePlayerBuilder(
player: YoutubePlayer(
bottomActions: [
const SizedBox(width: 14.0),
CurrentPosition(),
const SizedBox(width: 8.0),
ProgressBar(
isExpanded: true,
// colors: widget,
),
RemainingDuration(),
const PlaybackSpeedButton(),
],
// aspectRatio: width > height
// ? (width - ScreenUtil().statusBarHeight) / height
// : (width) / (height - ScreenUtil().statusBarHeight),
aspectRatio: width > height
? height / (width - ScreenUtil().statusBarHeight)
: (height - ScreenUtil().statusBarHeight) / (width),
controller: _controller,
width: size.width,
),
builder: (context, player) {
return Scaffold(
backgroundColor: Colors.black,
body: Padding(
padding: EdgeInsets.only(top: ScreenUtil().statusBarHeight),
child: SizedBox(
height: 1.sh - ScreenUtil().statusBarHeight,
width: 1.sw,
child: Stack(
children: [
Center(child: player),
// Positioned(
// bottom: 100,
// right: 100,
// child: GestureDetector(
// onTap: Navigator.of(context).pop,
// child: SvgPicture.asset(
// 'assets/svg/back_arrow.svg',
// color: Colors.white,
// width: 24.h,
// height: 24.h,
// ),
// ),
// ),
],
),
),
),
);
},
),
Positioned(
left: 5.w,
top: 30.h,
child: GestureDetector(
onTap: () {
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
]);
Navigator.of(context).pop();
},
child: SvgPicture.asset(
'assets/svg/back_arrow.svg',
color: Colors.white,
width: 16.w,
height: 16.w,
),
),
)
],
),
);
}
}
I applied Will pop scope on the main stack and inside the builder Scaffold as well but at both of the places it didn't work let me know how can I tackle this problem .
/* ::::::::::::::::::::::: OnWillPop show dialog :::::::::::::::::::::::*/
WillPopScope(
onWillPop: () {
return openDialog();
},)
openDialog() {
Get.dialog(
AlertDialog(
title: const Text('Are Yor Sure?'),
content: const Text('Do you want to exit this App'),
actions: [
TextButton(
onPressed: () => Get.back(),
child: const Text("No"),
),
TextButton(
onPressed: () {
if (Platform.isAndroid) {
SystemNavigator.pop(); // or
// Navigator.pushAndRemoveUntil(
// context,
// MaterialPageRoute(builder: (context) => HomePage()),
// (route) => false);
print("android>>>>");
} else if (Platform.isIOS) {
exit(0);
}
},
child: const Text("Yes"),
),
],
),
);
}
2nd way
onWillPop: () async {
final shouldPop = await showDialog<bool>(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('Do you want to go back?'),
actionsAlignment: MainAxisAlignment.spaceBetween,
actions: [
TextButton(
onPressed: () {
Navigator.pop(context, true);
},
child: const Text('Yes'),
),
TextButton(
onPressed: () {
Navigator.pop(context, false);
},
child: const Text('No'),
),
],
);
},
);
return shouldPop!;
},

flutter Problem: How to update number of items count in cart?

I implement to add to cart functionality items added into cart successfully but the number of count in the cart badge is not updated when I reload dart page than the number of count updates.can anyone help me?
I implement to add to cart functionality items added into cart successfully but the number of count in the cart badge is not updated when I reload dart page than the number of count updates.can anyone help me?
This is my Homepage.dart
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:badges/badges.dart';
import 'package:hospital/BestDeatProducts/best_deal_product_page.dart';
import 'package:hospital/CartPage/pages/cartPage.dart';
import 'package:hospital/Drawer/dropdown_menu.dart';
import 'package:hospital/FirstSection/carousel.dart';
import 'package:hospital/Drawer/drawercontent.dart';
import 'package:hospital/FloatingActionButton/ConsultWithDoctor/consult_with_doctor.dart';
import 'package:hospital/MedicineCateory/medicine_category_page.dart';
import 'package:hospital/SecondSection/second_page.dart';
import 'package:hospital/ThirdSection/third_page.dart';
import 'package:hospital/TrendingProducts/trending_product_page.dart';
import 'package:hospital/constant.dart';
import 'package:hospital/customApiVariable.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'No Internet/connectivity_provider.dart';
import 'No Internet/no_internet.dart';
import 'package:http/http.dart' as http;
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
SharedPreferences loginData;
// late String username;
Future getUsername() async {
loginData = await SharedPreferences.getInstance();
setState(() {
// print("uname" + uname.toString());
print("dddpppuu1 : responceData_un" +
loginData.getString('responceData_un').toString());
print("dddpppuu2 : responceData_ue" +
loginData.getString('responceData_ue').toString());
print("dddpppuu3 : responceData_status" +
loginData.getString('responceData_status').toString());
String responceData_uid =
loginData.getString('responceData_uid').toString();
fetchData(responceData_uid);
});
}
var response;
var addToCartApi;
#override
void initState() {
// TODO: implement initState
//
super.initState();
Provider.of<ConnectivityProvider>(context, listen: false).startMonitering();
// for loading
getUsername();
}
fetchData(String argResponceData_uid) async {
var api = Uri.parse(
'$ecommerceBaseUrl/addToCartApi.php?a2rTokenKey=$a2rTokenKey&action=addToCartList&uid=${argResponceData_uid}');
print('cartpage' + api.toString());
response = await http.get(api);
print("Carousel" + response.body);
addToCartApi = jsonDecode(response.body);
print('addToCartApi' + addToCartApi['total'].toString());
print('totalPriceAfterOffer' + totalPriceAfterOffer.toString());
setState(() {});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: kGreen,
title: Text(
"BK Arogyam",
style: TextStyle(fontStyle: FontStyle.italic),
),
actions: [
response != null
? Badge(
position: BadgePosition.topEnd(top: 3, end: 18),
animationDuration: Duration(milliseconds: 300),
animationType: BadgeAnimationType.slide,
badgeContent: Text(
addToCartApi['total']['num'].toString(),
style: TextStyle(color: Colors.white),
),
child: IconButton(
icon: Icon(Icons.shopping_cart),
padding: EdgeInsets.only(right: 30.0),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Cartpage()),
);
}),
)
: IconButton(
icon: Icon(Icons.shopping_cart),
// onPressed: () => print("open cart"),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Cartpage()),
);
},
),
DropDownMenu(),
],
),
floatingActionButton: FloatingActionButton(
backgroundColor: kGreen,
onPressed: () => Navigator.push(context,
MaterialPageRoute(builder: (context) => ConsultWithDoctor())),
tooltip: 'Consult With Doctor',
child: Container(
child: Image(
image: AssetImage(
"assets/icons/cwd.png",
),
color: Colors.white,
width: 40,
height: 40,
),
),
),
drawer: Drawer(
child: DrawerContent(),
),
body: pageUI());
}
Widget pageUI() {
return Consumer<ConnectivityProvider>(
builder: (consumerContext, model, child) {
if (model.isOnline != null) {
return model.isOnline
? ListView(
children: [
Carousel(),
SizedBox(
height: 10.0,
),
MedicineCategoryPage(),
SizedBox(
height: 10.0,
),
SecondPage(),
SizedBox(
height: 10.0,
),
ThirdPage(),
SizedBox(
height: 10.0,
),
TrendingProductPage(),
SizedBox(
height: 16.0,
),
BestDealProductPage(),
SizedBox(
height: 10.0,
),
],
)
: NoInternet();
}
return Container(
child: Center(
child: CircularProgressIndicator(),
),
);
},
);
}
}
You can use the change notifier provide by provider package.
And watch the video on how to use, exactly for ur use case search YouTube change notifier provider by the growing developer
Hope it helps 🙂
You can use provider(provider: ^5.0.0) or Getx(get: ^4.1.4) to handle this kind of case.
There are lots of examples are available for GetX and Provider.
If you don't want to use any of them, Then store your cart/badge count to tempCartCount variable(Example: int cartCount = 0) and set it to the badge count instead of "addToCartApi['total']['num'].toString()" , Make sure to setState on update/addCart Item.
Here I provide a simple example of how to update count on appBar.
if you want to change from any other screen make cartCount to global otherwise you can set it local/private.
import 'package:badges/badges.dart';
import 'package:flutter/material.dart';
class UpdateCountExample extends StatefulWidget {
#override
_UpdateCountExampleState createState() => _UpdateCountExampleState();
}
int cartCount = 0;
class _UpdateCountExampleState extends State<UpdateCountExample> {
List<String> cartArray = [];
#override
void initState() {
WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
setState(() {
cartCount = 0;
});
});
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("App Bar"),
actions: [
Padding(
padding: const EdgeInsets.only(right: 18.0, top: 5.0),
child: Badge(
badgeContent: Text(cartCount.toString()),
child: Icon(Icons.add_shopping_cart),
),
)
],
),
body: Container(
alignment: Alignment.center,
padding: EdgeInsets.all(20),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
"Add item in cart",
textAlign: TextAlign.center,
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18, decoration: TextDecoration.none, color: Colors.black),
),
SizedBox(
height: 20,
),
InkWell(
onTap: () {
setState(() {
cartArray.add("value ${cartArray.length}");
cartCount = cartArray.length;
});
},
child: Container(
padding: const EdgeInsets.all(10.0),
color: Colors.amber,
child: Text(
"Add Item",
textAlign: TextAlign.center,
style: TextStyle(fontSize: 15, decoration: TextDecoration.none, color: Colors.black),
),
),
),
Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: cartArray.length,
itemBuilder: (context, index) {
return Text(
cartArray[index],
style: TextStyle(fontSize: 20, color: Colors.black),
);
}),
)
],
),
),
);
}
}
I have used StreamBuilder to update cart items instantly.
You can use the code from this post
How to use Streambuilder in flutter

Why isn't Navigator.pop() refreshing data?

Hi guys I'm trying to build an app with flutter, so I have two screens HomeScreen() and RoutineScreen(). The first one is a Scaffold and in the body has a child Widget (a ListView called RoutinesWidget()) with all the routines. And the second one is to create a routine. The thing is, that when I create the routine, I use a button to pop to the HomeScreen() but it doesn't refresh the ListView (I'm guessing that it's because when I use Navigator.pop() it refreshes the Scaffold but not the child Widget maybe?)
HomeScreen() code here:
import 'package:flutter/material.dart';
import 'package:workout_time/constants.dart';
import 'package:workout_time/Widgets/routines_widget.dart';
import 'package:workout_time/Widgets/statistics_widget.dart';
import 'package:workout_time/Screens/settings_screen.dart';
import 'package:workout_time/Screens/routine_screen.dart';
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
int _selectedIndex = 0;
List<Widget> _views = [
RoutinesWidget(),
StatisticsWidget(),
];
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: kThirdColor,
appBar: AppBar(
leading: Icon(Icons.adb),
title: Text("Workout Time"),
actions: <Widget>[
IconButton(
icon: Icon(Icons.settings),
onPressed: () => Navigator.push(context,
MaterialPageRoute(builder: (context) => SettingsScreen()))),
],
),
body: _views[_selectedIndex],
floatingActionButton: (_selectedIndex == 1)
? null
: FloatingActionButton(
onPressed: () async {
await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => RoutineScreen(null)));
setState(() {});
},
child: Icon(
Icons.add,
color: kSecondColor,
size: 30.0,
),
elevation: 15.0,
),
bottomNavigationBar: BottomNavigationBar(
items: <BottomNavigationBarItem>[
bottomItems(Icon(Icons.fitness_center_rounded), "Routines"),
bottomItems(Icon(Icons.leaderboard_rounded), "Statistics"),
],
currentIndex: _selectedIndex,
onTap: (int index) => setState(() => _selectedIndex = index),
),
);
}
}
BottomNavigationBarItem bottomItems(Icon icon, String label) {
return BottomNavigationBarItem(
icon: icon,
label: label,
);
}
RoutinesWidget() code here:
import 'package:flutter/material.dart';
import 'package:workout_time/Services/db_crud_service.dart';
import 'package:workout_time/Screens/routine_screen.dart';
import 'package:workout_time/constants.dart';
import 'package:workout_time/Models/routine_model.dart';
class RoutinesWidget extends StatefulWidget {
#override
_RoutinesWidgetState createState() => _RoutinesWidgetState();
}
class _RoutinesWidgetState extends State<RoutinesWidget> {
DBCRUDService helper;
#override
void initState() {
super.initState();
helper = DBCRUDService();
}
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: helper.getRoutines(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
Routine routine = Routine.fromMap(snapshot.data[index]);
return Card(
margin: EdgeInsets.all(1.0),
child: ListTile(
leading: CircleAvatar(
child: Text(
routine.name[0],
style: TextStyle(
color: kThirdOppositeColor,
fontWeight: FontWeight.bold),
),
backgroundColor: kAccentColor,
),
title: Text(routine.name),
subtitle: Text(routine.exercises.join(",")),
trailing: IconButton(
icon: Icon(Icons.delete_rounded),
color: Colors.redAccent,
onPressed: () {
setState(() {
helper.deleteRoutine(routine.id);
});
},
),
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => RoutineScreen(routine))),
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0)),
color: kSecondColor,
);
},
);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
);
}
}
RoutineScreen() code here:
import 'package:flutter/material.dart';
import 'package:workout_time/Models/routine_model.dart';
import 'package:workout_time/Widgets/type_card_widget.dart';
import 'package:workout_time/constants.dart';
import 'package:workout_time/Services/db_crud_service.dart';
class RoutineScreen extends StatefulWidget {
final Routine _routine;
RoutineScreen(this._routine);
#override
_RoutineScreenState createState() => _RoutineScreenState();
}
class _RoutineScreenState extends State<RoutineScreen> {
DBCRUDService helper;
final _nameController = TextEditingController();
final _descriptionController = TextEditingController();
bool _type = true;
int _cycles = 1;
int _restBetweenExercises = 15;
int _restBetweenCycles = 60;
#override
void initState() {
super.initState();
helper = DBCRUDService();
}
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () => Navigator.pop(context),
),
title: widget._routine != null
? Text(widget._routine.name)
: Text("Create your routine"),
actions: [
IconButton(
icon: Icon(Icons.done_rounded),
onPressed: createRoutine,
)
],
bottom: TabBar(
tabs: [
Tab(
text: "Configuration",
),
Tab(
text: "Exercises",
),
],
),
),
body: TabBarView(children: [
//_routine == null ? ConfigurationNewRoutine() : Text("WIDGET N° 1"),
ListView(
children: [
Container(
padding: EdgeInsets.all(15.0),
child: Row(
children: [
Text(
"Name:",
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
),
),
SizedBox(
width: 40.0,
),
Expanded(
child: TextField(
textAlign: TextAlign.center,
controller: _nameController,
),
),
],
),
),
SizedBox(
height: 20.0,
),
Card(
margin: EdgeInsets.all(15.0),
color: kSecondColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
child: Container(
padding: EdgeInsets.all(15.0),
child: Column(
children: [
Text(
"Type",
style: TextStyle(fontSize: 25.0),
),
Row(
children: [
Expanded(
child: TypeCard(
Icons.double_arrow_rounded,
_type == true ? kFirstColor : kThirdColor,
() => setState(() => _type = true),
"Straight set",
),
),
Expanded(
child: TypeCard(
Icons.replay_rounded,
_type == false ? kFirstColor : kThirdColor,
() => setState(() => _type = false),
"Cycle",
),
),
],
),
],
),
),
),
SizedBox(
height: 20.0,
),
Container(
padding: EdgeInsets.all(15.0),
child: Row(
children: [
Text(
"N° cycles:",
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
),
),
SizedBox(
width: 40.0,
),
Expanded(
child: Text("Hello"),
),
],
),
),
SizedBox(
height: 20.0,
),
],
),
Text("WIDGET N° 2"),
]),
),
);
}
void createRoutine() {
List<String> _exercises = ["1", "2"];
List<String> _types = ["t", "r"];
List<String> _quantities = ["30", "20"];
Routine routine = Routine({
'name': _nameController.text,
'description': "_description",
'type': _type.toString(),
'cycles': 1,
'numberExercises': 2,
'restBetweenExercises': 15,
'restBetweenCycles': 60,
'exercises': _exercises,
'types': _types,
'quantities': _quantities,
});
setState(() {
helper.createRoutine(routine);
Navigator.pop(context);
});
}
}
Any idea what can I do to make it work? Thank you
Make it simple
use Navigator.pop() twice
so that the current class and old class in also removed
from the stack
and then use Navigator.push()
When you push a new Route, the old one still stays in the stack. The new route just overlaps the old one and forms like a layer above the old one. Then when you pop the new route, it will just remove the layer(new route) and the old route will be displayed as it was before.
Now you must be aware the Navigator.push() is an asynchronous method and returns a Future. How it works is basically when you perform a Navigator.push(), it will push the new route and will wait for it to be popped out. Then when the new route is popped, it returns a value to the old one and that when the future callback will be executed.
Hence the solution you are looking for is add a future callback like this after your Navigator.push() :
Navigator.push(context,
MaterialPageRoute(builder: (context) => SettingsScreen())
).then((value){setState(() {});}); /// A callback which is executed after the new route will be popped. In that callback, you simply call a setState and refresh the page.

How to validate the current date in (dd-mm) format with the passcode

I'm trying to build two screens where:
The first screen has a Pincode textfield when the user enters the current date in (dd-mm) format for eg: if today's date is 24-07, the user enters 2407, then it should navigate to another page i.e., second screen
First Screen: Passcode.dart
import 'package:flutter/material.dart';
import 'package:flutter_course/HomePage.dart';
//import 'package:pin_entry_text_field/pin_entry_text_field.dart';
import 'package:pin_code_text_field/pin_code_text_field.dart';
import 'package:intl/intl.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: homePage(),
));
}
}
class homePage extends StatefulWidget {
#override
_homePageState createState() => _homePageState();
}
class _homePageState extends State<homePage> {
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Stack(children: <Widget>[
Center(
child: Image.asset(
"assets/passcode.jpeg",
width: size.width,
height: size.height,
fit: BoxFit.fill,
),
),
Column(
children: <Widget>[
// SizedBox(height:200,),
// SizedBox(width: 300),
Padding(
padding: EdgeInsets.only(left: 460, top: 150),
child: Text("ENTER PASSCODE",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 38.0,
color: Colors.black)),
),
SizedBox(height: 30),
Padding(
padding: EdgeInsets.only(left: 460),
child: PinCodeTextField(
autofocus: false,
pinTextStyle: TextStyle(
color: Colors.black,
fontSize: 40,
fontWeight: FontWeight.bold),
hideCharacter: true,
maskCharacter: "*",
// highlight: true,
// highlightColor: Colors.blue,
defaultBorderColor: Colors.black,
hasTextBorderColor: Colors.white,
hasError: true,
errorBorderColor: Colors.red,
//onTextChanged: (String)=>func(context),
onDone: (String) => func(context),
),
),
],
)
]);
}
}
void func(context) {
var now = new DateTime.now();
var formatter = new DateFormat('MMMMd');
var formatted = formatter.format(now);
debugPrint(formatted);
if (String == formatted) {
Navigator.push(
context, MaterialPageRoute(builder: (context) => HomePage()));
}
}
Second Screen :HomePage.dart
import 'package:flutter/material.dart';
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return DefaultTabController(length: 2,child:Scaffold(
drawer: Drawer(
child: Column(
children: <Widget>[
AppBar(
automaticallyImplyLeading: false,
title: Text('Choose'),
backgroundColor:Color(0xffedac51),
),
ListTile(
title: Text('Devices'),
onTap: () {
// Navigator.pushReplacement(
// context,
// MaterialPageRoute(
// builder: (BuildContext context) =>
// ProductsPage()));
},
),
ListTile(
title: Text('Allotted Devices'),
onTap: () {
// Navigator.pushReplacement(
// context,
// MaterialPageRoute(
// builder: (BuildContext context) =>
// ProductsPage()));
},
),
ListTile(
title: Text('Assign Devices'),
onTap: () {
// Navigator.pushReplacement(
// context,
// MaterialPageRoute(
// builder: (BuildContext context) =>
// ProductsPage()));
},
)
],
),
),
appBar: AppBar(
title: Text('Home'),
backgroundColor:Color(0xffedac51) ,
),
body: HomeBody()
)
);}
}
class HomeBody extends StatelessWidget{
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Stack(
children: <Widget>[
Center(
child: new Image.asset(
'assets/passcode.jpeg',
width: size.width,
height: size.height,
fit: BoxFit.fill,
),
),
Padding(
padding: EdgeInsets.only(top: 200, left: 500),
child: Column(
children: <Widget>[
Text("Let\'s Get Started!",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 38.0,
color: Colors.white)),
],
)),
],
);
}
}
When the passcode is entered as the current date in ddmm format, then it should navigate to the next screen
Not quite sure what you're trying to achieve, but something simple like this should do the trick:
DateTime today = DateTime.now();
String day, month, passCode;
if(today.day < 10){
day = "0" + today.day.toString();
} else {
day = today.day.toString();
}
if(today.month < 10){
month = "0" + today.month.toString();
} else {
month = today.month.toString();
}
passCode = day + month;