How to align button in onboarding screen flutter - flutter

I wanted to add a login button below the onboarding screen: how could I do that? Below I have provided the picture of the screen and the code I have implemented so far. Appreciate your help on this.
class OnBoardingScreen extends StatefulWidget {
const OnBoardingScreen({Key? key}) : super(key: key);
#override
_OnBoardingScreenState createState() => _OnBoardingScreenState();
}
class _OnBoardingScreenState extends State<OnBoardingScreen> {
PageController _controller = PageController();
//keep track of if we are on the last page or not
bool onLastPage = false;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
PageView(
onPageChanged: (index) {
setState(() {
onLastPage = (index == 2);
});
},
controller: _controller,
children: [
IntroPageOne(),
IntroPageTwo(),
IntroPageThree(),
],
),
//dot indicators
Container(
alignment: Alignment(0, 0.6),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
//skip
GestureDetector(
onTap: () {
_controller.jumpTo(2);
},
child: Text('Skip', style: TextStyle(
height: 1.2,
fontFamily: "Roboto",
fontSize: 15,
color: MainGreen,
fontWeight: FontWeight.w500,
// fontWeight: FontWeight.w100,
))),
SmoothPageIndicator(
controller: _controller,
count: 3,
effect: WormEffect(
dotColor: Colors.grey,
activeDotColor: MainGreen,
),
),
//next or done
onLastPage
? GestureDetector(
onTap: () {
Get.to(() => const LoginScreen());
},
child: Text('Done',
style: TextStyle(
height: 1.2,
fontFamily: "Roboto",
fontSize: 15,
color: MainGreen,
fontWeight: FontWeight.w500,
// fontWeight: FontWeight.w100,
)),
)
: GestureDetector(
onTap: () {
_controller.nextPage(
duration: Duration(milliseconds: 500),
curve: Curves.easeIn,
);
},
child: Text('Next', style: TextStyle(
height: 1.2,
fontFamily: "Roboto",
fontSize: 15,
color: MainGreen,
fontWeight: FontWeight.w500,
// fontWeight: FontWeight.w100,
)),
)
],
)),
MainButton("Login")
],
));
}
}

Step by step:
Wrap your Stack by Expanded.
Wrap Expanded by Column.
Move MainButton("Login") from Stack children to Column children.
Like this:
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(child: Stack(...)),
MainButton("Login"),
]
),
);
}

Since your goal is to have 2 widgets displayed in a vertical way, then you should use a Column instead of stacking everything.
Something like this
import 'package:flutter/material.dart';
class OnBoardingScreen extends StatefulWidget {
const OnBoardingScreen({Key? key}) : super(key: key);
#override
_OnBoardingScreenState createState() => _OnBoardingScreenState();
}
class _OnBoardingScreenState extends State<OnBoardingScreen> {
PageController _controller = PageController();
//keep track of if we are on the last page or not
bool onLastPage = false;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Stack(
children: [
PageView(
onPageChanged: (index) {
setState(() {
onLastPage = (index == 2);
});
},
controller: _controller,
children: [
IntroPageOne(),
IntroPageTwo(),
IntroPageThree(),
],
),
//dot indicators
Container(
alignment: Alignment(0, 0.6),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
//skip
GestureDetector(
onTap: () {
_controller.jumpTo(2);
},
child: Text(
'Skip',
style: TextStyle(
height: 1.2,
fontFamily: "Roboto",
fontSize: 15,
color: MainGreen,
fontWeight: FontWeight.w500,
// fontWeight: FontWeight.w100,
),
),
),
SmoothPageIndicator(
controller: _controller,
count: 3,
effect: WormEffect(
dotColor: Colors.grey,
activeDotColor: MainGreen,
),
),
//next or done
onLastPage
? GestureDetector(
onTap: () {
Get.to(() => const LoginScreen());
},
child: Text('Done',
style: TextStyle(
height: 1.2,
fontFamily: "Roboto",
fontSize: 15,
color: MainGreen,
fontWeight: FontWeight.w500,
// fontWeight: FontWeight.w100,
)),
)
: GestureDetector(
onTap: () {
_controller.nextPage(
duration: Duration(milliseconds: 500),
curve: Curves.easeIn,
);
},
child: Text(
'Next',
style: TextStyle(
height: 1.2,
fontFamily: "Roboto",
fontSize: 15,
color: MainGreen,
fontWeight: FontWeight.w500,
// fontWeight: FontWeight.w100,
),
),
)
],
),
),
],
),
MainButton("Login"),
],
),
),
);
}
}

Try below code hope its helpful to you. I have try without Stack widget Wrap your Button inside Expanded and give its to alignment
Column(
children: <Widget>[
Text('All Leads'),
Text('Widget 2'),
Text('Widget 3'),
Text('Widget 4'),
Expanded(
child: Align(
alignment: FractionalOffset.bottomCenter,
child: ElevatedButton(
onPressed: () {},
child: Text('Login'),
),
),
),
],
),
Result Screen->

Related

How can I display 'year' property only when I using scroll_date_picker in Flutter?

I ran into a snag while using the scroll_date_picker package. I succeeded in marking the scroll as shown in the figure below, but I want only the year to be displayed and scrolled, not all of the year, month, and day. How would I recommend changing _selectedDate in this case?
This is my code.
import 'package:flutter/material.dart';
import 'package:scroll_date_picker/scroll_date_picker.dart';
import 'package:shipda/constants.dart';
class BuiltYearChoice extends StatefulWidget {
const BuiltYearChoice({Key? key}) : super(key: key);
#override
State<BuiltYearChoice> createState() => _BuiltYearChoiceState();
}
class _BuiltYearChoiceState extends State<BuiltYearChoice> {
DateTime _selectedDate = DateTime.now();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: baseColor10,
elevation: 0,
leading: TextButton(
onPressed: () {},
child: Text('Reset'),
),
title: Text(
'Example',
style: titleMediumBase50(),
),
centerTitle: true,
actions: [
IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(
Icons.close,
color: baseColor50,
),
),
],
),
body: Padding(
padding: const EdgeInsets.fromLTRB(48, 16, 48, 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Column(
children: [
Text(
'min',
// '최소진수년도',
style: TextStyle(
fontSize: bodyMedium,
fontFamily: 'regular',
color: Colors.grey.shade500,
),
),
marginHeight4,
Text(
'0000',
style: TextStyle(
fontSize: 32,
fontFamily: 'bold',
),
),
],
),
Column(
children: [
Text(''),
Text(
'~',
style: TextStyle(
fontSize: 32,
fontFamily: 'bold',
color: Colors.grey.shade400,
),
),
],
),
Column(
children: [
Text(
'max',
// '최대진수년도',
style: TextStyle(
fontSize: bodyMedium,
fontFamily: 'regular',
color: Colors.grey.shade500,
),
),
marginHeight4,
Text(
'0000',
style: TextStyle(
fontSize: 32,
fontFamily: 'bold',
),
),
],
),
],
),
SizedBox(
height: 300,
child: ScrollDatePicker(
locale: Locale('ko'),
selectedDate: _selectedDate,
onDateTimeChanged: (DateTime value) {
setState(() {
_selectedDate = value;
});
}),
)
],
),
),
);
}
}
You can make your CustomPicker, something like this:
import 'package:flutter/material.dart';
class CustomPicker extends StatelessWidget {
final List<DateTime> list;
const CustomPicker(this.list, {Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
// define item height
double itemHeight = 30;
var middleIndex = (list.length / 2).floor(); // index of the middle item
var scrollController = ScrollController(
// if you want middle item to be pre-selected
initialScrollOffset: middleIndex * itemHeight,
);
int numberOfItemsToBeVisible = 5;
double pickerHeight = itemHeight * numberOfItemsToBeVisible;
// or you can pass index of the item you want to be visible
var selectedItem = ValueNotifier(list[middleIndex]);
// changing selected item on scroll
scrollController.addListener(() {
selectedItem.value = list[(scrollController.offset / itemHeight).round()];
});
return Column(
children: [
Stack(
children: [
Positioned.fill(
child: Center(
child: Container(
height: itemHeight,
width: MediaQuery.of(context).size.width,
decoration: ShapeDecoration(
color: Colors.grey.shade300,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5),
),
),
),
),
),
// picker
SizedBox(
height: pickerHeight,
child: ListWheelScrollView(
diameterRatio: 1.2,
itemExtent: itemHeight,
controller: scrollController,
children: list
.map(
(element) => Align(
alignment: Alignment.center,
child: Text('${element.year}'),
),
)
.toList(),
),
),
],
),
// selected item
ValueListenableBuilder(
valueListenable: selectedItem,
builder: (context, DateTime value, _) =>
Text('selected year: ${value.year}'),
),
],
);
}
}
Then you can use it like this:
SizedBox(
height: 300,
child: CustomPicker(
List.generate(21, (index) => DateTime(2000 + index)),
),
)
The result is:

How do i correctly initialise a variable from a stateful widget to another widget in flutter and maintain state?

I have two widgets
JobsHeaderWidget
JobsView
JobsHeaderWidget is a stateful widget where i code all the logic and initialise int current = 0; in the state. In this same file, i have another class named CategoriesBuilder where i use switch cases to make sure at each switch case a different container is returned. ( a switch case for each tab )
This switch cases is now responsible for switching containers depending on the tab bar selected as seen in this image:
I will also drop the code snippet of the JobsHeaderWidget for better clarifications.
The problem is - when i use this CategoriesBuilder in same widget as the 'JobsHeaderWidget' it works.
But i don't want to use it in same widget cos of the logic of my design. I want to be able to use this builder in JobsView widget which is another dart file and it doesn't work maybe because of wrong approach.
I tried converting the JobsView to a stateful widget and initialising 'int current = 0;' but it doesn't work.
I also tried making int current = 0; global var, it worked but the state doesn't change when i select individual tab bars. ( I mean my switch cases don't seem to work ).
I have gone round stackoverflow for answers before asking this but can't find a solution.
Snippets of each widgets below.
JobsHeaderWidget
class JobsHeaderWidget extends StatefulWidget {
const JobsHeaderWidget({
Key key,
}) : super(key: key);
#override
State<JobsHeaderWidget> createState() => _JobsHeaderWidgetState();
}
class _JobsHeaderWidgetState extends State<JobsHeaderWidget> {
List<String> items = [
"All",
"Critical",
"Open",
"Closed",
"Overdue",
];
ValueChanged<int> onChange;
int current = 0;
List<DropdownMenuItem<String>> get dropdownItems {
List<DropdownMenuItem<String>> menuItems = [
DropdownMenuItem(
child: Text(
"Today",
),
value: "Today"),
];
return menuItems;
}
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(left: 15.0, right: 15.0),
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Jobs',
style: GoogleFonts.poppins(
color: Colors.black,
fontSize: 18,
fontWeight: FontWeight.w600),
),
Row(
children: [
Text(
'View Insights ',
style: GoogleFonts.poppins(
color: Color(0xff3498DB),
fontSize: 12,
fontWeight: FontWeight.w500),
),
Icon(
Icons.arrow_forward_ios,
color: Color(0xff3498DB),
size: 12,
),
],
),
SizedBox(
height: 10,
),
filterJobs(),
],
),
),
);
}
Widget filterJobs() {
String selectedValue = "Today";
return Column(
children: [
Container(
constraints: const BoxConstraints(maxWidth: 600, maxHeight: 100),
width: double.infinity,
child: IntrinsicWidth(
child: FittedBox(
fit: BoxFit.fitWidth,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
for (int i = 0; i < items.length; i++) ...[
GestureDetector(
onTap: () {
setState(() {
current = i;
});
},
child: AnimatedContainer(
height: 40,
duration: const Duration(milliseconds: 300),
margin: const EdgeInsets.all(5),
padding: const EdgeInsets.only(
left: 14.0, right: 14.0, top: 4, bottom: 4),
decoration: BoxDecoration(
color: current == i
? const Color(0xff34495E)
: const Color(0xffF5F5F5),
borderRadius: BorderRadius.circular(50),
),
child: Center(
child: Text(
items[i],
style: GoogleFonts.poppins(
fontSize: 15,
fontWeight: FontWeight.w500,
color:
current == i ? Colors.white : Colors.grey),
),
),
),
),
]
],
),
),
),
),
Divider(
color: Color(0xff34495E).withOpacity(0.2),
),
Row(
children: [
Text(
'All Jobs',
style:
GoogleFonts.poppins(fontSize: 9, fontWeight: FontWeight.w400),
),
SizedBox(
width: 5,
),
Text(
' * This Week',
style:
GoogleFonts.poppins(fontSize: 9, fontWeight: FontWeight.w400),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'25',
style: GoogleFonts.poppins(
fontSize: 20, fontWeight: FontWeight.w600),
),
Container(
height: 30,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(2),
color: Color(0xffF4F4F4)),
child: Padding(
padding: const EdgeInsets.only(
left: 8.0,
),
child: Row(
children: [
Container(
decoration: BoxDecoration(
color: Color(0xff34495E),
borderRadius: BorderRadius.circular(2)),
child: Icon(
Icons.tune,
size: 15,
color: Colors.white,
),
),
SizedBox(
width: 5,
),
DropdownMenuItem(
child: DropdownButtonHideUnderline(
child: Container(
child: DropdownButton(
isDense: true,
style: GoogleFonts.poppins(
fontSize: 10,
fontWeight: FontWeight.w500,
color: Color(0xff34495E),
),
onChanged: (value) {},
items: dropdownItems,
value: selectedValue,
),
),
),
),
],
),
),
),
],
),
//If i uncomment this line and use the category builder here, it works fine! CategoriesBuilder(current: current)
],
);
}
}
class CategoriesBuilder extends StatelessWidget {
const CategoriesBuilder({
Key key,
#required this.current,
}) : super(key: key);
final int current;
#override
Widget build(BuildContext context) {
return Builder(
builder: (context) {
switch (current) {
case 0:
return AllJobsListView();
case 1:
return CriticalJobsListView();
case 2:
return OpenJobsListView();
case 3:
return ClosedJobsListView();
case 4:
return OverdueJobsListView();
default:
return SizedBox.shrink();
}
},
);
}
}
JobsView
class JobsView extends StatefulWidget {
const JobsView({
Key key,
}) : super(key: key);
#override
State<JobsView> createState() => _JobsViewState();
}
class _JobsViewState extends State<JobsView> {
int current = 0;
#override
Widget build(BuildContext context) {
final controller = Get.put(EServicesController());
return Scaffold(
// floatingActionButton: new FloatingActionButton(
// child: new Icon(Icons.add, size: 32, color: Get.theme.primaryColor),
// onPressed: () => {Get.offAndToNamed(Routes.E_SERVICE_FORM)},
// backgroundColor: Get.theme.colorScheme.secondary,
// ),
floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
body: RefreshIndicator(
onRefresh: () async {
Get.find<LaravelApiClient>().forceRefresh();
controller.refreshEServices(showMessage: true);
Get.find<LaravelApiClient>().unForceRefresh();
},
child: CustomScrollView(
controller: controller.scrollController,
physics: AlwaysScrollableScrollPhysics(),
shrinkWrap: false,
slivers: <Widget>[
SliverAppBar(
backgroundColor: Color(0xffFFFFFF),
expandedHeight: MediaQuery.of(context).size.height * 0.4,
elevation: 0.5,
primary: true,
pinned: false,
floating: false,
//iconTheme: IconThemeData(color: Get.theme.primaryColor),
// title: Text(
// "Jobs".tr,
// style: Get.textTheme.headline6
// .merge(TextStyle(color: Get.theme.primaryColor)),
// ),
centerTitle: false,
automaticallyImplyLeading: false,
// leading: new IconButton(
// icon: new Icon(Icons.arrow_back_ios,
// color: Get.theme.primaryColor),
// onPressed: () => {Get.back()},
// ),
actions: [
SearchButtonWidget(),
],
//bottom: HomeSearchBarWidget(),
flexibleSpace: FlexibleSpaceBar(
collapseMode: CollapseMode.parallax,
title: JobsHeaderWidget(),
)),
SliverToBoxAdapter(
child: Wrap(
children: [
//ServicesListWidget(),
// The state doesnt change here for some reasosns CategoriesBuilder(current: current)
],
),
),
],
),
),
);
}
}
Try this: keep your 'int current' within _JobsViewState as you have in your code.
When you call your JobsHeaderWidget , pass the function it will use to update the the value of the current variable; and rebuild the state from here.
Something like this:
class JobsHeaderWidget extends StatefulWidget {
final Function changeCurrentValue(int newValue);
const JobsHeaderWidget({
this.changeCurrentValue,
Key key,
}) : super(key: key);
#override
State<JobsHeaderWidget> createState() => _JobsHeaderWidgetState();
}
class _JobsHeaderWidgetState extends State<JobsHeaderWidget> {
#override
Widget build(BuildContext context) {
// Somewhere inside build, instead calling setState()
// call the function you passed to the widget
GestureDetector(
onTap: () {
changeCurrentValue(i);
},
)
}
}
class _JobsViewState extends State<JobsView> {
int current = 0;
void changeCurrentValue(int newValue) {
setState(() {
current = newValue;
});
}
#override
Widget build(BuildContext context) {
//somewhere inside build
flexibleSpace: FlexibleSpaceBar(
collapseMode: CollapseMode.parallax,
title: JobsHeaderWidget(changeCurrentValue: changeCurrentValue),
)),
}
}
After hours and even sleeping overnight on this question i came up with a work-around that works. (minor refactoring)
This was my approach :
Convert my JobsView widget to a stateful widget and put all my controllers in place.
Copied all my variables from JobHeaderWidget and put it in the state of my JobsView widget.
Instead of returning a widget in the title of my sliver app as thus :
flexibleSpace: FlexibleSpaceBar( collapseMode: CollapseMode.parallax, title: JobsHeaderWidget(), )),
I copied all of my code from the widget tree from JobsHeaderWidget and put converted to a method and replaced it in my title.
My builder CategoryBuilder was put in a separate then imported as i used it in my SliverAppAdapter .
Of cos i got rid of the unnecessary dart file JobsHeaderWidget.
FULL CODE BELOW
class JobsView extends StatefulWidget {
#override
State<JobsView> createState() => _JobsViewState();
}
class _JobsViewState extends State<JobsView> {
List<String> items = [
"All",
"Critical",
"Open",
"Closed",
"Overdue",
];
int current = 0;
List<DropdownMenuItem<String>> get dropdownItems {
List<DropdownMenuItem<String>> menuItems = [
DropdownMenuItem(
child: Text(
"Today",
),
value: "Today"),
];
return menuItems;
}
#override
Widget build(BuildContext context) {
final controller = Get.put(EServicesController());
return Scaffold(
// floatingActionButton: new FloatingActionButton(
// child: new Icon(Icons.add, size: 32, color: Get.theme.primaryColor),
// onPressed: () => {Get.offAndToNamed(Routes.E_SERVICE_FORM)},
// backgroundColor: Get.theme.colorScheme.secondary,
// ),
floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
body: RefreshIndicator(
onRefresh: () async {
Get.find<LaravelApiClient>().forceRefresh();
controller.refreshEServices(showMessage: true);
Get.find<LaravelApiClient>().unForceRefresh();
},
child: CustomScrollView(
controller: controller.scrollController,
physics: AlwaysScrollableScrollPhysics(),
shrinkWrap: false,
slivers: <Widget>[
SliverAppBar(
backgroundColor: Color(0xffFFFFFF),
expandedHeight: MediaQuery.of(context).size.height * 0.4,
elevation: 0.5,
primary: true,
pinned: false,
floating: false,
//iconTheme: IconThemeData(color: Get.theme.primaryColor),
// title: Text(
// "Jobs".tr,
// style: Get.textTheme.headline6
// .merge(TextStyle(color: Get.theme.primaryColor)),
// ),
centerTitle: false,
automaticallyImplyLeading: false,
// leading: new IconButton(
// icon: new Icon(Icons.arrow_back_ios,
// color: Get.theme.primaryColor),
// onPressed: () => {Get.back()},
// ),
actions: [
SearchButtonWidget(),
],
//bottom: HomeSearchBarWidget(),
flexibleSpace: FlexibleSpaceBar(
collapseMode: CollapseMode.parallax,
title: mainHeader(),
)),
SliverToBoxAdapter(
child: Wrap(
children: [
//ServicesListWidget(),
CategoriesBuilder(current: current)
],
),
),
],
),
),
);
}
Padding mainHeader() {
return Padding(
padding: const EdgeInsets.only(left: 15.0, right: 15.0),
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Jobs',
style: GoogleFonts.poppins(
color: Colors.black,
fontSize: 18,
fontWeight: FontWeight.w600),
),
Row(
children: [
Text(
'View Insights ',
style: GoogleFonts.poppins(
color: Color(0xff3498DB),
fontSize: 12,
fontWeight: FontWeight.w500),
),
Icon(
Icons.arrow_forward_ios,
color: Color(0xff3498DB),
size: 12,
),
],
),
SizedBox(
height: 10,
),
() {
String selectedValue = "Today";
return Column(
children: [
Container(
constraints:
const BoxConstraints(maxWidth: 600, maxHeight: 100),
width: double.infinity,
child: IntrinsicWidth(
child: FittedBox(
fit: BoxFit.fitWidth,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
for (int i = 0; i < items.length; i++) ...[
GestureDetector(
onTap: () {
setState(() {
current = i;
});
},
child: AnimatedContainer(
height: 40,
duration: const Duration(milliseconds: 300),
margin: const EdgeInsets.all(5),
padding: const EdgeInsets.only(
left: 14.0,
right: 14.0,
top: 4,
bottom: 4),
decoration: BoxDecoration(
color: current == i
? const Color(0xff34495E)
: const Color(0xffF5F5F5),
borderRadius: BorderRadius.circular(50),
),
child: Center(
child: Text(
items[i],
style: GoogleFonts.poppins(
fontSize: 15,
fontWeight: FontWeight.w500,
color: current == i
? Colors.white
: Colors.grey),
),
),
),
),
]
],
),
),
),
),
Divider(
color: Color(0xff34495E).withOpacity(0.2),
),
Row(
children: [
Text(
'All Jobs',
style: GoogleFonts.poppins(
fontSize: 9, fontWeight: FontWeight.w400),
),
SizedBox(
width: 5,
),
Text(
' * This Week',
style: GoogleFonts.poppins(
fontSize: 9, fontWeight: FontWeight.w400),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'25',
style: GoogleFonts.poppins(
fontSize: 20, fontWeight: FontWeight.w600),
),
Container(
height: 30,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(2),
color: Color(0xffF4F4F4)),
child: Padding(
padding: const EdgeInsets.only(
left: 8.0,
),
child: Row(
children: [
Container(
decoration: BoxDecoration(
color: Color(0xff34495E),
borderRadius: BorderRadius.circular(2)),
child: Icon(
Icons.tune,
size: 15,
color: Colors.white,
),
),
SizedBox(
width: 5,
),
DropdownMenuItem(
child: DropdownButtonHideUnderline(
child: Container(
child: DropdownButton(
isDense: true,
style: GoogleFonts.poppins(
fontSize: 10,
fontWeight: FontWeight.w500,
color: Color(0xff34495E),
),
onChanged: (value) {},
items: dropdownItems,
value: selectedValue,
),
),
),
),
],
),
),
),
],
),
//CategoriesBuilder(current: current)
],
);
}(),
],
),
),
);
}
}

Tab barView doesn't automatically get updated by setstate until the tab bar is clicked on

I am using a Tabbar widget which controls a TabbarView. When I call on setstate after changing the value of a variable named "searchTerm", the anticipated change isn't updated in the tabbarView widgets until I click on any of the tabs.I need the tabviewView to update immediately i call on setstate.Please i need a response as soon as possible See screenshot here
Below is the code
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> with SingleTickerProviderStateMixin {
String searchTerm;
List <Widget> kTabPages;
TabController tabController;
final ktabs = <Tab>[Tab(child: Text("All"),),Tab(child: Text("Popular"),),Tab(child: Text("Top"),),];
#override
void dispose() {
tabController.dispose();
super.dispose();
}
#override
void initState() {
tabController = TabController(length: ktabs.length, vsync: this);
super.initState();
}
#override
Widget build(BuildContext context) {
kTabPages = <Widget>[Center(child: GridWidget(category: "all",searchTerm: searchTerm,),),
Center(child: GridWidget(category: "popular",searchTerm: searchTerm,),),
Center(child: GridWidget(category: "top",searchTerm: searchTerm,),)];
return Scaffold(
resizeToAvoidBottomInset: false,
backgroundColor: Color.fromARGB(255, 69, 22, 99),
body: SafeArea(
child: DefaultTabController(
length: ktabs.length,
child: Column(
children: [
Expanded(child: Container(
child: Padding(
padding: const EdgeInsets.only(left: 25,right: 16,top: 25,bottom: 10),
child: Column(
children: [
Expanded(
flex: 5,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
GestureDetector(
child: Icon(
Icons.apps_outlined,
color: Colors.white,
),
),
GestureDetector(
onTap: ()async{
//assigns a new value to variable searchName after returning from SearchScreen
var searchName = await Navigator.push(context,
MaterialPageRoute(builder: (context){
return SearchScreen();
}));
if(searchName != null){
setState(() {
//Assigns SearchName value to variable searchTerm
searchTerm = searchName;
});
}
},
child: Icon(
Icons.search,
color: Colors.white,
),
),
],
),
SizedBox(
height: 15,
),
Text("Hi Xeroes🖐️",style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w700,
fontSize: 25.0
),),
SizedBox(
height: 10,
),
Text("Today is a good day",style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w400,
fontSize: 13.0
),),
SizedBox(
height: 2,
),
Text("To learn something new!",style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w400,
fontSize: 13.0
),),
],
),
),
Expanded(
flex: 1,
child: TabBar(
controller: tabController,
tabs:ktabs ,
labelColor: Colors.white,
indicatorColor: Colors.amberAccent,
indicatorSize: TabBarIndicatorSize.label,
labelStyle: TextStyle(
// fontSize: 16
),),
)
],
),
),
color: Color.fromARGB(255, 69, 22, 99),
),
flex: 4,),
Expanded(
child: Container(
padding: EdgeInsets.only(top: 20),
child: TabBarView(
controller: tabController,
children: kTabPages,
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(topLeft: Radius.circular(30),topRight:Radius.circular(30))
),
),
flex: 8,)
],
),
),
),
);
}
}

Flutter Problem: How to use Marquee text in flutter?

I want to use Marquee Where is my Text Widget.
When I am using marquee by removing text widget After using marquee then my text is disappearing and getting more error in console.
so please help me to use marquee.
import 'package:flutter/material.dart';
import 'package:hospital/CartIcon/cart_icon.dart';
import 'package:hospital/Drawer/dropdown_menu.dart';
import 'package:hospital/MyOrderPage/MyOrderDetailsViewPage/myOrderDetailsView.dart';
import 'package:hospital/constant.dart';
import 'package:intl/intl.dart';
import 'package:marquee/marquee.dart';
class MyOrderPage extends StatefulWidget {
const MyOrderPage({Key key}) : super(key: key);
#override
_MyOrderPageState createState() => _MyOrderPageState();
}
class _MyOrderPageState extends State<MyOrderPage> {
// final DateTime orderDate = DateTime.now();
final DateTime orderDate = DateTime.now();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: kGreen,
title: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"My Order",
style: TextStyle(fontStyle: FontStyle.italic),
),
],
),
actions: [CartIcon(), DropDownMenu()],
),
body: Column(
children: [
Container(
// height: 200,
padding: EdgeInsets.all(8),
child: Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Theme.of(context).primaryColor.withOpacity(0.3),
blurRadius: 8,
)
],
borderRadius: BorderRadius.circular(8),
color: Colors.white,
),
child: Padding(
padding: EdgeInsets.all(15),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row(
children: <Widget>[
Flexible(
//I want to use marquee user instead of text widget here
//Marquee(
// text: 'GeeksforGeeks is a one-stop destination for programmers.',
// style: TextStyle(fontWeight: FontWeight.bold),
//scrollAxis: Axis.horizontal,
// crossAxisAlignment: CrossAxisAlignment.start,
// blankSpace: 20.0,
// velocity: 100.0,
// pauseAfterRound: Duration(seconds: 1),
//showFadingOnlyWhenScrolling: true,
// fadingEdgeStartFraction: 0.1,
// fadingEdgeEndFraction: 0.1,
// numberOfRounds: 3,
//startPadding: 10.0,
// accelerationDuration: Duration(seconds: 1),
// accelerationCurve: Curves.linear,
// decelerationDuration: Duration(milliseconds: 500),
// decelerationCurve: Curves.easeOut,
//)
child: Text(
'Spondylolysis,Pittasnadhanak,D_stone,Natural Tulsi',
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: Colors.black,
fontSize: 20,
),
),
),
],
),
SizedBox(
height: 10,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row(
children: <Widget>[
Text('20-07-2021',
style: TextStyle(
color: Colors.black54,
// fontWeight: FontWeight.bold,
fontSize: 20)),
],
),
SizedBox(
height: 6,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text('Delivery Status',
style: TextStyle(
color: Colors.black54,
// fontWeight: FontWeight.bold,
fontSize: 20)),
Text('Delivered',
style: Theme.of(context)
.textTheme
.headline6
.copyWith(color: Colors.green)),
],
)
],
),
SizedBox(
height: 4,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row(
children: <Widget>[
Text('Quantity: ',
style: TextStyle(
color: Colors.black54,
// fontWeight: FontWeight.bold,
fontSize: 20)),
Padding(
padding: const EdgeInsets.only(left: 4),
child: Text('3',
style: TextStyle(
color: Colors.black,
// fontWeight: FontWeight.bold,
fontSize: 18)),
),
],
),
Row(
children: <Widget>[
Text('Totat Amount: ',
style: TextStyle(
color: Colors.black54,
// fontWeight: FontWeight.bold,
fontSize: 20)),
Padding(
padding: const EdgeInsets.only(left: 15),
child: Text('324' + '\$',
//total amount
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 20)),
),
],
)
],
)
],
),
),
)),
SizedBox(
height: 5,
),
],
),
);
}
}
I want to use Marquee Where is my Text Widget.
When I am using marquee by removing text widget After using marquee then my text is disappearing and getting more error in console.
class MarqueeWidget extends StatefulWidget {
final Widget child;
final Axis direction;
final Duration animationDuration, backDuration, pauseDuration;
MarqueeWidget({
#required this.child,
this.direction: Axis.horizontal,
this.animationDuration: const Duration(milliseconds: 3000),
this.backDuration: const Duration(milliseconds: 800),
this.pauseDuration: const Duration(milliseconds: 800),
});
#override
_MarqueeWidgetState createState() => _MarqueeWidgetState();
}
class _MarqueeWidgetState extends State<MarqueeWidget> {
ScrollController scrollController;
#override
void initState() {
scrollController = ScrollController(initialScrollOffset: 50.0);
WidgetsBinding.instance.addPostFrameCallback(scroll);
super.initState();
}
#override
void dispose(){
scrollController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: widget.child,
scrollDirection: widget.direction,
controller: scrollController,
);
}
void scroll(_) async {
while (scrollController.hasClients) {
await Future.delayed(widget.pauseDuration);
if(scrollController.hasClients)
await scrollController.animateTo(
scrollController.position.maxScrollExtent,
duration: widget.animationDuration,
curve: Curves.ease);
await Future.delayed(widget.pauseDuration);
if(scrollController.hasClients)
await scrollController.animateTo(0.0,
duration: widget.backDuration, curve: Curves.easeOut);
}
}
}
class MarqueeText extends StatefulWidget {
#override
_MarqueeTextState createState() => _MarqueeTextState();
}
class _MarqueeTextState extends State<MarqueeText> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Marquee Text"),
),
body: Center(
child: SizedBox(
width: 200.0,
child: MarqueeWidget(
direction: Axis.horizontal,
child: Text(
"your text"))),
));
}
}

How to Turn Some Functions to an Independent Widget in Flutter?

I need to turn these two functions : _collectKeywords and _matchKeywords into a Widget, so I can reuse them another time. I have tried it, but I don't know how and where to instatiate the a widget that only processes data without returning any value. Can somebody help me?
//please don't mind the UI, button's color, etc
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:fluttermatchcard/cardButton.dart';
class MainMenu extends StatelessWidget {
void _accessCardMatcher(String butKeyword)
{
_collectKeywords(butKeyword);
}
//================================================
String _keyword_1;
String _keyword_2;
void _collectKeywords(String _keyword_now){
if(_keyword_1==null)
{
_keyword_1=_keyword_now;
}
else{
_keyword_2=_keyword_now;
_matchKeyword(_keyword_1,_keyword_2);
}
}
void _matchKeyword(_keyWord_one, _keyWord_two){
if(_keyWord_one==_keyWord_two){
//Lock the But
print("MATCH!!!!");
}
_keyword_1=null;
_keyword_1=null;
}
//================================================
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
//textBaseline: ,
children: <Widget>[
Container(
child: Text("Match Card", style: TextStyle(
fontSize: 50,
color: Colors.amber,
fontFamily: "FreeHand"
),
),
),
Icon( Icons.filter_none,
color: Colors.amber,
size: 40,
),
SizedBox(
height: 30,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
//But Start
CardButton(
onTapExecute:_accessCardMatcher,
keyword: "start",
text: Text("STA", style: TextStyle(
fontSize: 20,
),),
alignment: Alignment.centerRight,
),
//But Start2
CardButton(
onTapExecute:_accessCardMatcher,
keyword: "start",
text: Text("RT", style: TextStyle(
fontSize: 20,
),),
alignment: Alignment.centerLeft,
),
SizedBox(
width: 10,
),
//But Option
CardButton(
onTapExecute:_accessCardMatcher,
keyword: "option",
text: Text("OPT", style: TextStyle(
fontSize: 20,
),),
alignment: Alignment.centerRight,
),
CardButton(
onTapExecute:_accessCardMatcher,
keyword: "option",
text: Text("ION", style: TextStyle(
fontSize: 20,
),),
alignment: Alignment.centerLeft,
),
],
),
SizedBox(
height: 20,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
//But
CardButton(
onTapExecute:_accessCardMatcher,
keyword: "credit",
text: Text("CRE", style: TextStyle(
fontSize: 20,
),),
alignment: Alignment.centerRight,
),
CardButton(
onTapExecute:_accessCardMatcher,
keyword: "credit",
text: Text("DIT", style: TextStyle(
fontSize: 20,
),),
alignment: Alignment.centerLeft,
),
],
)
],
)
);
}
}
Its a sample, Modify as your requirement !
class MyWidget extends StatefulWidget {
#override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
int buttonCount = 0;
String textYouWantToModify = '';
TextEditingController te;
CommonMethods methods = CommonMethods();
#override
void initState() {
super.initState();
te = TextEditingController();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(title: Text('Title')),
body: Container(
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
//Other widgets like TextFiled to save text......or whatever
TextField(
controller: te,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Type something 1',
labelStyle: TextStyle(color: Colors.black)),
style: TextStyle(color: Colors.black)
),
RaisedButton(
color: Colors.black,
onPressed: () {
setState(() {
buttonCount++;
if (buttonCount == 2) {
methods.method1(te.text);
methods.method2();
}
});
},
child:
Text('Button 1', style: TextStyle(color: Colors.white))),
RaisedButton(
onPressed: () {
setState(() {
buttonCount++;
if (buttonCount == 2) {
methods.method1(te.text);
methods.method2();
}
});
},
child:
Text('Button 2', style: TextStyle(color: Colors.black))),
//Other widgets.....
]))));
}
}
class CommonMethods {
void method1(String s) {
//your code.....
print(s);
}
void method2() {
//your code.....
}
}