Why does slider value return null? - flutter

I'm building a page with multiple styled sliders, so I made a separate SliderWidget class. The slider itself behaves normally, but when I try to print the value of the slider to console, it returns null as flutter: null.
I've tried putting specific int values into my currentValue variable (in the SliderWidget class) to test with no luck, so I'm pretty sure that the problem is the getter itself, but I can't figure out what is wrong. I'm pretty new to flutter, so it's very possible I did something stupid.
Here is the slider object:
SliderWidget moodSlider = new SliderWidget(
sliderHeight: 48,
min: 0,
max: 10,
color1: 0xFF9BC1BC,
color2: 0xFF9BC1BC);
Here is the SliderWidget class:
import 'package:first_tutorial/MoodUpdate/custom_thumb_circle.dart';
import 'package:flutter/material.dart';
class SliderWidget extends StatefulWidget {
final double sliderHeight;
final int min;
final int max;
final fullWidth;
final int color1;
final int color2;
final int number;
SliderWidget(
{this.sliderHeight,
this.max,
this.min,
this.fullWidth = false,
this.color1,
this.color2,
this.number});
#override
_SliderWidgetState createState() => _SliderWidgetState();
}
class _SliderWidgetState extends State<SliderWidget> {
double currentValue = 0;
int get number => currentValue.round();
#override
Widget build(BuildContext context) {
double paddingFactor = .2;
if (this.widget.fullWidth) paddingFactor = .3;
return Container(
width: this.widget.fullWidth
? double.infinity
: (this.widget.sliderHeight) * 5.5,
height: (this.widget.sliderHeight),
decoration: new BoxDecoration(
borderRadius: new BorderRadius.all(
Radius.circular((this.widget.sliderHeight * .3)),
),
gradient: new LinearGradient(
colors: [
Color(this.widget.color1),
Color(this.widget.color2),
],
begin: const FractionalOffset(0.0, 0.0),
end: const FractionalOffset(1.0, 1.00),
stops: [0.0, 1.0],
tileMode: TileMode.clamp),
),
child: Padding(
padding: EdgeInsets.fromLTRB(this.widget.sliderHeight * paddingFactor,
2, this.widget.sliderHeight * paddingFactor, 2),
child: Row(
children: <Widget>[
Text(
'${this.widget.min}',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: this.widget.sliderHeight * .3,
fontWeight: FontWeight.w700,
color: Colors.white,
),
),
SizedBox(
width: this.widget.sliderHeight * .1,
),
Expanded(
child: Center(
child: SliderTheme(
data: SliderTheme.of(context).copyWith(
activeTrackColor: Colors.white.withOpacity(1),
inactiveTrackColor: Colors.white.withOpacity(.5),
trackHeight: 4.0,
thumbShape: CustomSliderThumbCircle(
thumbRadius: this.widget.sliderHeight * .4,
darkColor: this.widget.color1,
min: this.widget.min,
max: this.widget.max,
),
overlayColor: Colors.white.withOpacity(.4),
),
child: Slider(
value: currentValue,
onChanged: (value) {
setState(() {
currentValue = value;
});
}),
),
),
),
SizedBox(
width: this.widget.sliderHeight * .1,
),
Text(
'${this.widget.max}',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: this.widget.sliderHeight * .3,
fontWeight: FontWeight.w700,
color: Colors.white,
),
),
],
),
),
);
}
}
Edit: I'm printing it to the console within this widget. It's at the bottom in the onPressed parameter:
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('My Mood', style: TextStyle(fontFamily: 'WorkSans')),
backgroundColor: PrimaryColor,
),
backgroundColor: Color(0xFFF4F1BB),
body: Column(
children: <Widget>[
SizedBox(height: 20),
//Mood title
Align(
alignment: Alignment.center,
child: Text('How are you feeling?',
style: TextStyle(
color: Colors.grey[800],
fontSize: 20,
fontFamily: 'WorkSans'))),
SizedBox(height: 20),
//Mood slider
Align(
alignment: Alignment.center,
child:moodSlider),
SizedBox(height: 20),
//Sleep title
Align(
alignment: Alignment.center,
child: Text('How long did you sleep?',
style: TextStyle(
color: Colors.grey[800],
fontSize: 20,
fontFamily: 'WorkSans'))),
SizedBox(height: 20),
//Sleep slider
Align(
alignment: Alignment.center,
child: //SliderWidget(
// sliderHeight: 48,
// min: 0,
// max: 12,
// color1: 0xFF766E87,
// color2: 0xFF766E87)
sleepSlider),
SizedBox(height: 20),
//Save button
Align(
alignment: Alignment.bottomCenter,
child: RaisedButton(
child: Text('Save'),
textColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10)),
color: PrimaryColor,
onPressed: () {
print(moodSlider.number);
}, //_save(moodValue, sleepValue),
)),
],
),
);
}

I see one getter named number defined in your code..
int get number => currentValue.round();
..which is defined in _SliderWidgetState class. Not in SliderWidget class. These 2 are 2 different classes. So when you write moodSlider.number, you are not calling the above getter. Because moodSlider is an instance of SliderWidget class and the getter is defined in the other class. Instead, by writing moodSlider.number, what you are doing is - you are accessing the member variable number of the SliderWidget class..
class SliderWidget extends StatefulWidget {
final double sliderHeight;
final int min;
final int max;
final fullWidth;
final int color1;
final int color2;
final int number; //<-- this one here
SliderWidget(
{this.sliderHeight,
this.max,
this.min,
this.fullWidth = false,
this.color1,
this.color2,
this.number});
#override
_SliderWidgetState createState() => _SliderWidgetState();
}
..and this member variable number is never assigned a value. That is why it always prints null.
Edit:
For this to work, we can add an onChanged callback to the SliderWidget, just like the Slider widget has. We can make this callback to accept a int value parameter, so we can round it from inside _SliderWidgetState and pass to the callback. I made a demo on dartpad. You can see it here - https://dartpad.dev/dc8fd327ff5b94edff6c6f6fe3fea17c

As #JigarPatel said, you're calling not calling getter of your State class but you are calling it from the SliderWidget class whose number value is null
You can try updating the SliderWidget to a Stateless Widget See example below:
class SliderWidget extends StatelessWidget {
final double sliderHeight;
final int min;
final int max;
final fullWidth;
final int color1;
final int color2;
final double currentValue;
final ValueChanged<double> onChanged;
SliderWidget(
{this.sliderHeight,
this.max,
this.min,
this.fullWidth = false,
this.color1,
this.color2,
this.currentValue, this.onChanged});
#override
Widget build(BuildContext context) {
double paddingFactor = .2;
if ( fullWidth) paddingFactor = .3;
return Container(
width: fullWidth
? double.infinity
: ( sliderHeight) * 5.5,
height: ( sliderHeight),
decoration: new BoxDecoration(
borderRadius: new BorderRadius.all(
Radius.circular(( sliderHeight * .3)),
),
gradient: new LinearGradient(
colors: [
Color( color1),
Color( color2),
],
begin: const FractionalOffset(0.0, 0.0),
end: const FractionalOffset(1.0, 1.00),
stops: [0.0, 1.0],
tileMode: TileMode.clamp),
),
child: Padding(
padding: EdgeInsets.fromLTRB( sliderHeight * paddingFactor,
2, sliderHeight * paddingFactor, 2),
child: Row(
children: <Widget>[
Text(
'$min',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: sliderHeight * .3,
fontWeight: FontWeight.w700,
color: Colors.white,
),
),
SizedBox(
width: sliderHeight * .1,
),
Expanded(
child: Center(
child: SliderTheme(
data: SliderTheme.of(context).copyWith(
activeTrackColor: Colors.white.withOpacity(1),
inactiveTrackColor: Colors.white.withOpacity(.5),
trackHeight: 4.0,
thumbShape: CustomSliderThumbCircle(
thumbRadius: sliderHeight * .4,
darkColor: color1,
min: min,
max: max,
),
overlayColor: Colors.white.withOpacity(.4),
),
child: Slider(
value: currentValue,
onChanged: onChanged),
),
),
),
SizedBox(
width: sliderHeight * .1,
),
Text(
'$max',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: sliderHeight * .3,
fontWeight: FontWeight.w700,
color: Colors.white,
),
),
],
),
),
);
}
}
In onChanged callback you will get the value of the slider.

Related

Flutter TabController late initializer

I am creating an app and I am working on the profile setup and am using a tabcontroller. I have my tabcontroller working to navigate my first 3 screens, but for some reason I get a "late initializtion" error for my last screen. I have a custom button that I use for each screen, and the error gets shown once I add the custom button to my last acrren. Could someone explain to me what I need to do to get it working for my last screen? I've attached my code for the tabcontroller, custom button, and my last screen:
Tabcontroller onboarding model:
class AccountOnboarding extends StatefulWidget {
const AccountOnboarding({Key? key}) : super(key: key);
#override
State<AccountOnboarding> createState() => _AccountOnboardingState();
}
class _AccountOnboardingState extends State<AccountOnboarding> {
static const List<Tab> tabs = <Tab>[
Tab(text: 'Name'),
Tab(text: 'Age and Profile'),
Tab(text: 'Bio and Interests'),
Tab(text: 'Selection')
];
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: tabs.length,
child: Builder(builder: (BuildContext context) {
final TabController tabController = DefaultTabController.of(context)!;
tabController.addListener(() {
if (!tabController.indexIsChanging) {}
});
return Scaffold(
resizeToAvoidBottomInset: false,
backgroundColor: const Color(0xff31708c),
appBar: AppBar(
automaticallyImplyLeading: false,
backgroundColor: Colors.transparent,
elevation: 0,
title: Row(
children: [
Expanded(
child: Image.asset('assets/images/Logo_Strength.png',
height: 50),
),
Expanded(
flex: 2,
child: RichText(
text: TextSpan(
style: GoogleFonts.montserrat(
fontSize: 30),
children: <TextSpan> [
TextSpan(text: 'Stren',
style: GoogleFonts.montserrat(
color: Colors.white,
fontWeight: FontWeight.bold,
letterSpacing: 1,
shadows: [
Shadow(
color: Colors.black.withOpacity(0.7),
offset: const Offset(1.5, 0.0))
])),
TextSpan(text: ';',
style: GoogleFonts.montserrat(
color: const Color(0xffef6a7a), fontWeight: FontWeight.bold,
letterSpacing: 1,
shadows: [
Shadow(
color: Colors.black.withOpacity(0.7),
offset: const Offset(1.5, 0.0))
])),
TextSpan(text: 'th',
style: GoogleFonts.montserrat(
color: Colors.white,
fontWeight: FontWeight.bold,
letterSpacing: 1,
shadows: [
Shadow(
color: Colors.black.withOpacity(0.7),
offset: const Offset(1.5, 0.0))
]))
],
),
),
),
],
)
),
body: TabBarView(
// physics: const NeverScrollableScrollPhysics(),
children: [
NamePage(tabController: tabController,),
ageAndPicture(tabController: tabController,),
bioAndInterests(tabController: tabController,),
SelectionPage(tabController: tabController,)
],
),
);
}));
}}
Custom Button:
class CustomButton extends StatelessWidget {
final TabController tabController;
const CustomButton({Key? key,
required this.tabController})
: super(key: key);
#override
Widget build(BuildContext context) {
return DecoratedBox(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(50),
color: Colors.white
),
child: ElevatedButton(
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(
vertical: 16),
elevation: 0,
primary: Colors.transparent
),
onPressed: () {
tabController.animateTo(tabController.index + 1);
},
child: Container(
width: double.infinity,
child: Center(
child: Text('Continue',
style: GoogleFonts.montserrat(
color: const Color.fromARGB(255, 20, 83, 106),
fontSize: 19,
fontWeight: FontWeight.w600
),),
),
)
),
);
}
}
Last Screen code:
class SelectionPage extends StatefulWidget {
final TabController tabController;
const SelectionPage({Key? key,
required this.tabController}) : super(key: key);
#override
_SelectionPageState createState() => _SelectionPageState();
}
class _SelectionPageState extends State<SelectionPage>{
List <Item>listOfModel = [];
late TabController tabController;
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
String retrieveString;
final data = ModalRoute.of(context)!.settings;
if (data.arguments == null) {
retrieveString = "empty";
} else {
retrieveString = data.arguments as String;
}
listOfModel.add(Item(title: "Maintaining healthy relationships"));
listOfModel.add(Item(title: "Stress and anxiety management"));
listOfModel.add(Item(title: "Maintaing a better work-life balance"));
listOfModel.add(Item(title: "Personal growth and development"));
listOfModel.add(Item(title: "Being happier and more content in life"));
listOfModel.add(Item(title: "Mental and emotional well-being"));
double _height = MediaQuery.of(context).size.height;
return Scaffold(
resizeToAvoidBottomInset: false,
backgroundColor: const Color(0xff31708c),
body: Padding(
padding: EdgeInsets.only(
left: 30,
right: 30,
top: _height * 0.07,
bottom: _height * 0.05),
child: Column(
children: [
Column(
children: [
Column(
children: <Widget>[
Text('Hello there $retrieveString! What all would you like to focus on?',
style: GoogleFonts.montserrat(
color: Colors.white70,
fontSize: 19,
fontWeight: FontWeight.w600
),
textAlign: TextAlign.center,),
const SizedBox(height: 10),
Text("You can pick all that apply:",
style: GoogleFonts.montserrat(
color: Colors.white70,
fontSize: 14.5,
fontWeight: FontWeight.w600
),),
const SizedBox(height: 15,),
GridView.count(
primary: true,
shrinkWrap: true,
padding: const EdgeInsets.all(10),
childAspectRatio: 1.15,
crossAxisCount: 2,
crossAxisSpacing: 25,
mainAxisSpacing: 25,
children: [
gridItem(listOfModel[0],MyFlutterApp.relationships),
gridItem(listOfModel[1],MyFlutterApp2.meditate),
gridItem(listOfModel[2],MyFlutterApp.balance),
gridItem(listOfModel[3],MyFlutterApp2.personal_growth),
gridItem(listOfModel[4],MyFlutterApp.happy),
gridItem(listOfModel[5],MyFlutterApp3.well_rounded),
],
),
const SizedBox(height: 18,),
],
),
CustomButton(tabController: tabController)
],
),
],
),
),
);
}
Widget gridItem(Item item, IconData icon){
return GestureDetector(
onTap: () {
setState(() {
item.isSelected = !item.isSelected;
});
},
child: Stack(
children: [Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
border: Border.all(
color: const Color.fromARGB(255, 20, 83, 106),
width: 2.5),
color: item.isSelected ? Color.fromARGB(255, 234, 188, 193) : Colors.white
),
child: Column(
children: [
Align(alignment: Alignment.topCenter,
child: Icon(
icon,
color: const Color(0xff31708c),
size: 45,
),
),
const SizedBox(height: 4,),
Text(item.title,
style: GoogleFonts.montserrat(
fontSize: 14,
fontWeight: FontWeight.w500,
color: const Color(0xff31708c)
),
textAlign: TextAlign.center,),
],
),
),
Positioned(
top: 0,
right: 0,
child: Offstage(
offstage: !item.isSelected,
child: Container(
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(width: 2.5),
shape: BoxShape.circle),
child: const Icon(
Icons.check,
color: Colors.green,
),
),
),
)
],
)
);
}
}
class Item{
String title;
bool isSelected;
Item({required this.title, this.isSelected = false});
}
Remove
late TabController tabController;
in SelectionPage and change
CustomButton(tabController: tabController)
in SelectionPage to
CustomButton(tabController: widget.tabController)

Display TickMark widget depending on String and boolean value in Dart

Need to display icon with checkmark based on a String value that comes dynamically.
Like
this image is its pending show first widget with tick and rest are blank.
if delivered show with tick and the rest are blank.
Facing problems in creating logic using enums.
Currently, it displays the icons on button clicks
based on four constants which is fine with the widget CheckStatus.
Need to make in a way based on a boolean check if it's true and pending that pending tick widget displayed
and similar with other values.
Here is the complete code for it currently.
import 'package:dotted_border/dotted_border.dart';
import 'package:dotted_line/dotted_line.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:matab/models/order.dart';
import 'package:matab/ui/general_widgets/check_status.dart';
import 'package:matab/ui/pages/styles.dart';
import '../../general_widgets/custom_gradient_button.dart';
class TrackOrder extends StatefulWidget {
const TrackOrder({Key? key, required this.order}) : super(key: key);
final Order order;
#override
State<TrackOrder> createState() => _TrackOrderState();
}
enum Status { Pending, Confirmed, Shipped, Received }
class _TrackOrderState extends State<TrackOrder> {
static const darkGreyColor = Colors.grey;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Center(child: Text('Track Order')),
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () => Get.back(),
),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
const SizedBox(height: 50),
Text(
"Order ID:" + widget.order.orderID,
style: const TextStyle(
color: darkGreyColor,
fontSize: 18,
fontWeight: FontWeight.bold),
),
const SizedBox(height: 50),
const Text('Sat, 12 Mar 2022',
style: TextStyle(
color: darkGreyColor,
fontSize: 18,
fontWeight: FontWeight.bold)),
const SizedBox(
height: 15,
),
Container(
margin: const EdgeInsets.fromLTRB(15, 0, 0, 0),
child: const Text('Estimated Time: 07 Days',
style: TextStyle(fontSize: 23, fontWeight: FontWeight.bold)),
),
const SizedBox(height: 30),
SizedBox(
width: 200,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
OrderStatusBar(title: widget.order.orderStatus, status: true),
dottedLine(),
OrderStatusBar(
title: widget.order.orderStatus, status: false),
dottedLine(),
OrderStatusBar(
title: widget.order.orderStatus, status: false),
dottedLine(),
OrderStatusBar(
title: widget.order.orderStatus, status: false),
],
),
),
const SizedBox(
height: 40,
),
Container(
margin: const EdgeInsets.fromLTRB(15, 0, 0, 0),
child: const Text('Shipping Address',
style: TextStyle(fontSize: 23, fontWeight: FontWeight.bold)),
),
Center(
child: Text(widget.order.deliveryAddress.address,
style: const TextStyle(
color: Colors.grey,
fontSize: 18,
fontWeight: FontWeight.bold)),
),
Center(
child: Padding(
padding: const EdgeInsets.all(
50.0,
),
child: CustomGradientButton(
buttonText: "Track Order".tr, buttonFunction: () => {}),
),
),
Center(
child: Padding(
padding: const EdgeInsets.only(top: 18.0),
child: GestureDetector(
child: Text(
'Back to Home'.tr,
style: TextStyle(
color: mainColor,
fontSize: 23,
fontWeight: FontWeight.bold),
),
onTap: () => {
Get.off(CheckStatus(
order: widget.order,
))
},
),
),
)
],
),
),
);
}
}
class OrderStatusBar extends StatefulWidget {
const OrderStatusBar({Key? key, required this.title, required this.status})
: super(key: key);
final String title;
final bool status;
#override
State<OrderStatusBar> createState() => _OrderStatusBarState();
}
class _OrderStatusBarState extends State<OrderStatusBar> {
#override
Widget build(BuildContext context) {
return Directionality(
textDirection: TextDirection.rtl,
child: Row(
children: [
widget.status ? dottedCircleWithCheckMark() : dottedCircle(),
const SizedBox(width: 30),
Text(
widget.title.tr,
style: TextStyle(
fontSize: 20,
fontWeight: widget.status ? FontWeight.bold : null,
),
),
],
),
);
}
}
const size = 25.0;
const strokeWidth = 1.0;
const checkedColor = Color.fromRGBO(232, 113, 65, 1);
Widget dottedLine() {
return Directionality(
textDirection: TextDirection.rtl,
child: Align(
alignment: Alignment.topRight,
child: Container(
margin: const EdgeInsets.fromLTRB(0, 0, size / 2, 0),
child: const Padding(
padding: EdgeInsets.only(left: 27 / 2),
child: SizedBox(
height: size,
child: DottedLine(
dashColor: Colors.black,
direction: Axis.vertical,
lineLength: size,
lineThickness: strokeWidth,
dashLength: 5,
dashGapLength: 5,
),
),
),
),
),
);
}
dottedCircle() {
return DottedBorder(
borderType: BorderType.Circle,
dashPattern: const [5, 5],
child: Container(
height: size,
width: size,
decoration: const BoxDecoration(shape: BoxShape.circle),
));
}
dottedCircleWithCheckMark() {
return Container(
height: size + strokeWidth * 2,
width: size + strokeWidth * 2,
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: checkedColor,
),
child: const Icon(
Icons.check,
color: Colors.white,
size: size / 4 * 3,
),
);
}
// ignore_for_file: constant_identifier_names
class CheckStatus extends StatefulWidget {
const CheckStatus({Key? key, required this.order}) : super(key: key);
final Order order;
#override
State<CheckStatus> createState() => _CheckStatusState();
}
class _CheckStatusState extends State<CheckStatus> {
int selectedItemIndex = 0;
var pending = Status.Pending;
List<bool> orderStatus = [true,true,true,false];
#override
void initState() {
// TODO: implement initState
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
for (int i = 0; i < Status.values.length; i++)
ElevatedButton(
onPressed: () {
selectedItemIndex = i;
setState(() {});
},
child: Text("Order Status ${Status.values[i]}"),
),
Row(
children: [
for (int i = 0; i <= selectedItemIndex; i++)
Container(
height: size + strokeWidth * 2,
width: size + strokeWidth * 2,
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: checkedColor,
),
child: const Icon(
Icons.check,
color: Colors.white,
size: size / 4 * 3,
),
),
ElevatedButton(onPressed: () {}, child: Text("Back"))
],
)
],
),
);
}
}

How to create This Ui in - Flutter

Hello there I'm new to flutter and I want to achieve this certain UI. from the UI I can see -
At the top it has a custom search bar I don't know if it's an appbar or not.
It has a SizedBox or something similar below the searchbar.
It has A listview.builder (I already Know how to achieve this)
So I would like to ask how to achieve the first two contents of the app
here is a screenshot of the app
You can take this as an example. a similar design.
import 'package:flutter/material.dart';
class FirstScreen extends StatefulWidget {
const FirstScreen({Key? key}) : super(key: key);
#override
State<FirstScreen> createState() => _FirstScreenState();
}
class _FirstScreenState extends State<FirstScreen> {
#override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Column(
children: [
const SizedBox(
height: 30,
),
buildTitleText(context),
const SizedBox(
height: 30,
),
buildSearchBar(context),
const SizedBox(
height: 30,
),
buildSecondTitle(context),
const SizedBox(
height: 10,
),
buildContent(context)
],
),
),
);
}
SizedBox buildSecondTitle(BuildContext context) {
return SizedBox(
width: MediaQuery.of(context).size.width - 65,
child: Row(
children: const [
Text(
'Favorite Places',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
TextButton(
onPressed: null,
child: Text(
'See All',
style: TextStyle(color: Colors.blue, fontSize: 18),
)),
],
),
);
}
Container buildTitleText(BuildContext context) {
return Container(
width: MediaQuery.of(context).size.width - 50,
child: const Text(
"What you would like to find?",
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 30,
),
),
);
}
SingleChildScrollView buildContent(BuildContext context) {
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: [
const SizedBox(
width: 25,
),
buildCityCard(context,
photoName: 'img_istanbul.jpg',
cityName: 'İstanbul',
cityActivity: '98 Aktivite',
cityScore: '4.8'),
const SizedBox(
width: 25,
),
buildCityCard(context,
photoName: 'img_mugla.jpg',
cityName: 'Muğla',
cityActivity: '102 Aktivite',
cityScore: '4.7'),
const SizedBox(
width: 25,
),
buildCityCard(context,
photoName: 'img_antalya.jpg',
cityName: 'Antalya',
cityActivity: '98 Aktivite',
cityScore: '4.5'),
const SizedBox(
width: 25,
),
],
),
);
}
Container buildSearchBar(BuildContext context) {
return Container(
width: MediaQuery.of(context).size.width - 65,
child: TextField(
decoration: InputDecoration(
prefixIcon: const Icon(
Icons.search,
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(360),
borderSide: const BorderSide(
color: Colors.blueAccent,
width: 2,
)),
labelText: "Locaiton",
),
),
);
}
Container buildCityCard(BuildContext context,
{required String photoName,
required String cityName,
required String cityActivity,
required String cityScore}) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: Colors.white,
),
height: MediaQuery.of(context).size.height / 2.5,
width: MediaQuery.of(context).size.height / 3.7,
child: Column(
children: [
Expanded(
flex: 5,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: Colors.blue,
image: DecorationImage(
image: AssetImage("assets/images/${photoName}"),
fit: BoxFit.fill,
),
),
),
),
const SizedBox(
height: 10,
),
Expanded(
flex: 1,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
const SizedBox(
width: 20,
),
Icon(Icons.location_on, color: Colors.blue),
Text(
"${cityName}",
style: const TextStyle(
fontSize: 16, fontWeight: FontWeight.bold),
),
],
),
),
Expanded(
flex: 1,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
const SizedBox(
width: 20,
),
const Icon(
Icons.star,
color: Colors.yellow,
),
Text(
"${cityScore}",
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
const Padding(
padding: EdgeInsets.fromLTRB(95, 0, 0, 0),
child: Icon(Icons.arrow_forward_ios),
),
],
),
),
const SizedBox(
height: 10,
),
],
),
);
}
}
This is the home. If you want to use tabbar.
import 'package:circle_bottom_navigation_bar/circle_bottom_navigation_bar.dart';
import 'package:circle_bottom_navigation_bar/widgets/tab_data.dart';
import 'package:flutter/material.dart';
import 'package:inovatif/third_screen.dart';
import 'first_screen.dart';
import 'second_screen.dart';
class HomeView extends StatefulWidget {
HomeView({Key? key}) : super(key: key);
static String routeName = 'home';
#override
State<HomeView> createState() => _HomeViewState();
}
class _HomeViewState extends State<HomeView> {
int currentPage = 0;
final List<Widget> _pages = [
FirstScreen(),
SecondScreen(),
ThirdScreen(),
];
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;
final viewPadding = MediaQuery.of(context).viewPadding;
double barHeight;
double barHeightWithNotch = 67;
double arcHeightWithNotch = 67;
if (size.height > 700) {
barHeight = 70;
} else {
barHeight = size.height * 0.1;
}
if (viewPadding.bottom > 0) {
barHeightWithNotch = (size.height * 0.07) + viewPadding.bottom;
arcHeightWithNotch = (size.height * 0.075) + viewPadding.bottom;
}
return Scaffold(
appBar: AppBar(backgroundColor: Colors.transparent, elevation: 0),
body: _pages[currentPage],
bottomNavigationBar: buildCircleBottomNavigationBar(
viewPadding, barHeightWithNotch, barHeight, arcHeightWithNotch),
);
}
CircleBottomNavigationBar buildCircleBottomNavigationBar(
EdgeInsets viewPadding,
double barHeightWithNotch,
double barHeight,
double arcHeightWithNotch) {
return CircleBottomNavigationBar(
initialSelection: currentPage,
barHeight: viewPadding.bottom > 0 ? barHeightWithNotch : barHeight,
arcHeight: viewPadding.bottom > 0 ? arcHeightWithNotch : barHeight,
itemTextOff: viewPadding.bottom > 0 ? 0 : 1,
itemTextOn: viewPadding.bottom > 0 ? 0 : 1,
circleOutline: 15.0,
shadowAllowance: 0.0,
circleSize: 50.0,
blurShadowRadius: 50.0,
circleColor: Colors.purple,
activeIconColor: Colors.white,
inactiveIconColor: Colors.grey,
tabs: getTabsData(),
onTabChangedListener: (index) => setState(() => currentPage = index),
);
}
List<TabData> getTabsData() {
return [
TabData(
icon: Icons.home,
iconSize: 25.0,
title: 'Home',
fontSize: 12,
fontWeight: FontWeight.bold,
),
TabData(
icon: Icons.phone,
iconSize: 25,
title: 'Emergency',
fontSize: 12,
fontWeight: FontWeight.bold,
),
TabData(
icon: Icons.search,
iconSize: 25,
title: 'Search Place',
fontSize: 12,
fontWeight: FontWeight.bold,
),
// TabData(
// icon: Icons.alarm,
// iconSize: 25,
// title: 'Alarm',
// fontSize: 12,
// fontWeight: FontWeight.bold,
// ),
];
}
}
To create an page like this you will need to know about Text,SingleChildScrollView set scroll direction to horizontal,Bottom Navigation bar,Banner etc.

Can't place text in the bottom of the screen when using column

I wrote a flutter app that uses a column widget with TextFormField and some title, and now I want to place another text widget on the bottom of the screen, I tried use the Align widget but it seems to work for me only when I use it without any other widgets, when I use it inside the column widget it not working and have no effect and place it right under the previous widget. (I tried to use the Expanded widget as well but it not working either.)
Someone know how can I fix it?
I also can't rounded the "create account" container borders so if someone know how can I also do that it will be much appreciated
this is my code:
// imports...
class CreateName extends StatefulWidget {
const CreateName({Key? key, this.phoneNumber, this.userId}) : super(key: key);
final phoneNumber;
final userId;
#override
_CreateNameState createState() => _CreateNameState(phoneNumber, userId);
}
class _CreateNameState extends State<CreateName> {
late final phone;
late final uid;
late double _formHeight;
late String username;
final _varKey = GlobalKey<FormState>();
Color buttonColorBack = const Color(0xDCDCDCDC);
Color buttonColorText = Colors.black;
Color saveButtonColorText = const Color(0xDCDCDCDC);
_CreateNameState(this.phone, this.uid);
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
if (size.height <= 736) {
_formHeight = (size.height * .05) + 6;
} else {
_formHeight = size.height * .048;
}
return Scaffold(
body: SafeArea(
child: GestureDetector(
onTap: () => FocusScope.of(context).requestFocus(
FocusNode(),
),
child: SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: size.height - 90,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Stack(
alignment: Alignment.topLeft,
children: [
GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Padding(
padding: EdgeInsets.only(
top: size.height * .006,
left: size.width * .03,
),
child: SvgPicture.asset(
"assets/arrow-back.svg",
),
),
),
],
),
Padding(
padding: EdgeInsets.only(
top: size.height * .18,
),
child: Center(
child: Text(
"Create a Username",
style: TextStyle(
fontSize: size.width * .066,
letterSpacing: size.width * .015,
fontWeight: FontWeight.w300,
),
),
),
),
Padding(
padding: EdgeInsets.only(
top: size.height * .015,
),
child: Center(
child: Container(
margin: EdgeInsets.symmetric(
horizontal: size.width * .045,
),
height: _formHeight,
child: Form(
key: _varKey,
child: TextFormField(
style: TextStyle(
fontSize: size.width * .035,
),
decoration: InputDecoration(
contentPadding: const EdgeInsets.fromLTRB(
0,
10,
0,
0,
),
hintText: 'Username',
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(7.0),
borderSide: const BorderSide(
color: Colors.black,
width: 1.25,
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(7.0),
borderSide: const BorderSide(
color: Colors.black,
width: 1.5,
),
),
),
autofocus: false,
cursorColor: Colors.black,
textAlign: TextAlign.center,
onChanged: (input) {
setState(() {
if (input.length > 1) {
buttonColorBack = Colors.black;
buttonColorText = Colors.white;
} else if (input.length < 1) {
buttonColorBack = saveButtonColorText;
buttonColorText = Colors.black;
}
});
},
onSaved: (input) async {
username = input!;
},
),
),
),
),
),
GestureDetector(
child: Padding(
padding: EdgeInsets.symmetric(
vertical: size.height * .01,
horizontal: size.width * .02,
),
child: Container(
height: _formHeight,
color: buttonColorBack,
child: Center(
child: Text(
"Create account",
style: TextStyle(
fontSize: size.width * .035,
color: buttonColorText,
),
),
),
),
),
onTap: () {
_varKey.currentState!.save();
if (username.length > 1) {
loginUser(uid, phone, username);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const ClientHomePage(),
),
);
} else {
print("enter username");
}
},
),
Align( // here is the widget that I want to place in the bottom of the screen
alignment: Alignment.bottomCenter,
child: Text("test"),
),
],
),
),
),
),
),
);
}
}
the reason is that Column's height is not fullscreen. It just has enough height to show all widgets in it, so alignment will not help in this situation.
But you can use Spacer widget which will take all available space on screen in Column.
For example:
Column(
children: [
widgets
...
const Spacer(),
Text('Hello world!'), //widget which you want to be at the bottom of screen
],
),
If you want to add rounded borders to container add decoration. Notice that you can't use decoration and color parameters at the same time, but you can specify color in decoration!
Container(
decoration: BoxDecoration(
color: Colors.black, //or any other color
borderRadius: BorderRadius.circular(16.0) //this value changes borderRadius,
boxShape: BoxShape.circle //if you need a circle container use this instead of border radius
),
)
Attention! You can't use Spacer() if Column is in ScrollView. If there is not lots of content in Column, and every screen you need can handle it do not use ScrollView.

Buttons center their children when they are placed in a ListView.builder widget

Why do buttons in Flutter tend to align their children to the centre when they are placed in list views?
For example:
import 'package:flutter/material.dart';
class Test extends StatefulWidget {
#override
_TestState createState() => _TestState();
}
class _TestState extends State<Test> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemCount: 10,
itemBuilder: (context, index){
return MaterialButton(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Hello"),
],
));
}
),
);
}
}
This would result in ten hellos spaced evenly by the default height of the button, but they would be centered; even though I used the CrossAxisAlignment.start property in a column.
Here is the image:
But when I replace the MaterialButton with a Container they are aligned to the start to the column as wanted.
When I just remove the ListView.Builder I get 'hello' aligned to the start.
The same thing happens with the rest of the buttons.
Is there a way to make buttons in list views not have centered children inside them?
Edit: the example was fixed by #Harry but it didn't fix my exact code
here is my code: I try to created a list of widgets outside and use a function to add my list items into that list and return a list view through the ActivitiesList widget
import 'package:flutter/material.dart';
import 'package:list_them_out/models/activities.dart';
import 'package:provider/provider.dart';
class ActivitiesList extends StatefulWidget {
#override
_ActivitiesListState createState() => _ActivitiesListState();
}
double conBorderRadius = 30;
class _ActivitiesListState extends State<ActivitiesList> {
List<Widget> itemData = [];
void getData(context) {
double cardHeight = MediaQuery.of(context).size.height * 0.3;
double cardWidth = MediaQuery.of(context).size.width * 0.97;
final activities = Provider.of<List<Activity>>(context);
activities == null
// ignore: unnecessary_statements
? null
: setState(() {
itemData = [];
});
activities == null
// ignore: unnecessary_statements
? null
: setState(() {
activities.forEach((element) {
itemData.add(Padding(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Container(
width: cardWidth,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(conBorderRadius),
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: <Color>[
Colors.lightGreen[300],
Colors.lightBlue[300],
]
),
boxShadow: [
BoxShadow(
color: Colors.grey[600],
offset: Offset(4.0, 4.0),
blurRadius: 15,
spreadRadius: 1),
BoxShadow(
color: Colors.white,
offset: Offset(-4.0, -4.0),
blurRadius: 15,
spreadRadius: 1),
]),
child: Stack(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(conBorderRadius),
child: MaterialButton(
splashColor: HSLColor.fromColor(Colors.green).toColor(),
onPressed: () {},
child: Align(
alignment: Alignment.centerLeft,
child: Container(
child: Padding(
padding: EdgeInsets.only(top: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: cardWidth * 0.61,
child: Text(
element.name,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: Colors.grey[600],
fontSize: 25,
fontWeight: FontWeight.w500,
letterSpacing: 1,
),
),
),
Padding(
padding: EdgeInsets.only(top: cardHeight * 0.09, left: cardWidth * 0.03),
child: Container(
width: cardWidth * 0.48,
child: RichText(
maxLines: 2,
overflow: TextOverflow.ellipsis,
text: TextSpan(children: [
TextSpan(
text: "Start: ",
style: TextStyle(
color: Colors.grey[800],
fontSize: 20,
fontWeight: FontWeight.w400,
letterSpacing: 1),
),
TextSpan(
text: element.time,
style: TextStyle(
color: Colors.black87,
fontWeight: FontWeight.w300,
fontSize: 20,
))
]),
),
),
),
SizedBox(height: cardHeight * 0.06,),
Row(
children: [
IconButton(icon: Icon(Icons.comment),
onPressed: () => null,
color: Colors.grey[600],
),
Padding(
padding: EdgeInsets.only(bottom: 5),
child: Text("Comments", style: TextStyle(color: Colors.grey[600], fontSize: 20, fontWeight: FontWeight.w300, letterSpacing: 1),),
)
],
)
],
),
),),
),
),
),
Positioned(
right: 0,
bottom: 0,
top: 0,
child: ClipPath(
clipper: MyClip(radius: conBorderRadius),
child: Container(
height: cardHeight,
width: cardWidth * 0.45,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: <Color>[
Colors.grey[300],
Colors.lightBlue[100].withOpacity(0.5)
])),
),
),
),
Positioned(
right: cardWidth * 0.05,
bottom: 20,
child: Container(
child: Text("Hello"),
),
)
],
)),
));
});
});
}
#override
Widget build(BuildContext context) {
double listHeight = MediaQuery.of(context).size.height * 0.86;
double listWidth = MediaQuery.of(context).size.width * 0.97;
getData(context);
return ClipRRect(
borderRadius: BorderRadius.only(
topRight: Radius.circular(50), topLeft: Radius.circular(50)),
child: Container(
height: listHeight,
width: listWidth,
child: ListView.builder(
itemCount: itemData.length,
itemBuilder: (context, index) {
return Padding(
padding: EdgeInsets.only(bottom: 30),
child: itemData[index],
);
}),
));
}
}
``
Try using the Align widget. Just wrap the column with an align widget and have the alignment parameter be alignment.centerLeft.
import 'package:flutter/material.dart';
class Test extends StatefulWidget {
#override
_TestState createState() => _TestState();
}
class _TestState extends State<Test> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemCount: 10,
itemBuilder: (context, index){
return MaterialButton(
child: Align(
child:Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Hello"),
],
),
alignment: Alignment.centerLeft,
)
);
}
),
);
}
}