How to make a widget available after a selection in dropdown? - flutter

I want to create a card after a user makes a selection in drop down how to achieve this in flutter. The UI model is given below.
The first card is like a permanent one but the second card should appear after if there is any change in the dropdown button.
The lower card should be scrollable and the size should be dynamic like a listview. if the Key and data increases the value should increase.
The Code I have used for creating the app bar and the 1st card is here.
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
toolbarHeight: 75,
title: Center(
child: Text(
'Flutter App',
style: GoogleFonts.lato(
textStyle:
TextStyle(fontWeight: FontWeight.bold, fontSize: 26)),
),
),
),
body: ListView(children: [
Column(
children: [
Container(
height: 250,
child: Column(children: [
Card(
child: Column(
children: [
Row(children: [
Padding(
padding: EdgeInsets.only(left: 30, top: 15),
child: Text(
'Text here',
style: GoogleFonts.poppins(
textStyle: TextStyle(
fontWeight: FontWeight.w700,
fontSize: 37,
)),
textAlign: TextAlign.left,
),
),
]),
Padding(
padding: EdgeInsets.only(top: 30),
child: Text(
'Some text here',
style: GoogleFonts.lato(
textStyle: TextStyle(fontSize: 18)),
),
),
Padding(
padding: EdgeInsets.only(top: 30),
child: DropdownButton(
items: markets
.map<DropdownMenuItem<String>>((String val) {
return DropdownMenuItem<String>(
value: val, child: Text(val));
}).toList(),
onChanged: (sto) {
setState(() {
_mySelection = sto;
});
retrievedata.getPrice(_mySelection);
},
value: _mySelection,
hint: Text('Hint text here'),
),
),
],
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
elevation: 5,
margin: EdgeInsets.all(10),
),
]),
),
],
),
]),
);
}

You can wrap the Card that should appear after dropDownChanges to Visibility widget.
Add this variable
bool _isVisible = false;
Make changes to DropdownButton
DropdownButton(
...
onChanged: (sto) {
setState(() {
_mySelection = sto;
_isVisible = true;
});
retrievedata.getPrice(_mySelection);
},
...
),
Wrap the Card with Visiblity
Visibility (
visible: _isVisible,
child: Card(
child: ....
),
),
If you want the card to be always visible and enable interaction only after the DropdownButton changes, wrap the card to IgnorePointer instead of visibility.

You can achieve this by having an additional state that is responsible for visibility of second card. Something like this:
final visible = false;
#override
Widget build(BuildContext context) {
return
...
onChanged: (sto) {
setState(() {
_mySelection = sto;
visible = true;
});
retrievedata.getPrice(_mySelection);
},
...
And later on we can make the second card visible based on this value:
visible ? SecondCard(
...
) : SizedBox.shrink()
This ensures that nothing is shown until visible is set to true

Related

Passing variables from Tab to DefaultTabController - Flutter

I have a DefaultTabController with two pages nested in a scaffold. In my scaffold's App Bar is a save button and I want this button to return a value to a previous page, based on a variable that is calculated in one of the tabs. How do I get this value?
Here is my DefaultTabController
DefaultTabController(
initialIndex: index,
length: 2,
child: Scaffold(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
appBar: AppBar(
elevation: 0,
backgroundColor: fumigruen_accent,
leading: CloseButton(
color: Colors.black,
onPressed: () {
Navigator.of(context).pop();
},
),
actions: buildEditingActions(),
),
body: Column(children: [
tabBar(),
Expanded(
child: TabBarView(children: [
//1st Tab
GewichtsrechnerEinfach(),
//2nd Tab
Column()
]),
)
]),
));}
And here is the save-Button I want to use to pass a varaible to the previous screen
List<Widget> buildEditingActions() => [
ElevatedButton.icon(
style: ElevatedButton.styleFrom(
backgroundColor: fumigruen_accent,
elevation: 0,
foregroundColor: Colors.black,
),
onPressed: () {
Navigator.of(context).pop(gewicht);
},
icon: Icon(Icons.save),
label: Text("Speichern"))
];
The tabbar Code
Widget tabBar() => TabBar(
labelColor: Theme.of(context).primaryColor,
indicatorColor: Theme.of(context).primaryColor,
labelStyle: TextStyle(fontWeight: FontWeight.bold),
tabs: [
Tab(
child: Row(mainAxisSize: MainAxisSize.min, children: [
Icon(
Icons.assessment_outlined,
),
SizedBox(
width: 5,
),
Text("Einfach")
]),
),
Tab(
child: Row(mainAxisSize: MainAxisSize.min, children: [
Icon(
Icons.addchart,
),
SizedBox(
width: 5,
),
Text("Fortgeschritten")
]),
),
]);
and an extract of the GewichtsrechnerEinfach():
class _GewichtsrechnerEinfachState extends State<GewichtsrechnerEinfach> {
final _formKey = GlobalKey<FormState>();
num koerperlaenge = 0;
num brustumfang = 0;
var _koerperlaengeControler = TextEditingController();
var _brustumfangControler = TextEditingController();
num gewicht = 0;
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: SingleChildScrollView(
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
//{two textinput fields setting the variables koerperlaenge and brustumfang are here}
Center(
child: Container(
width: MediaQuery.of(context).size.width * 0.8,
decoration: ThemeHelper().buttonBoxDecoration(context),
child: ElevatedButton(
style: ThemeHelper().buttonStyle(),
child: Padding(
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
child: Text(
"berechnen".toUpperCase(),
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
onPressed: () async {
if (_formKey.currentState!.validate()) {
setState(() {
gewicht = Gewichtskalkulator().einfach(
brustumfang.toDouble(),
koerperlaenge.toDouble());
});
}
}),
),
),
],
),
),
),
);
}
The variable "gewicht" is calculated and changed in the first tab "GewichtsrechnerEinfach". So how do I get the changed variable to this main screen so that I can use it while saving?
Thanks a lot :)
As I found out by chatting in comments section, you are changing a value in a Page and you want to use it in another pages or screen, this is why you should use StateManagement something like Provider.
As you said you need to change the gewicht variable and use it where ever you want.
step 1) please add provider: ^6.0.5 (or any version that is compatible) in your pubspec.yaml and call flutter pub get.
step 2) now you should create a provider class to make all the variables that you want to use everywhere, alive. please create a dart file named:
gewichtsrechner_einfach_provider.dart
step 3) now you should put these codes in you provider class:
import 'package:flutter/material.dart';
class GewichtsrechnerEinfachProvider extends ChangeNotifier{
num _gewicht = 0;
num get gewicht => _gewicht;
void setGewicht(num newGewicht){
_gewicht = newGewicht;
notifyListeners();
}
}
as you see _gewicht is private and you can use it alive entire your project.
step 4) you should add the provider to main.dart:
MultiProvider(
providers: [
// you are adding your provider
ListenableProvider.value(value: GewichtsrechnerEinfachProvider()),
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
home: ...........
),
);
step 5) now you should use its setter and getter of gewicht:
as you see in _GewichtsrechnerEinfachState you are setting the value and should do this by using Consumer:
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: SingleChildScrollView(
child: Consumer<GewichtsrechnerEinfachProvider>(//note this
builder: (context, gewichtsrechnerEinfachProvider ,child) {
return Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
//{two textinput fields setting the variables koerperlaenge and brustumfang are here}
Center(
child: Container(
width: MediaQuery.of(context).size.width * 0.8,
decoration: ThemeHelper().buttonBoxDecoration(context),
child: ElevatedButton(
style: ThemeHelper().buttonStyle(),
child: Padding(
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
child: Text(
"berechnen".toUpperCase(),
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
onPressed: () async {
if (_formKey.currentState!.validate()) {
// and note this
gewichtsrechnerEinfachProvider.setGewicht(
Gewichtskalkulator().einfach(
brustumfang.toDouble(),
koerperlaenge.toDouble())
);
}
}),
),
),
],
),
);
}
),
),
);
}
step 6) now you should use its getter where ever you want:
List<Widget> buildEditingActions() => [
Consumer<GewichtsrechnerEinfachProvider>(
builder: (context, gewichtsrechnerEinfachProvider ,child) {
return ElevatedButton.icon(
style: ElevatedButton.styleFrom(
backgroundColor: fumigruen_accent,
elevation: 0,
foregroundColor: Colors.black,
),
onPressed: () {
// Navigator.of(context).pop(gewicht);
print('here is your result:
${gewichtsrechnerEinfachProvider.gewicht}');
},
icon: Icon(Icons.save),
label: Text("Speichern"));
}
)
];
note that you can use your provider where ever you want even with this code not just consumer:
var gewichtsrechnerEinfachProvider = Provider.of<GewichtsrechnerEinfachProvider>(context,listen: false);
as you see by changing its value the provider notifies to where you are showing it.
Ich hoffe, ich konnte dir helfen ;)
happy coding my friend...

DropdownButton<List> using local data - Do not list items on the screen, only after hot reload

I'm new to the flutter and I don't know how to solve this problem.
I have a List with await method, but my screen does not await for the list to load to list, only when I update with the hot-reload, the screen works.
My async method
ListaRefeitorio? _selecione;
List<ListaRefeitorio> _refeitorios = <ListaRefeitorio>[];
RefeitorioController controller = new RefeitorioController();
#override
void initState() {
super.initState();
_listarRefeitorios();
}
My Screen
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBarControleAcessoWidget("Refeitório"),
body: Column(
children: [
SizedBox(height: 30),
Container(
child: Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
padding: EdgeInsets.only(left: 16, right: 16),
decoration: BoxDecoration(
border:
Border.all(color: AppColors.chartSecondary, width: 1),
borderRadius: BorderRadius.circular(15),
),
child: DropdownButton<ListaRefeitorio>(
hint: Text("Selecione Refeitório"),
dropdownColor: AppColors.white,
icon: Icon(Icons.arrow_drop_down),
iconSize: 36,
isExpanded: true,
underline: SizedBox(),
style: TextStyle(
color: AppColors.black,
fontSize: 20,
),
value: _selecione,
onChanged: (ListaRefeitorio? novoValor) {
setState(() {
_selecione = novoValor;
});
},
items: _refeitorios.map((ListaRefeitorio valueItem) {
return new DropdownMenuItem<ListaRefeitorio>(
value: valueItem,
child: new Text(valueItem.acessoPontoAcessoDescricao),
);
}).toList(),
),
),
),
),
),
Container(),
Expanded(
child: GridView.count(
crossAxisSpacing: 12,
mainAxisSpacing: 12,
crossAxisCount: 2,
children: [
Container(
child: SizedBox.expand(
child: FlatButton(
child: CardsWidget(
label: "Ler QR Code",
imagem: AppImages.scanQrCode,
),
onPressed: () {
scanQRCode();
},
),
),
),
Container(
child: SizedBox.expand(
child: FlatButton(
child: CardsWidget(
label: "Sincronizar Dados", imagem: AppImages.sync),
onPressed: () {
controller.sincronizar();
// RefeitorioService.listarRefeitorio();
},
),
),
),
SizedBox(height: 30),
Text("Resultado"),
Text(QRCode),
Text(DataHora),
Text(_selecione.toString()),
],
),
),
],
));
}
I've tried using the futurebuilder but I don't think that's my problem.
I don't know what to do anymore
I had the same issue with the DropDownButton list only displaying because of the Hot Reload refreshing the state.
When using a custom mapping of a List remember to use setState() in the method that populates the List with data (in my case it was pulling from Sqflite).
//This populate method would be called in either initstate or afterFirstLayout
populateDataList() {
await controller.getList().then((list) =>
setState(() {
_refeitorios = list;
})
);
}

Flutter return widgets in for loop

My code below is working, but instead of returning multiple widgets based on the length of the list, it stops in the first round and after a lot of research and googling I understand that it stops because I'm returning a widget. So basically the for loop stops when it hits the "return".
And if I don't add the "return" before the widget it return's nothing or it gives error saying that the "widget expecting a return type but nothing returning". So no "I think" I know th issue but I can't find the solution.
#override
Widget build(BuildContext context) {
for (var allAttributes in widget.allAttributes) {
//print(allAttributes.name);
bool attributeCheck;
if(widget.attributes.length > 0){
for(var attributes in widget.attributes){
if(allAttributes.id == attributes.attributeId){
return Row(
children: <Widget>[
new Container(
alignment: Alignment(-1.0, -1.0),
child: Padding(
padding: const EdgeInsets.only(bottom: 10.0, right: 10.0),
child: Text(
allAttributes.name + ':',
style: TextStyle(
color: Colors.black,
fontSize: 20,
fontWeight: FontWeight.w600),
),
)),
DropdownButton<Attributes>(
hint: Text("Select item"),
value: selectedUser,
onChanged: (Attributes Value) {
setState(() {
selectedUser = Value;
});
},
items: widget.attributes.map((Attributes attributes) {
return DropdownMenuItem<Attributes>(
value: attributes,
child: Row(
children: <Widget>[
SizedBox(
width: 10,
),
Text(
attributes.value,
style: TextStyle(color: Colors.black),
),
],
),
);
}).toList(),
),
],
);
}
}
}
}
return Text('Nothing');
}
I did try with the map but it didn't work too, Here's the code for the map:
#override
Widget build(BuildContext context) {
widget.allAttributes.map((AllAttributes allAttributes) {
//print(allAttributes.name);
widget.attributes.map((Attributes attributes){
return Row(
children: <Widget>[
new Container(
alignment: Alignment(-1.0, -1.0),
child: Padding(
padding: const EdgeInsets.only(bottom: 10.0, right: 10.0),
child: Text(
allAttributes.name + ':',
style: TextStyle(
color: Colors.black,
fontSize: 20,
fontWeight: FontWeight.w600),
),
)),
DropdownButton<Attributes>(
hint: Text("Select item"),
value: selectedUser,
onChanged: (Attributes Value) {
setState(() {
selectedUser = Value;
});
},
items: widget.attributes.map((Attributes attributes) {
return DropdownMenuItem<Attributes>(
value: attributes,
child: Row(
children: <Widget>[
SizedBox(
width: 10,
),
Text(
attributes.value,
style: TextStyle(color: Colors.black),
),
],
),
);
}).toList(),
),
],
);
}).toList();
}).toList();
return Text('Nothing');
}
I think Map method of list could be best solution for this type of situation.
It is really hard to change such big code without edit, so i showed how you can do in your case.
List<int> _data = [1, 2, 3, 4, 5, 6];
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: Column(
children: _data.map((e) {
return Text(e.toString());
}).toList(),
)),
);
}
I still tried my best to change code. i hope following code work without any error.
Moreover, you was making list two time by wrapping list with list(for loop with for loop) so removed it.
//print(allAttributes.name);
return Column(
children:
widget.attributes.length>0? widget.attributes.map((Attributes attributes){
return Row(
children: <Widget>[
new Container(
alignment: Alignment(-1.0, -1.0),
child: Padding(
padding: const EdgeInsets.only(bottom: 10.0, right: 10.0),
child: Text(
allAttributes.name + ':',
style: TextStyle(
color: Colors.black,
fontSize: 20,
fontWeight: FontWeight.w600),
),
)),
DropdownButton<Attributes>(
hint: Text("Select item"),
value: selectedUser,
onChanged: (Attributes Value) {
setState(() {
selectedUser = Value;
});
},
items: widget.attributes.map((Attributes attributes) {
return DropdownMenuItem<Attributes>(
value: attributes,
child: Row(
children: <Widget>[
SizedBox(
width: 10,
),
Text(
attributes.value,
style: TextStyle(color: Colors.black),
),
],
),
);
}).toList(),
),
],
);
}).toList(): [Text('Nothing')]);

How to center text in DropdownButton?

I'm trying to make the DropdownButton hint, text and menu items appear in the center instead of left but TextAlign.center does not seem to be doing anything.
Image of Dropdown with the hint:
Image of Dropdown with the selected item as text:
Image of the Menu items when arrow is pressed:
My code:
return Theme(
data: ThemeData(canvasColor: blackTrans2, brightness: Brightness.dark),
child:Container(
width: MediaQuery.of(context).size.width/1.2,
decoration: BoxDecoration(
color: blackTrans,
borderRadius: BorderRadius.all(Radius.circular(5.0)),
),
child:DropdownButtonHideUnderline(
child: ButtonTheme(
alignedDropdown: true,
child: DropdownButton(
value: _dateSelected,
hint: AutoSizeText(NA_FLIGHT_PAGE_DROPDOWN, style: TextStyle(color: white,),textAlign: TextAlign.center,),
isDense: false,
onChanged: (String newValue){
setState(() {
_dateSelected = newValue;
});
},
items: snapshot.data.documents.map((DocumentSnapshot document){
return DropdownMenuItem<String>(
value: document.documentID,
child: AutoSizeText(document.documentID, style: TextStyle(color: white,),textAlign: TextAlign.center,),
);
}).toList(),
),
),
)
)
);
Not sure if this affects anything but I'm using AutoSizeText in order to resize my text dynamically.
Update: I managed to make the Menu items appear in the center by using Center, but the text and hint is still remains to the left tho even with Center... :
// Does not seem to change the hint or text position (when menu item selected)
hint: Center(child:AutoSizeText(NA_FLIGHT_PAGE_DROPDOWN, style: TextStyle(color: white,),textAlign: TextAlign.center,)),
// Changes the menu item to the center instead of left
child: Center(child:AutoSizeText(document.documentID, style: TextStyle(color: white,),textAlign: TextAlign.center,)),
For those who are seeing option to change flutter class dropdown.dart. You don't need to do that.
Do this:
set property isExpanded to true
use Center widget with DropdownMenuItem class children.
IsExpanded will also take care of overflow.
DropdownButton(
isExpanded: true,
value: category_selected,
items: categories.map<DropdownMenuItem<String>>((var value) {
return DropdownMenuItem<String>(
value: value["name"],
child: Center(
child: Text(
value["name"],
textAlign: TextAlign.center,
),
),
);
}).toList(),
),
A simple and straight answer is Not Possible. But there's always a way.
You have to go to the dropdown.dart provided with the flutter package.If you're using VSCode Ctrl+Click on the DrpoDownMenuItem class and change the following code.
#override
Widget build(BuildContext context) {
return Container(
height: _kMenuItemHeight,
alignment: AlignmentDirectional.centerStart,
child: child,
);
}
Change the alignment: AlignmentDirectional.centerStart to alignment: AlignmentDirectional.center and it should work :)
Yes you can do it like the following code sample.
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(5))),
margin: EdgeInsets.only(top: 5, bottom: 5),
padding: EdgeInsets.only(right: 5, left: 5),
child: ConstrainedBox(
constraints: const BoxConstraints(
minWidth: double.infinity,
),
child: Container(
child: Center(
child: DropdownButtonHideUnderline(
child: DropdownButton(
iconSize: 0.0,
items: <DropdownMenuItem<int>>[
new DropdownMenuItem(
child: new Text(
'Optional Information',
style: TextStyle(color: Colors.black54),
),
),
new DropdownMenuItem(
child: new Text(
'Male',
style: TextStyle(color: Colors.black54),
),
),
new DropdownMenuItem(
child: new Text(
'Female',
style: TextStyle(color: Colors.black54),
)),
],
onChanged: (V) {},
),
),
),
),
),
),
Here i have used my color and decoration view for my porpose you can change it as per you requirement.
You can use the code below to perfectly position the text in the dropdown at the center and still have the dropdown icon positioned at the right end of your container.
DropdownButtonHideUnderline(
child: DropdownButton(
value: dropdownvalue,
items: items.map((String items) {
return DropdownMenuItem(
value: items,
child: Center(
child: Text(items),
),
);
}).toList(),
onChanged: (String? newValue) {
setState(() {
dropdownvalue = newValue!;
});
},
isExpanded: true,
),
),
So we simply add isExpanded: true, and add a Center() widget to the Text(items) in the DropdownMenuItem().
There is a alignment property in DropdownMenuItem class.
DropdownButton(
//...
isExpanded: true, // this will take all width available
)
If you want to change it's width wrap DropdownButton with SizedBox or Padding.
item: [
DropdownMenuItem(
//...
alignment: AlignmentDirectional.center,
),
]
in your DropdownButtonFormField or DropdownButton
add
isExpanded: true
thing like this
DropdownButtonFormField<String>(isExpanded: true)

How to center the Title of a ListTile in Flutter

I have been trying again today to center the title of a Flutter ListTile. Over the past few days I have spent an hour or two Googling and trying things then loosing my cool and giving up.
I am just learning Flutter and love the concept but can find no video training courses (Lynda.com, uDemy.com etc). I have read through the relevant documentation but cannot get rid of all the red lines that appear when I try to apply them to my code.
There must be logic in the syntax but after 2 weeks I have not worked it out yet.
Back to the problem, I have tried
List<Widget> list = <Widget>[
new ListTile(
new child: Center (
title:
new Text('Title 1',
style: new TextStyle(
fontWeight: FontWeight.w500,
color: Colors.deepOrangeAccent,
fontSize: 25.0)),
)
),
];
List<Widget> list = <Widget>[
new ListTile(
title:
new child: Center (
new Text('Title 2',
style: new TextStyle(
fontWeight: FontWeight.w500,
color: Colors.deepOrangeAccent,
fontSize: 25.0)),
)
),
];
List<Widget> list = <Widget>[
new ListTile(
child: Center
title: (
new Text('Title 3',
style: new TextStyle(
fontWeight: FontWeight.w500,
color: Colors.deepOrangeAccent,
fontSize: 25.0)),
)
),
];
List<Widget> list = <Widget>[
new ListTile(
title: Center
new Text('Title 4',
style: new TextStyle(
fontWeight: FontWeight.w500,
color: Colors.deepOrangeAccent,
fontSize: 25.0)),
)
),
];
Please help me with this problem and also where to find a video course on Flutter?
On the upside, if this continues I will no longer be grey, I will be bald instead.
I thought I worked it out when I added 'textAlign: TextAlign.center,' to the text object. There were no red lines but the text was still left aligned.
I am not sure what have you tried, but you in order to center the title of the ListTile you can use a center widget like you did in your code, or wrap your text within a Row widget and set mainAxisAlignment: MainAxisAlignment.center.
Using Center widget:
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(title: new Text("ListTile Example"),),
body: new ListView(
children: new List.generate(7, (int index) {
return new ListTile(
title: new Center(child: new Text("Centered Title#$index",
style: new TextStyle(
fontWeight: FontWeight.w500, fontSize: 25.0),)),
subtitle: new Text("My title is centered"),
);
}),
),
);
}
Using Row widget:
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(title: new Text("ListTile Example"),),
body: new ListView(
children: new List.generate(7, (int index) {
return new ListTile(
title: new Row(children: <Widget>[new Text("Centered Title#$index",
style: new TextStyle(
fontWeight: FontWeight.w500, fontSize: 25.0),)
], mainAxisAlignment: MainAxisAlignment.center,),
subtitle: new Text("My title is centered"),
);
}),
),
);
}
However, your problem is not about centering the title, it is about you are trying to insert too big of a Text inside a small area, that is why you are getting the red lines, so one solution is choose a smaller fontSize, a better solution is to get rid of ListTile and build your own custom widget, since a ListTile is
A single fixed-height row that typically contains some text as well as
a leading or trailing icon.
So it should not be used if you are using bigger widgets.
This is simple example of how to create a custom widget that resembles ListTile, but is more flexible and customizable when dealing with larger items:
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(title: new Text("ListTile Example"),),
body: new ListView(
children: new List.generate(7, (int index) {
return new Container(
padding: const EdgeInsets.symmetric(
vertical: 10.0, horizontal: 20.0),
child: new Column(
children: <Widget>[
new Align (child: new Text("Centered Title $index",
style: new TextStyle(fontSize: 40.0),), //so big text
alignment: FractionalOffset.topLeft,),
new Divider(color: Colors.blue,),
new Align (child: new Text("Subtitle $index"),
alignment: FractionalOffset.topLeft,),
new Divider(color: Colors.blue,),
new Align (child: new Text("More stuff $index"),
alignment: FractionalOffset.topLeft,),
new Row(mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[ //add some actions, icons...etc
new FlatButton(onPressed: () {}, child: new Text("EDIT")),
new FlatButton(onPressed: () {},
child: new Text("DELETE",
style: new TextStyle(color: Colors.redAccent),))
],),
],
),
);
}),
)
);
}
You can change the alignment of the text by using textAlign
Use this to center the Title of a ListTile:
ListTile(title: Text('YOUR TEXT', textAlign: TextAlign.center));
Here is my example of a three-row tile:
class ThreeRowTile extends StatelessWidget {
final Widget title;
final Widget detail;
final String utility1;
final String utility1Help;
final String utility2Help;
final String utility2;
final Icon icon;
final String cell;
final String home;
final String office;
final String email;
final VoidCallback cellTapped;
final VoidCallback cellLongPressed;
final VoidCallback iconTapped;
ThreeRowTile({
this.title,
this.icon,
this.detail,
this.utility1,
this.utility1Help,
this.utility2,
this.utility2Help,
this.cellTapped,
this.home,
this.email,
this.cell,
this.office,
this.cellLongPressed,
this.iconTapped,
});
#override
Widget build(BuildContext context) {
List<Widget> buildChildren() {
List<Widget> builder = [];
if (cell.isNotEmpty && !cell.toString().contains("--")) {
builder.add(ListTile(
leading: const Icon(Icons.phone),
title: Text(
'Cell',
textScaleFactor: globals.textScaleFactor,
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
subtitle: Text(
cell.toString().length > 0 ? cell : "No Number Found",
textScaleFactor: globals.textScaleFactor,
),
onTap: cell.toString().contains("--")
? null
: () {
globals.Utility.makePhoneCall(context, cell);
},
));
}
if (office.isNotEmpty && !office.toString().contains("--")) {
builder.add(ListTile(
leading: const Icon(Icons.work),
title: Text(
'Office',
textScaleFactor: globals.textScaleFactor,
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
subtitle: Text(
office.toString().length > 0 ? office : "No Number Found",
textScaleFactor: globals.textScaleFactor,
),
onTap: office.toString().contains("--")
? null
: () {
globals.Utility.makePhoneCall(context, office);
},
));
}
if (home.isNotEmpty && !home.toString().contains("--")) {
builder.add(ListTile(
leading: const Icon(Icons.home),
title: Text(
'Home',
textScaleFactor: globals.textScaleFactor,
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
subtitle: Text(
home.toString().length > 0 ? home : "No Number Found",
textScaleFactor: globals.textScaleFactor,
),
onTap: home.toString().contains("--")
? null
: () {
globals.Utility.makePhoneCall(context, home);
},
));
}
if (email.isNotEmpty && !email.contains('No Email Address')) {
builder.add(ListTile(
leading: const Icon(Icons.email),
title: Text(
'Email',
textScaleFactor: globals.textScaleFactor,
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
subtitle: Text(
email.toString().length > 0 ? email : "No Email Found",
textScaleFactor: globals.textScaleFactor,
),
onTap: email.toString().isEmpty
? null
: () {
globals.Utility.sendEmail(context, email);
},
));
}
if (builder.isEmpty) {
builder.add(
ListTile(
leading: const Icon(Icons.info),
title: Text(
'No Contact Information Found',
textScaleFactor: globals.textScaleFactor,
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
),
);
}
return builder;
}
String _utility1 =
utility1 == null || utility1.contains("1-1-1800") ? "" : utility1;
String _utility2 =
utility2 == null || utility2.contains("1-1-1800") ? "" : utility2;
var rowCard = Container(
decoration: BoxDecoration(
border: Border(bottom: BorderSide(color: Colors.grey[300]))),
child: Container(
padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 5.0),
child: new Column(
children: <Widget>[
Row(
children: <Widget>[
Align(
child: IconButton(
icon: icon,
onPressed: iconTapped,
),
alignment: FractionalOffset.centerLeft,
),
Expanded(
child: Column(
children: <Widget>[
new Align(
child: title, //so big text
alignment: FractionalOffset.topLeft,
),
// new Divider(),
new Align(
child: detail,
alignment: FractionalOffset.topLeft,
),
// new Divider(),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Expanded(
child: Container(
margin: const EdgeInsets.all(3.0),
padding: const EdgeInsets.all(3.0),
decoration: BoxDecoration(
border: Border.all(
color: _utility1.length > 1
? Colors.grey
: Colors.transparent)),
child: Tooltip(
message:
utility1Help == null ? "" : utility1Help,
child: Text(
_utility1,
maxLines: 1,
textAlign: TextAlign.center,
textScaleFactor: globals.textScaleFactor,
),
),
),
),
Expanded(
child: Container(
margin: const EdgeInsets.all(3.0),
padding: const EdgeInsets.all(3.0),
decoration: BoxDecoration(
border: Border.all(
color: _utility2.length > 1
? Colors.grey
: Colors.transparent)),
child: Tooltip(
message: utility2 == null ? "" : utility2,
child: Text(
_utility2,
maxLines: 1,
textAlign: TextAlign.center,
textScaleFactor: globals.textScaleFactor,
),
),
),
),
],
),
],
),
),
Align(
child: IconButton(
icon: Icon(Icons.arrow_drop_down),
onPressed: () {
showModalBottomSheet<void>(
context: context,
builder: (BuildContext context) {
return Container(
child: Padding(
padding: EdgeInsets.only(bottom: 10.0),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: buildChildren()),
),
));
});
},
),
alignment: FractionalOffset.centerRight,
),
],
),
],
),
),
// color: globals.isDarkTheme ? Colors.black45 : Colors.white,
);
return (rowCard);
}
}
And it can be used like this:
ThreeRowTile(
icon: Icon(Icons.person),
title: _contacts?.items[index]?.lastName.toString().isEmpty &&
_contacts?.items[index]?.firstName.toString().isEmpty
? null
: Text(
(_contacts?.items[index]?.lastName ?? "") +
", " +
(_contacts?.items[index]?.firstName ?? ""),
textScaleFactor: globals.textScaleFactor,
),
detail: Text(
_contacts?.items[index]?.lastActivity,
textScaleFactor: globals.textScaleFactor,
),
utility1: _contacts?.items[index]?.dateCreated,
utility1Help: 'Date Created',
utility2: _contacts?.items[index]?.dateModified,
utility2Help: "Date Modified",
cell: _contacts?.items[index]?.cell,
home: _contacts?.items[index]?.home,
office: _contacts?.items[index]?.office,
email: _contacts?.items[index]?.email,
cellTapped: () {
globals.contactID = _contacts?.items[index]?.contactID;
Navigator.of(context).pushNamed("/contact_details").then((value) {
if (globals.infoChanged) {
_getData("", false).then((newitems) {
setState(() {
_contacts = newitems;
});
});
}
});
},
);