Related
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,
),
This is my app bar with one line text:
appBar: AppBar(
title: Text("Summer Trip"),
centerTitle: true,
actions: [
PopupMenuButton(
itemBuilder: (context){
return [
PopupMenuItem<int>(
value: 0,
child: Text("Test"),
),
];
},
),
],
),
And it gives the following result:
As you see the center of the row is about 25 pixels from screen border.
Now I need to add the second line to my title. This is my solution:
appBar: AppBar(
toolbarHeight: 70,
flexibleSpace: SafeArea(
child: Center(
child: Column(
children: [
Padding(
padding: const EdgeInsets.only(top: 10),
child: Text('Summer Trip',
style: TextStyle(color: Colors.white, fontWeight: FontWeight.w500, fontSize: 20.0)
),
),
Padding(
padding: const EdgeInsets.only(top: 5),
child: Text('Step 1',
style: TextStyle(color: Colors.white54, fontWeight: FontWeight.normal, fontSize: 14.0)
),
),
],
),
),
),
actions: [
PopupMenuButton(
itemBuilder: (context){
return [
PopupMenuItem<int>(
value: 0,
child: Text("Test"),
),
];
},
),
],
),
And this is the result:
As you see, if we increase toolbarHeight of AppBar then arrow and menu buttons move down. However, I need them to stay at the same position. Could anyone say how to do it?
You can wrap your widgets with Align widget.
appBar: AppBar(
toolbarHeight: 70,
flexibleSpace: SafeArea(
child: Center(
child: Column(
children: const [
Padding(
padding: EdgeInsets.only(top: 10),
child: Text('Summer Trip',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w500,
fontSize: 20.0)),
),
Padding(
padding: EdgeInsets.only(top: 5),
child: Text(
'Step 1',
style: TextStyle(
color: Colors.white54,
fontWeight: FontWeight.normal,
fontSize: 14.0),
),
),
],
),
),
),
leading: Align(
alignment: Alignment.topCenter,
child: IconButton(
onPressed: () {},
icon: const Icon(
Icons.arrow_back,
),
),
),
actions: [
Align(
alignment: Alignment.topCenter,
child: PopupMenuButton(
itemBuilder: (context) {
return [
const PopupMenuItem<int>(
value: 0,
child: Text("Test"),
),
];
},
),
),
],
),
Output:
Thanks to #Pavel_K for correcting me, earlier I misunderstood the question.
Corrected Answer
Instead of using flexibleSpace, use title (for the main title) and bottom (for the subtitle). This approach will solve your query, and make the icons stay on top (along the center of the title).
appBar: AppBar(
centerTitle: true,
toolbarHeight: 70,
leading: const Icon(Icons.arrow_back),
title: Column(
children: const [
Text(
'Summer Trip',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w500,
fontSize: 20.0,
),
),
],
),
bottom: const PreferredSize(
preferredSize: Size(0, 14),
child: Padding(
padding: EdgeInsets.only(bottom: 8),
child: Text(
'Step 1',
style: TextStyle(
color: Colors.white54,
fontWeight: FontWeight.normal,
fontSize: 14.0,
),
),
),
),
actions: [
PopupMenuButton(
itemBuilder: (context) {
return [
const PopupMenuItem<int>(
value: 0,
child: Text("Test"),
),
];
},
),
],
),
Old (incorrect) Answer
I think you are using the flexibleSpace with the incorrect intent; it is meant to be used with FlexibleSpaceBar.
What you want to achieve can be simply achieved using title property of AppBar, and it will center the icon on it's own.
It will look like this:
appBar: AppBar(
centerTitle: true,
toolbarHeight: 70,
leading: const Icon(Icons.arrow_back),
title: Column(
children: const [
Padding(
padding: EdgeInsets.only(top: 10),
child: Text(
'Summer Trip',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w500,
fontSize: 20.0,
),
),
),
Padding(
padding: EdgeInsets.only(top: 5),
child: Text(
'Step 1',
style: TextStyle(
color: Colors.white54,
fontWeight: FontWeight.normal,
fontSize: 14.0,
),
),
),
],
),
),
I can not remove the indent from the first ListTile in any way. I think this is some kind of default indent, but I could not overcome it. Is it possible? Attached is the code and screenshot.
Drawer(
child: Container(
padding: EdgeInsets.zero,
child: Column(
children: <Widget>[
SizedBox(
height: 88.0,
width: 1000,
child: DrawerHeader(
decoration: BoxDecoration(
color: Colors.blue,
),
child: Text(
'Настройки',
style: TextStyle(
color: Colors.white,
fontSize: MainStyle.p.fontSize
),
),
),
),
Expanded(
child: Column(
children: <Widget>[
ListTile(
title: Text(
'Язык',
style: TextStyle(
fontSize: MainStyle.p.fontSize
),
),
subtitle: Text(
"Русский",
),
trailing: IconButton(
icon: Icon(Icons.edit),
color: Colors.black,
onPressed: () {
},
),
),
ListTile(
title: Text(
'Выход',
style: TextStyle(
fontSize: MainStyle.p.fontSize
),
),
onTap: () {
exit();
},
),
],
)
),
Container(
child: Align(
alignment: FractionalOffset.bottomCenter,
child: Column(
children: <Widget>[
ListTile(
title: Text(
globalState.version,
style: TextStyle(
fontSize: 15,
color: Colors.grey
),
textAlign: TextAlign.center,
),
),
],
)
)
),
],
),
)
);
P.S. There is not any details, but StackOverflow make me write more text, because of "It looks like your post is mostly code; please add some more details."
add this line to your DrawerHeader:
margin: EdgeInsets.zero,
Trying to make this UI, unable to set gravity or position on dialog. I don't have any idea to make overlay doted line.
class DashboardScreen extends StatefulWidget {
#override
_DashboardScreenState createState() => _DashboardScreenState();
}
class _DashboardScreenState extends State<DashboardScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
body:Container(),
appBar: AppBar(centerTitle: false,
automaticallyImplyLeading: false,
backgroundColor: Colors.white,
elevation: 0,
title: Text(
"Inventory",
textScaleFactor: 1.3,
style: TextStyle(color: Colors.black87, fontFamily: "light"),
),
actions: [
IconButton(
onPressed: (){},
color: Colors.black,
icon: ImageIcon(
AssetImage('assets/images/camera_outline.png'),
size:50,
),
),
IconButton(
onPressed: (){},
color: Colors.black,
icon: ImageIcon(
AssetImage('assets/images/camera_outline.png'),
size:50,
),
),
IconButton(
onPressed: (){
// openAlertBox();
showDialog(context: context,
builder: (_) =>Dialog(
backgroundColor: Colors.transparent,
insetPadding: EdgeInsets.all(20),
child: Column(
children: <Widget>[
Container(
width: double.infinity,
height: 150,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.white
),
padding: EdgeInsets.fromLTRB(20, 50, 20, 20),
child: Text("You can make cool stuff!",
style: TextStyle(fontSize: 24),
textAlign: TextAlign.center
),
),
],
)
));
},
color: Colors.black,
icon: ImageIcon(
AssetImage('assets/images/camera_outline.png'),
size:50,
),
)
],
),
);
}
}
How it is looking.
I am having a hard time figuring this one out (im still new to flutter btw), I created a new screen with form that lets the user fill it out with information and after filling them out, there is a validator and onSaved: on EACH TextFormField() as of the moment, I just want the textform fields to have the datas saved to Firebase Database.
EDIT: I managed to make it work somehow using this code BUT the data Ive input in is nulled in Firebase database (second pic):
child: FlatButton(
color: Colors.blue,
child: Text("Confirm", style: TextStyle(color: Colors.white)),
onPressed: () async {
await db.collection("createdoffers").add(
{
'name': offerName,
'type': offerType,
'start': start,
'end': end,
}
);
},
),
Ive also watched some tutorial but Im having trouble making it work since its kind of a bit different to what Im trying to do (I guess its a beginners problem, Im new to programming and I fell in love with flutter lol)
Now on my Firebase console, I created a new collection with some new
dummy data just to fill in (mind you, I still dont save INPUTS from
the app, just created a collection and put in some dummy data)
The image of my firebase is below:
NULLED data
my code is below for the screen form that I am trying to save data from INPUTS in the TextFormField and saving it all to my database by clicking the FlatButton
My target for this is: 1. Save the data to firebase 2. Read that data and display it to a Container widget, I just want the C and R in CRUD for now
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
class AddOffer extends StatefulWidget {
AddOffer({Key key}) : super(key: key);
#override
_AddOfferState createState() => _AddOfferState();
}
class _AddOfferState extends State<AddOffer> {
String offerName;
String offerType;
String start;
String end;
bool allBranches = false;
bool selectedBranches = false;
final db = Firestore.instance;
final _formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: ListView(
children: <Widget>[
Container(
color: Color(0xFF707070),
height: 200.0,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
InkWell(
onTap: () {
setState(() {
Navigator.pop(context);
});
},
child: Padding(
padding: EdgeInsets.fromLTRB(20, 30, 20, 0),
child: Icon(Icons.arrow_back,
color: Colors.white, size: 25.0),
),
),
Center(
child: Padding(
padding: EdgeInsets.all(80.0),
child: Text(
"DEAL IMAGE",
style: TextStyle(
fontSize: 20.0,
color: Colors.white,
fontWeight: FontWeight.bold),
),
),
),
],
),
),
Form(
key: _formKey,
child: Padding(
padding: EdgeInsets.fromLTRB(30, 30, 30, 0),
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Text(
"Name",
style: TextStyle(
color: Color(0xFF707070),
fontSize: 17.0,
fontWeight: FontWeight.bold),
),
],
),
TextFormField(
decoration: InputDecoration(hintText: 'Enter Offer Name'),
validator: (value) {
if (value.isEmpty) {
}
return 'Please Enter Offer Name';
},
onSaved: (value) => offerName = value,
),
SizedBox(height: 30.0),
Row(
children: <Widget>[
Text(
"Type",
style: TextStyle(
color: Color(0xFF707070),
fontSize: 17.0,
fontWeight: FontWeight.bold),
),
],
),
TextFormField(
decoration: InputDecoration(hintText: 'Enter Offer Type'),
validator: (value) {
if (value.isEmpty) {
}
return 'Please Enter Offer Type';
},
onSaved: (value) => offerType = value,
),
SizedBox(height: 60.0),
Row(
children: <Widget>[
Text(
"Start",
style: TextStyle(
color: Color(0xFF707070),
fontSize: 17.0,
fontWeight: FontWeight.bold),
),
],
),
TextFormField(
decoration:
InputDecoration(hintText: 'Enter Offer Start Date'),
validator: (value) {
if (value.isEmpty) {
}
return 'Please Enter Offer Start Date';
},
onSaved: (value) => offerName = value,
),
SizedBox(height: 30.0),
Row(
children: <Widget>[
Text(
"End",
style: TextStyle(
color: Color(0xFF707070),
fontSize: 17.0,
fontWeight: FontWeight.bold),
),
],
),
TextFormField(
decoration:
InputDecoration(hintText: 'Enter Offer End Date'),
validator: (value) {
if (value.isEmpty) {
}
return 'Please Enter Offer End Date';
},
onSaved: (value) => offerName = value,
),
SizedBox(height: 60.0),
Row(
children: <Widget>[
Column(
children: <Widget>[
Text(
"Valid Until",
style: TextStyle(
color: Color(0xFF707070),
fontSize: 17.0,
fontWeight: FontWeight.bold),
),
SizedBox(height: 5.0),
Text(
"01/01/20",
style: TextStyle(
color: Color(0xFF707070), fontSize: 17.0),
),
],
),
],
),
SizedBox(height: 30.0),
Row(
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"Time of Active",
style: TextStyle(
color: Color(0xFF707070),
fontSize: 17.0,
fontWeight: FontWeight.bold),
),
SizedBox(height: 5.0),
Text(
"12/12/19",
style: TextStyle(
color: Color(0xFF707070), fontSize: 17.0),
),
],
),
],
),
SizedBox(height: 60.0),
Row(
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"Max people (optional)",
style: TextStyle(
color: Color(0xFF707070),
fontSize: 17.0,
fontWeight: FontWeight.bold),
),
SizedBox(height: 5.0),
Text(
"5",
style: TextStyle(
color: Color(0xFF707070), fontSize: 17.0),
),
],
),
],
),
SizedBox(height: 20.0),
Row(
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"Max redemption per member (optional)",
style: TextStyle(
color: Color(0xFF707070),
fontSize: 17.0,
fontWeight: FontWeight.bold),
),
SizedBox(height: 5.0),
Text(
"5",
style: TextStyle(
color: Color(0xFF707070), fontSize: 17.0),
),
],
),
],
),
SizedBox(height: 20.0),
Row(
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"Number of redemption",
style: TextStyle(
color: Color(0xFF707070),
fontSize: 17.0,
fontWeight: FontWeight.bold),
),
SizedBox(height: 5.0),
Text(
"5",
style: TextStyle(
color: Color(0xFF707070), fontSize: 17.0),
),
],
),
],
),
SizedBox(height: 60.0),
Row(
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"Branches",
style: TextStyle(
color: Color(0xFF707070),
fontSize: 17.0,
fontWeight: FontWeight.bold),
),
SizedBox(height: 5.0),
Row(
children: <Widget>[
Checkbox(
value: allBranches,
onChanged: (bool value) {
setState(() {
allBranches = value;
});
},
),
Text(
"All Branches",
style: TextStyle(
color: Color(0xFF707070), fontSize: 17.0),
),
],
),
Row(
children: <Widget>[
Checkbox(
value: selectedBranches,
onChanged: (bool value) {
setState(() {
selectedBranches = value;
});
},
),
Text(
"Selected Branches",
style: TextStyle(
color: Color(0xFF707070), fontSize: 17.0),
),
],
),
],
),
],
),
SizedBox(height: 30.0),
Container(
width: 250.0,
child: FlatButton(
color: Colors.blue,
child: Text("Confirm", style: TextStyle(color: Colors.white)),
onPressed: () {
},
),
),
SizedBox(height: 30.0),
],
),
),
)
],
),
),
);
}
}
WHAT I TRIED SO FAR
child: FlatButton(
color: Colors.blue,
child: Text("Confirm", style: TextStyle(color: Colors.white)),
onPressed: () {
setState(() async{
await db.collection("createdoffers").add(
{
'name': offerName,
'type': offerType,
'start': start,
'end': end,
}
);
}
);
}
)
What Went Wrong
child: FlatButton(
color: Colors.blue,
child: Text("Confirm", style: TextStyle(color: Colors.white)),
onPressed: () async {
await db.collection("createdoffers").add(
{
'name': offerName, // This is null, try to change the way you save data via setState
'type': offerType,
'start': start,
'end': end,
}
);
},
),
What you can do
If you are continuing with this implementation, please do try TextEditingController.
// Declaration
TextEditingController _offerNameTextController = TextEditingController();
// Usage
TextFormField(
controller: _offerNameTextController,
...
)
// Retrieving data from the input field
FlatButton(
onPressed: () {
// Utilize the value (eg. on your Firebase saving method
print(_offerNameTextController.text);
}
)
Further reading
https://api.flutter.dev/flutter/widgets/TextEditingController-class.html
You're passing the value of the textformfield during onsaved. But you forgot to save the form. Add this _formKey.currentState.save();
child: FlatButton(
color: Colors.blue,
child: Text("Confirm", style: TextStyle(color: Colors.white)),
onPressed: () async {
_formKey.currentState.save();
await db.collection("createdoffers").add(
{
'name': offerName,
'type': offerType,
'start': start,
'end': end,
}
);
},
),