In Flutter I have Gridview with three static containers. I am trying to achieve tap action in the Container. The container have Image and Text. I tried with Inkwell.
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: "4.0",
home: Scaffold(
appBar: AppBar(title: const Text(_title)),
body: GridView.count(
crossAxisCount: 3,
children: [
Container(
color: Colors.green,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.work,
color: Colors.white,
size: 60,
),
Text("Work ", style: TextStyle(color: Colors.white, fontSize: 18))
],
),
),
Container(
color: Colors.green,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Icon(
Icons.account_circle,
color: Colors.white,
),
Text("Account", style: TextStyle(color: Colors.white))
],
),
),
Container(
color: Colors.green,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Icon(
Icons.message,
color: Colors.white,
),
Text("Messages", style: TextStyle(color: Colors.white))
],
),
),
],
shrinkWrap: true,
mainAxisSpacing: 10,
crossAxisSpacing: 10,
)));
}
I am not sure about where to set InkWell in the container. I am bit new to Flutter, Any suggestions would be helpful.
First for cleaner code make widget from your container like this:
Widget CustomItem(String label, IconData icon, Function()? onTap) {
return InkWell(
onTap: onTap,
child: Container(
color: Colors.green,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
icon,
color: Colors.white,
size: 60,
),
Text(label, style: TextStyle(color: Colors.white, fontSize: 18))
],
),
),
);
}
then use it like this:
GridView.count(
crossAxisCount: 3,
children: [
CustomItem("Work", Icons.work, () {
print("work clicked");
}),
CustomItem("Account", Icons.account_circle, () {
print("Account clicked");
}),
CustomItem("Messages", Icons.message, () {
print("Messages clicked");
})
],
shrinkWrap: true,
mainAxisSpacing: 10,
crossAxisSpacing: 10,
),
You can use Inkwell Widget for this purpose
InkWell(
onTap: () {
// your action
},
child: YOUR CHILD WIDGET,
),
Related
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
I have a column inside a single child scroll view. I need to make my login screen scroll when I type using the keyboard because the keyboard hides the password text field.
class UserRegistration extends StatefulWidget {
#override
_UserRegistrationState createState() => _UserRegistrationState();
}
class _UserRegistrationState extends State<UserRegistration> {
#override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
statusBarColor: Color(0xFF6C62FF)
));
return SafeArea(
child: GestureDetector(
onTap: () => FocusScope.of(context).requestFocus(FocusNode()),
child: Scaffold(
resizeToAvoidBottomInset: false,
resizeToAvoidBottomPadding: false,
backgroundColor: Color(0xFF6C62FF),
body: SingleChildScrollView(
padding: EdgeInsets.symmetric(horizontal: 30),
child: Column([![enter image description here][1]][1]
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Center(child: FittedBox(child: Text('Welcome', style: TextStyle(fontFamily: 'SourceSans', fontSize: 50, fontWeight: FontWeight.w600, color: Color(0xFFFFD700)),))),
Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Register', style: TextStyle(fontFamily: 'SourceSans', fontSize: 40, fontWeight: FontWeight.w600, color: Colors.white)),
SizedBox(height: 5,),
Text('Start from today', style: TextStyle(fontFamily: 'SourceSans', fontSize: 25, letterSpacing: 1.5,fontWeight: FontWeight.w600, color: Colors.white), overflow: TextOverflow.ellipsis,),
],
),
),
Form(
child: Column(
children: [
EditTextNormal(hintText: 'Email', iconData: Icons.email, textInputType: TextInputType.emailAddress, validate: false, errorText: 'Enter your email',),
SizedBox(height: 20,),
EditTextObscure(hintText: 'Password', iconData: Icons.lock, textInputType: TextInputType.text, validate: false, errorText: 'Enter your password',),
SizedBox(height: 50,),
Container(
height: 50,
width: 180,
child: FlatButton(
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8)
),
onPressed: () {},
color: Colors.white,
child: Text('Register', style: TextStyle(color: Color(0xFF6C62FF), fontSize: 20), overflow: TextOverflow.ellipsis,),
),
)
],
),
),
Center(
child: RichText(
text: TextSpan(
children: <TextSpan>[
TextSpan(text: 'Login', style: TextStyle(color: Color(0xFFFFD700), letterSpacing: 1, wordSpacing: 1.5))
],
text: 'Have an account? ',
style: TextStyle(fontSize: 18, fontFamily: 'SourceSans', fontWeight: FontWeight.bold, letterSpacing: 1, wordSpacing: 1.5)
),
),
),
],
),
),
),
),
);
}
}
This is my code but here when I use a column inside a single child scroll view space evenly does not work. Please give me a solution.
My output:
Expected Output:
Try This
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
physics: NeverScrollableScrollPhysics(),
child: ConstrainedBox(
constraints: BoxConstraints(
minWidth: MediaQuery.of(context).size.width,
minHeight: MediaQuery.of(context).size.height,
),
child: IntrinsicHeight(
child: Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
// CONTENT HERE
],
),
),
),
),
);
}
Add Container inside SingleChildScrollView and assign it height based on your keyboard open or not.
Add Dependency:
dependencies:
keyboard_visibility: ^0.5.6
Initialize keyboard listener in initState() for callback
bool _isKeyBoardShown = false;
#protected
void initState() {
super.initState();
KeyboardVisibilityNotification().addNewListener(
onChange: (bool visible) {
setState(() {
_isKeyBoardShown = visible;
});
},
);
}
Based on _isKeyBoardShown value decide whether to add additional height on the screen or not.
Container(
width: MediaQuery.of(context).size.width,
height: _isKeyBoardShown
? MediaQuery.of(context).size.height +
MediaQuery.of(context).size.height / 2
: MediaQuery.of(context).size.height,
child: Column(....)
)
Note: Use MediaQuery to decide additional height don't use hard-coded values
here I used MediaQuery.of(context).size.height / 2
I can't understand what I'm doing wrong.
I have created a small detail page for an application that I am developing on vegan recipes.
I have a space that I can't take away and I don't understand what generated it. Space is what you see circled in red.
Can you help me ?
Thank you,
Vincenzo
class _CookDetailState extends State<CookDetail> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back, color: Colors.white),
onPressed: () => Navigator.of(context).pop(),
),
title: Text(this.widget.ricetta.title),
backgroundColor: AppColors.darkModeBackgroundColor),
body: Stack(
children: <Widget>[
Positioned(
top: 0,
left: 0,
right: 0,
bottom: 0,
child: Hero(
tag: this.widget.ricetta.title,
child: Container(
decoration:
BoxDecoration(image: DecorationImage(image: NetworkImage("https://cdn.pixabay.com/photo/2017/09/16/19/21/salad-2756467__340.jpg"),
fit: BoxFit.cover)),
),
),
),
// white container
Positioned(
left: 24.0,
right: 24.0,
bottom: 16.0,
child: Container(
//height: MediaQuery.of(context).size.height * 0.75,
//height: 650,
child: ClipRect(
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 100, sigmaY: 200),
child: Container(
padding: EdgeInsets.all(16.0),
height: 500,
decoration: BoxDecoration(borderRadius: BorderRadius.circular(16.0), color: Colors.white.withOpacity(0.2)),
child: SingleChildScrollView(
child: Container(
padding: EdgeInsets.all(16.0),
height: 800,
decoration: BoxDecoration(borderRadius: BorderRadius.circular(16.0), color: Colors.white.withOpacity(0.2)),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
children: <Widget>[
Text(
this.widget.ricetta.title,
style: TextStyle(color: Colors.white, fontSize: 20.0, fontWeight: FontWeight.bold),
),
Spacer(),
Icon(
Icons.favorite_border,
size: 24.0,
color: Colors.white,
),
],
),
new Container(
child: ListView(
shrinkWrap: true,
children: <Widget>[
this._generateList(this.widget.ricetta.listIngredieti),
this._generateStep(this.widget.ricetta.listPassaggio),
],
),
),
],
),
),
),
),
),
),
),
),
],
),
);
}
Widget _generateList(List<Ingrediente> listIngrediente){
return Column(
children: <Widget>[
for ( var myElement in listIngrediente ) Text(
myElement.title + " " + myElement.quantita,
style: TextStyle(color: Colors.white, fontSize: 12, fontWeight: FontWeight.w600))
],
);
}
Widget _generateStep(List<StepRicetta> listStep){
return Column(
children: <Widget>[
for (var myStep in listStep) CheckboxListTile(title: AutoSizeText(myStep.title),
value: false, onChanged: (bool selected){
print("Valore selected");
},
secondary: const Icon(Icons.hourglass_empty),
)
],
);
}
}
My concept would be to leave the writing "Recipe 1", blocked, scrolling only and exclusively the list concerning the list of ingredients, such as "Put the bread", "Put 300 g of water"
I think your second EdgeInsets.all(16.0) create the space, do you have try this : EdgeInset.only(left: 16.0, right: 16.0) ?
I am new to flutter so I am unable to found the problem in this code. All things are working fine but I am trying to use Grid list with two rows which are working fine when I am giving height to the parent container of the list but I want to wrap the Height according to items.
void main() {
runApp(new MaterialApp(
home: new MyHome(),
));
}
class MyHome extends StatefulWidget {
#override
_AppState createState() => _AppState();
}
TextEditingController controller = new TextEditingController();
class _AppState extends State<MyHome> {
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: PreferredSize(
preferredSize: Size(null, 180),
child: CustomAppBar(_scaffoldKey, controller),
),
drawer: createDrawer(),
body: SingleChildScrollView(
child: Container(
color: Colors.black12,
//=========Main Container For Scrollview==============//
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 15, 0, 0),
child: Column(
children: <Widget>[
Container(
//================Container for Categories==================//
color: Colors.white,
child: Padding(
padding: const EdgeInsets.fromLTRB(15, 10, 15, 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Column(
children: <Widget>[
CircleAvatar(
backgroundImage:
ExactAssetImage('images/user_icon.png'),
minRadius: 20,
maxRadius: 30,
),
Text(
'Women',
style: TextStyle(
fontSize: 13,
color: Colors.black,
fontFamily: 'SFProRegular'),
)
],
),
Column(
children: <Widget>[
CircleAvatar(
backgroundImage:
ExactAssetImage('images/user_icon.png'),
minRadius: 20,
maxRadius: 30,
),
Text(
'Women',
style: TextStyle(
fontSize: 13,
color: Colors.black,
fontFamily: 'SFProRegular'),
)
],
),
Column(
children: <Widget>[
CircleAvatar(
backgroundImage:
ExactAssetImage('images/user_icon.png'),
minRadius: 20,
maxRadius: 30,
),
Text(
'Women',
style: TextStyle(
fontSize: 13,
color: Colors.black,
fontFamily: 'SFProRegular'),
)
],
),
Column(
children: <Widget>[
CircleAvatar(
backgroundImage:
ExactAssetImage('images/user_icon.png'),
minRadius: 20,
maxRadius: 30,
),
Text(
'Women',
style: TextStyle(
fontSize: 13,
color: Colors.black,
fontFamily: 'SFProRegular'),
)
],
),
],
),
),
),
Card(
child: SizedBox(
height: 200.0,
child: Carousel(
images: [
NetworkImage(
'https://cdn-images-1.medium.com/max/2000/1*GqdzzfB_BHorv7V2NV7Jgg.jpeg'),
NetworkImage(
'https://cdn-images-1.medium.com/max/2000/1*wnIEgP1gNMrK5gZU7QS0-A.jpeg'),
],
dotSize: 4.0,
dotSpacing: 15.0,
indicatorBgPadding: 5.0,
borderRadius: false,
)),
),
//======================Here is the Problem===========//
GridView.count(
childAspectRatio: 4.0,
// Create a grid with 2 columns. If you change the scrollDirection to
// horizontal, this produces 2 rows.
crossAxisCount: 2,
// Generate 100 widgets that display their index in the List.
children: List.generate(100, (index) {
return Center(
child: Text(
'Item $index',
style: Theme.of(context).textTheme.headline,
),
);
}),
)
],
),
),
),
),
);
}
}
Since you're using SingleChildScrollView as a parent widget for your GridView, so you need to specify primary: false and shrinkWrap: true so GridView takes the least height based on the item counts.
Complete code:
void main() {
runApp(new MaterialApp(
home: new MyHome(),
));
}
class MyHome extends StatefulWidget {
#override
_AppState createState() => _AppState();
}
TextEditingController controller = new TextEditingController();
class _AppState extends State<MyHome> {
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: PreferredSize(
preferredSize: Size(null, 180),
child: CustomAppBar(_scaffoldKey, controller),
),
drawer: createDrawer(),
body: SingleChildScrollView(
child: Container(
color: Colors.black12,
//=========Main Container For Scrollview==============//
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 15, 0, 0),
child: Column(
children: <Widget>[
Container(
//================Container for Categories==================//
color: Colors.white,
child: Padding(
padding: const EdgeInsets.fromLTRB(15, 10, 15, 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Column(
children: <Widget>[
CircleAvatar(
backgroundImage:
ExactAssetImage('images/user_icon.png'),
minRadius: 20,
maxRadius: 30,
),
Text(
'Women',
style: TextStyle(
fontSize: 13,
color: Colors.black,
fontFamily: 'SFProRegular'),
)
],
),
Column(
children: <Widget>[
CircleAvatar(
backgroundImage:
ExactAssetImage('images/user_icon.png'),
minRadius: 20,
maxRadius: 30,
),
Text(
'Women',
style: TextStyle(
fontSize: 13,
color: Colors.black,
fontFamily: 'SFProRegular'),
)
],
),
Column(
children: <Widget>[
CircleAvatar(
backgroundImage:
ExactAssetImage('images/user_icon.png'),
minRadius: 20,
maxRadius: 30,
),
Text(
'Women',
style: TextStyle(
fontSize: 13,
color: Colors.black,
fontFamily: 'SFProRegular'),
)
],
),
Column(
children: <Widget>[
CircleAvatar(
backgroundImage:
ExactAssetImage('images/user_icon.png'),
minRadius: 20,
maxRadius: 30,
),
Text(
'Women',
style: TextStyle(
fontSize: 13,
color: Colors.black,
fontFamily: 'SFProRegular'),
)
],
),
],
),
),
),
Card(
child: SizedBox(
height: 200.0,
child: Carousel(
images: [
NetworkImage(
'https://cdn-images-1.medium.com/max/2000/1*GqdzzfB_BHorv7V2NV7Jgg.jpeg'),
NetworkImage(
'https://cdn-images-1.medium.com/max/2000/1*wnIEgP1gNMrK5gZU7QS0-A.jpeg'),
],
dotSize: 4.0,
dotSpacing: 15.0,
indicatorBgPadding: 5.0,
borderRadius: false,
)),
),
GridView.count(
shrinkWrap: true,
primary: false,
childAspectRatio: 4.0,
// Create a grid with 2 columns. If you change the scrollDirection to
// horizontal, this produces 2 rows.
crossAxisCount: 2,
// Generate 100 widgets that display their index in the List.
children: List.generate(100, (index) {
return Center(
child: Text(
'Item $index',
style: Theme.of(context).textTheme.headline,
),
);
}),
)
],
),
),
),
),
);
}
}
I want make a button with text and icon inside it, with custom background color and custom width. with fix position (not scrollable). would you like to help me please ?
here are the code:
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.shifting,
currentIndex: 0, // this will be set when a new tab is tapped
items: [
BottomNavigationBarItem(icon: Icon(Icons.supervised_user_circle), title: Text('Players'),backgroundColor: Colors.red),
BottomNavigationBarItem(icon: Icon(Icons.whatshot), title: Text('Trending'),backgroundColor: Colors.blueAccent),
BottomNavigationBarItem(icon: Icon(Icons.access_time), title: Text('Highlights'),backgroundColor: Colors.yellow)
]
its only give a color for the icon.
this is what I want:
Here you go
Widget build(context) {
return Scaffold(
bottomNavigationBar: Container(
height: 56,
margin: EdgeInsets.symmetric(vertical: 24, horizontal: 12),
child: Row(
children: <Widget>[
Container(
width: 66,
color: Colors.green,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[Icon(Icons.chat, color: Colors.white), Text("CHAT", style: TextStyle(color: Colors.white))],
),
),
Container(
width: 66,
color: Colors.green,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[Icon(Icons.notifications_active, color: Colors.white), Text("NOTIF", style: TextStyle(color: Colors.white))],
),
),
Expanded(
child: Container(
alignment: Alignment.center,
color: Colors.red,
child: Text("BUY NOW", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18)),
),
),
],
),
),
);
}
You may want to look at the concept of a BottomAppBar instead.
This bar accepts any widget as children not just BottomNavigationBarItems.
You could try this:
BottomAppBar(
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Expanded(
child: SizedBox(
height: 44,
child: Material(
type: MaterialType.transparency,
child: InkWell(
onTap: () {},
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.add, color: Colors.blue, size: 24),
Text("Add")
],
),
),
),
),
),
]
),
)