I want that Cancellation charges and the bottom button remains fixed on screen, while the Choose Seat(s) and passengers should be scrollable. But, whenever I am trying to insert any widget after singlechildscrollview, it is not appearing at the bottom.
As, my column has 3 widgets, a row, singlechildscrollview and button, so my button and top row should remain there and remaining seats and passengers should be scrollable, but I am not able to see the bottom button, while my row working fine, remaining there.
Code -
showCancellationCharges(BuildContext? context) {
final DateTime currentDate = DateTime.now();
if (ticketData!.data!.booking!.boarding!.eta! >
currentDate.millisecondsSinceEpoch)
showModalBottomSheet(
backgroundColor: Colors.white,
context: context!,
builder: (context) => Wrap(
children: [
StatefulBuilder(
builder: (context, stateSetter) => Padding(
padding: MediaQuery.of(context).viewInsets,
child: Container(
//height: MediaQuery.of(context).size.height*0.7,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: const EdgeInsets.only(top: 5.0, bottom: 5.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Cancellation Charges',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
)
),
IconButton(
icon: Icon(
Icons.close,
color: colorPrimary,
),
onPressed: () {
Navigator.of(context).pop();
},
),
],
),
),
Container(
height: MediaQuery.of(context).size.height*0.5,
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Text(
'Choose Seat(s)',
style: TextStyle(color: popUpLightTextColor),
),
),
Column(
children: List.generate(
ticketData!.data!.booking!.seats!.length,
(index) => CancellationItem(
checkBoxState: ticketData!.data!.booking!
.seats![index].selected,
checkBox: (v) => stateSetter(() {
print('seat at index $index $v');
if (v)
totalSeatToCancel++;
else
totalSeatToCancel--;
ticketData!.data!.booking!.seats![index]
.selected = v;
}),
// checkBoxState: data[index.],
imagePath:
'assets/icons/ticket_seat_icon.svg',
title: ticketData!
.data!.booking!.seats![index].code,
)),
),
// CancellationSeatItems(
// data: ticketData.data.booking.seats,
// ),
Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Text(
'Choose Passenger(s)',
style: TextStyle(color: popUpLightTextColor),
),
),
Column(
children: List.generate(
ticketData!.data!.booking!.passengers!.length,
(index) => CancellationItem(
checkBoxState: ticketData!.data!.booking!
.passengers![index].selected,
checkBox: (v) => stateSetter(() {
if (v)
totalPassengerToCancel++;
else
totalPassengerToCancel--;
print('passenger at index $index $v');
ticketData!.data!.booking!
.passengers![index].selected = v;
}),
imagePath: (ticketData!.data!.booking!
.passengers![index].gender ==
'MALE')
? 'assets/icons/male_icon.svg'
: 'assets/icons/female_icon.svg',
title: ticketData!.data!.booking!
.passengers![index].name,
)),
),
],
),
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16),
child: Container(
child: ValueListenableBuilder(
valueListenable: isCalculating,
builder: (BuildContext context, bool val, Widget? child) {
return FlatButton(
height: 44,
minWidth: MediaQuery.of(context).size.width,
color: val ? Colors.grey : colorPrimary,
onPressed: () => calculateItem(),
child: Text(
val ? 'Calculating...' : 'Calculate',
style: TextStyle(
color: Colors.white,
fontSize: 16
),
),
);
},
),
),
),
// CancellationPassengerItems(
// data: ticketData.data.booking.passengers,
// ),
],
),
),
),
),
),
],
));
else
_snackbarService.showSnackbar(
message: 'Sorry, ticket can not be cancelled');
}
Actually I solved the problem. I just used isScrollControlled: true, parameter for showModalBottomSheet and it's done.
you may put the listview inside a container with a height
Related
So I have a container with 9 ElevatedButtons (code shown below) i would like to change the color of the selected button, but there can only be 1 selected button at a time, how would i go about doing this? So if one button is selected the button will go green, but if another button in the container is clicked it will revert back the color of the previously selected color and change the current selected button to green.
here is the container with the elevated buttons:
Container(
padding: EdgeInsets.all(25),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(20)),
color: Colors.white),
width: MediaQuery.of(context).size.width,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Material(
elevation: 2,
child: InkWell(
onTap: (){},
child: Container(
padding: EdgeInsets.all(15),
child: Center(child: Text("10.000"))),
),
),
),
SizedBox(width: 10),
Expanded(
child: Material(
elevation: 2,
child: InkWell(
onTap: (){},
child: Container(
padding: EdgeInsets.all(15),
child: Center(child: Text("20.000"))),
),
),
),
SizedBox(width: 10),
Expanded(
child: Material(
elevation: 2,
child: InkWell(
onTap: (){},
child: Container(
padding: EdgeInsets.all(15),
child: Center(child: Text("50.000"))),
),
),
),
],
),
SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Material(
elevation: 2,
child: InkWell(
onTap: (){},
child: Container(
padding: EdgeInsets.all(15),
child: Center(child: Text("100.000"))),
),
),
),
SizedBox(width: 10),
Expanded(
child: Material(
elevation: 2,
child: InkWell(
onTap: (){},
child: Container(
padding: EdgeInsets.all(15),
child: Center(child: Text("250.000"))),
),
),
),
SizedBox(width: 10),
Expanded(
child: Material(
elevation: 2,
child: InkWell(
onTap: (){},
child: Container(
padding: EdgeInsets.all(15),
child: Center(child: Text("500.000"))),
),
),
),
],
),
SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Material(
elevation: 2,
child: InkWell(
onTap: (){},
child: Container(
padding: EdgeInsets.all(15),
child: Center(child: Text("750.000"))),
),
),
),
SizedBox(width: 10),
Expanded(
child: Material(
elevation: 2,
child: InkWell(
onTap: (){},
child: Container(
padding: EdgeInsets.all(15),
child: Center(child: Text("1.000.000", style: TextStyle(fontSize: 13)))),
),
),
),
SizedBox(width: 10),
Expanded(
child: Material(
elevation: 2,
child: InkWell(
onTap: (){},
child: Container(
padding: EdgeInsets.all(15),
child: Center(child: Text("2.000.000", style: TextStyle(fontSize: 13)))),
),
),
),
],
),
],
),
),
If i have to guess I would think I would need to put it inside of a map, but I'm not sure how to go about doing this. I would prefer to learn the manual implementation but if needed i'm fine with using packages if needed.
For this work You can use ChoiceChip instead of using Material Button directly
A material design choice chip.
ChoiceChips represent a single choice from a set. Choice chips contain
related descriptive text or categories.
class MyThreeOptions extends StatefulWidget {
const MyThreeOptions({Key? key}) : super(key: key);
#override
State<MyThreeOptions> createState() => _MyThreeOptionsState();
}
class _MyThreeOptionsState extends State<MyThreeOptions> {
int? _value = 1;
#override
Widget build(BuildContext context) {
return Wrap(
children: List<Widget>.generate(
3,
(int index) {
return ChoiceChip(
label: Text('Item $index'),
selected: _value == index,
onSelected: (bool selected) {
setState(() {
_value = selected ? index : null;
});
},
);
},
).toList(),
);
}
}
create a new StatefulWidget and just return a button inside that. call the functions and api's in that file only. and call this class name as the child instead ofyour old button. Works for me.
here is my app
as you can see working well, I installed this on my phone, and it works fine too.
and I send this to my friend, and his phone showing like this
mine and his phone is same phone, literally same phone, but in his and any others phone is showing this overflow, mine and this emulator have no problem, how do i fix overflow problem
class Homescreen extends StatelessWidget {
const Homescreen({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: const Text("Pluto Guess Game"),
backgroundColor: Colors.white60,
),
body: Container(
color: Colors.white,
child: SafeArea(
child: ListView(
children: [
Card(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
PlayerWidget(
player: messi
),
PlayerWidget(
player: neymar
)
],
),
),
Card(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
PlayerWidget(
player: mbappe
)
PlayerWidget(
player: ramos
)
],
),
),
Card(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
PlayerWidget(
player: messi
),
PlayerWidget(
player: neymar
)
],
),
),
Card(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
PlayerWidget(
player: messi
),
PlayerWidget(
player: neymar
)
],
),
),
Card(
child: IconButton(
icon: const Icon(Icons.gesture),
iconSize: 50,
color: Colors.black,
splashColor: Colors.orange,
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (nav) {
return const Asking();
},
),
);
},
),
),
],
),
),
),
),
);
}
}
and also I'm new at flutter, I know I'm doing lot of mistake in this code please suggest that also
->Use This Code
Widget build(BuildContext context) {
double h = MediaQuery.of(context).size.height;
double w = MediaQuery.of(context).size.width;
return Scaffold(
appBar: getAppBar(context, "Back", "", []),
body: SafeArea(
top: true,
bottom: true,
child: Column(
children: [
Expanded(
child: ListView.builder(
shrinkWrap: true,
physics: BouncingScrollPhysics(),
itemCount: 15,
itemBuilder: (context,v){
return
Container(
padding: EdgeInsets.only(left: 15.0,right: 15.0),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
height: h*0.2,
width: w*0.4,
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(25.0)
),
),
Container(
height: h*0.2,
width: w*0.4,
decoration: BoxDecoration(
color: Colors.black38,
borderRadius: BorderRadius.circular(25.0)
),
),
],
),
SizedBox(height: 15.0,),
Divider(
color: Colors.black,
),
SizedBox(height: 15.0,),
],
),
);
}),
)
],
),
),
);
}
Without your code I can't make corrections to the current code. but if you need responsive UI that work regardless of screen size, I suggest you use Rows, Columns with Expanded Widget, as necessary.
for example if you need to have 2 Items inside a Row where each occupies same space you can use,
Row (
children: [
Expanded (
flex:1
child: YourWidget()
),
Expanded (
flex:1
child: YourWidget()
)
]
)
Remember to remove hardcoded size properties along the main axis of your Colum or Row.
Same goes for Columns.
If you need each to have varied sizes, you can use flex property of the Expanded Widget. for example, one items has 1/3 of width and other has 2/3 you can put 1 and 2 as flex values.
more explanation from flutter team: Expanded
I've been trying so hard to build page view system for quotes app. I want the page to flow full screen from top to bottom and bottom to top scrollable/swipe able to navigate between different quotes each time
like this. The scroll will bring new page each time its not casual scroll. I haven't found any guide regarding this on internet so far.
I don't know about how to build it, nothing is popping in my mind for days now. I've tried pageview with gesture detector for swiping up and down, it doesn't works as desired and appbar is static too and the bottom containers as well I don't want this. What I want is the page/screen to flow under the appbar or even a button on top right corner and under 2 buttons on the bottom.
Create a column of Containers where each Container's height and width equals the height and width of the screen. You can do that by using:
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
Also, make sure to wrap your code with a SingleChildScrollView widget to scroll vertically.
Here's the code:
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: SingleChildScrollView(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(child: Text('Quote number one')),
Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(icon: Icon(Icons.share), onPressed: () {}),
IconButton(
icon: Icon(Icons.favorite), onPressed: () {})
],
),
)
],
),
),
Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: Column(
children: [
Text('Quote number two'),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(icon: Icon(Icons.share), onPressed: () {}),
IconButton(icon: Icon(Icons.favorite), onPressed: () {})
],
)
],
),
)
],
),
),
),
);
}
}
You can use PageView to get this type of view
Drive Video link
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
PageController pageController;
PageView pageView;
List<String> quotes = [
'#Quote 1\n\n“I\'m selfish, impatient and a little insecure. I make mistakes, I am out of control and at times hard to handle. But if you can\'t handle me at my worst, then you sure as hell don\'t deserve me at my best.” ',
'#Qoute 2\n\nSo many books, so little time.',
'#Quote 3\n\n A room without books is like a body without a soul'
];
#override
void initState() {
super.initState();
pageController = PageController();
final _quotes = List.generate(quotes.length, (index) => quoteWidget(index));
pageView = PageView(
children: _quotes,
controller: pageController,
scrollDirection: Axis.vertical,
);
}
Widget quoteWidget(int index) {
return Scaffold(
backgroundColor: Colors.black,
body: Column(
children: [
Expanded(
flex: 3,
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Center(
child: Text(
quotes[index],
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w300,
color: Colors.white,
),
),
),
),
),
Expanded(
flex: 1,
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
FloatingActionButton(
onPressed: () {},
child: Icon(Icons.share),
),
const SizedBox(width: 20),
FloatingActionButton(
onPressed: () {},
child: Icon(Icons.favorite_border),
),
],
),
),
Expanded(child: Container())
],
),
);
}
#override
void dispose() {
pageController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
brightness: Brightness.dark,
title: Text(widget.title),
),
body: SafeArea(
child: Stack(
alignment: Alignment.bottomCenter,
children: [
pageView,
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
child: Row(
children: [
RaisedButton.icon(
icon: Icon(Icons.menu_book),
label: Text('General'),
onPressed: () {},
),
const Spacer(),
Container(
width: 50,
height: 50,
margin: const EdgeInsets.symmetric(horizontal: 10),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(5),
),
child: Icon(Icons.color_lens),
),
Container(
width: 50,
height: 50,
margin: const EdgeInsets.symmetric(horizontal: 10),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(5),
),
child: Icon(Icons.person),
),
],
),
)
],
),
),
);
}
}
my buttons are must be on center but must aligned in same line ,
the text in side button also should aligned left.
for that i use textalign left but not works in my code , I dont know why.This is my layout screenshot.
So Can anyone modify my code so that the text inside button aligned left ,without affecting my buttons position .
Thank you
class Something extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Solve Before Downvote !'),
),
body: Container(
color: Color(0xff263238),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SingleChildScrollView(
child: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
MaterialButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0)),
padding: EdgeInsets.only(left: 5),
color: Colors.green,
onPressed: () {},
child: Text('SomeThing', textAlign: TextAlign.left),
),
MaterialButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0)),
color: Colors.green,
onPressed: () { },
child: Text('Nothing', textAlign: TextAlign.left),
),
MaterialButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0)),
color: Colors.green,
onPressed: () {},
child: Text('Can You do something ?',
textAlign: TextAlign.left),
),
MaterialButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0)),
color: Colors.green,
onPressed: () {},
child: Text('Nothing to do !', textAlign: TextAlign.left),
),
],
),
),
)
],
),
),
);
}
}
what i made
Please check the below code. I have comment out the solution in code.
class Something extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Solve Before Downvote !'),
),
body: Container(
width: MediaQuery.of(context).size.width,
color: Color(0xff263238),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SingleChildScrollView(
child: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.all(2.0),
child: Material(
color: Colors.green,
borderRadius: BorderRadius.circular(10.0),
child: InkWell(
onTap: () {
setState(() {
abc = true;
});
},
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 12, 15, 12),
child: Text('SomeThing', textAlign: TextAlign.left),
),
),
),
),
Padding(
padding: const EdgeInsets.all(2.0),
child: Material(
color: Colors.green,
borderRadius: BorderRadius.circular(10.0),
child: InkWell(
onTap: () {
setState(() {
abc = true;
});
},
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 12, 15, 12),
child: Text('Nothing', textAlign: TextAlign.left),
),
),
),
),
Padding(
padding: const EdgeInsets.all(2.0),
child: Material(
color: Colors.green,
borderRadius: BorderRadius.circular(10.0),
child: InkWell(
onTap: () {
setState(() {
abc = true;
});
},
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 12, 15, 12),
child: Text('Can You do something ?',
textAlign: TextAlign.left),
),
),
),
),
Padding(
padding: const EdgeInsets.all(2.0),
child: Material(
color: Colors.green,
borderRadius: BorderRadius.circular(10.0),
child: InkWell(
onTap: () {
setState(() {
abc = true;
});
},
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 12, 15, 12),
child: Text('Nothing to do !',
textAlign: TextAlign.left),
),
),
),
),
],
),
),
)
],
),
),
);
}
}
Can you add Align() and set alignment : Alignment.centerLeft before widget child text
Here am trying to show a text widget if the snapshot of cart items has no values in it, what I tried is snapshot.hasData inside default case but didn't succeed and is there ay better way to do it? am building an e-commerce app wherein I have a cart page containing this code below to load all cart items.
return StreamBuilder(
stream: db
.collection('login')
.document(_userId)
.collection('cartItems')
.snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) return Text('Error: ${snapshot.error}');
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return Text('Loading...');
default:
return ListView(
scrollDirection: Axis.vertical,
children:
snapshot.data.documents.map((DocumentSnapshot document) {
return Container(
width: 110,
child: Card(
elevation: 20,
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(2.0),
child: InkWell(
onTap: () {},
child: Container(
width: 100.0,
child: ListTile(
trailing: IconButton(
icon: Icon(Icons.cancel),
onPressed: () async {
db
.collection('login')
.document(_userId)
.collection('cartItems')
.document(document['model'])
.delete();
},
),
leading: Image.network(
document['image'],
width: 100.0,
height: 100.0,
),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
document['model'],
style: new TextStyle(
fontSize: 18.0, color: Colors.black),
),
Text(
"₹" + document['price'],
style: new TextStyle(
fontSize: 18.0,
color: Colors.black45),
),
],
)),
),
),
),
),
);
}).toList(),
);
}
},
);
}
This worked for me but is this the conventional way ?
if(snapshot.data.documents.isEmpty){
return Center(
child: Text('Your Cart is empty!',style: TextStyle(
fontSize: 30,
color: Colors.black
),),
);