How to buid Card? - dart

I'm new on Flutter and I'm now working on my first project, then in one of my page I'm building form in order to collect informations, so I created two Card but went I'm trying adding some TextField in the second one, all the the content disappear.
Please Help :(
import 'package:flutter/material.dart';
import 'customInputField.dart';
class DropDown extends StatefulWidget {
#override
_DropDownState createState() => _DropDownState();
}
class _DropDownState extends State<DropDown> {
// Here we're going to define the LIST
List _cities = ["Douala","Yaoundé"];
List _weight = ["0-1","1-3","3-5"];
List _dimensions = ["A5","A4","A3","A2"];
// End
var resultsList = new List.filled(3, "");
#override
void initState(){
// Here we're going to set the initial values
resultsList[0] = "Douala";
resultsList[1] = "0-1";
resultsList[2] = "A5";
return super.initState();
}
// Here we're going to create the method which will build and update the dropDown menu
_fieldDropDown(List theList, int resultPosition, var dbField) {
return new FormField(
builder: (FormFieldState state) {
return InputDecorator(
decoration: InputDecoration(),
child: new DropdownButtonHideUnderline(
child: new DropdownButton(
value: this.resultsList[resultPosition],
isDense: true,
onChanged: (dynamic newValue) {
setState(() {
this.resultsList[resultPosition] = newValue;
state.didChange(newValue);
print(
'The List result = ' + this.resultsList[resultPosition]);
//write newValue to a database field, which can be used in the override init to set the field originally
});
},
// Comment to remove Error
items: theList.map((dynamic value) {
return new DropdownMenuItem(
value: value,
child: new Text(value),
);
}).toList(),
),
),
);
},
);
}
#override
Widget build(BuildContext context) {
return new Scaffold(
body: Container(
decoration: new BoxDecoration(
color: Color.fromRGBO(0x12, 0x34, 0x55, 0.9),
),
child: new Form(
//key: _formKey,
autovalidate: true,
child: new ListView(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
children: [
Card(
child: Padding(
padding: EdgeInsets.fromLTRB(8, 20, 8, 10),
child: Column(
children: <Widget>[
Text('Informations sur le colis',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18, ),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text('Pli'),
new Radio(
value: 0,
groupValue: null,
onChanged: null
),
new Text('Colis'),
new Radio(
value: 1,
groupValue: null,
onChanged: null
)
]
),
//create some fields, hand in the list
Row(
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width*.3,
child: Text('Départ:', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 15),
),
),
Container(
width: MediaQuery.of(context).size.width*.5,
child: _fieldDropDown(_cities, 0, 'colorDBfield')
)
],
),
Row(
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width*.3,
child: Text('Poids:', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 15),
),
),
Container(
width: MediaQuery.of(context).size.width*.5,
child: _fieldDropDown(_weight, 1, 'dogDBfield'),
)
],
),
Row(
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width*.3,
child: Text('Dimensions:', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 15),
),
),
Container(
width: MediaQuery.of(context).size.width*.5,
child: _fieldDropDown(_dimensions, 2, 'peopleDBfield'),
)
],
),
],
)),
),
Card(
child: Padding(
padding: EdgeInsets.fromLTRB(8, 20, 8, 10),
child: Column(
children: <Widget>[
Text('Informations sur le destinataire',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18, ),
),
Row(
children: <Widget>[
new TextField(
decoration: InputDecoration(
border: OutlineInputBorder()
),
),
],
)
],
),
),
)
],
)
),
),
);
}
}

Related

Add more fields after a listview.builder

I have a statefull layout with a listview.builder inside the builder I have a couple of expansionTile widgets
How do I show the entire list on the screen and add some textform widget below the list?
I have added a Expanded widget around the list to allow for more widgets below it but the list gets cut at a certain point where I want to show the entire list and then the text widgets after
class ContactUsScreen extends StatefulWidget {
const ContactUsScreen({Key? key}) : super(key: key);
static const String contactRouteName = "/contactScreen";
#override
State<ContactUsScreen> createState() => _ContactUsScreenState();
}
class _ContactUsScreenState extends State<ContactUsScreen> {
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text("Contact Us"),
centerTitle: true,
),
body: CustomScrollView(
slivers: [
SliverFillRemaining(
hasScrollBody: true,
child: Column(
children: [
Expanded(
child: ListView.builder(
itemCount: salesList.length,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Card(
elevation: 5,
child: ExpansionTile(
key: PageStorageKey<ContactPeople>(salesList[index]),
controlAffinity: ListTileControlAffinity.leading,
childrenPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20),
expandedCrossAxisAlignment: CrossAxisAlignment.end,
maintainState: true,
title: Text(
salesList[index].regionDescription,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 18,
),
),
children: //[Text("Test")],
salesList[index].people!.map(
(peopleRecord) {
return ExpansionTile(
expandedCrossAxisAlignment: CrossAxisAlignment.start,
key: PageStorageKey<ContactUsScreen>(peopleRecord),
title: Align(
alignment: Alignment.topLeft,
child: Row(
children: [
ClipOval(
child: Image.asset(
"assets/images/people/${peopleRecord.avatarImage}",
fit: BoxFit.cover,
width: 60,
height: 60,
),
),
SizedBox(
width: 10,
),
Text(
peopleRecord.name,
style: const TextStyle(fontSize: 15),
),
],
),
),
children: [
Text(
peopleRecord.title,
style: const TextStyle(fontWeight: FontWeight.bold),
),
Text(peopleRecord.cellPhoneNumber),
Text(
peopleRecord.emailAddress,
),
const SizedBox(
height: 5,
),
],
);
},
).toList(),
),
),
);
}),
),
SizedBox(height: 15,),
Text("Contact us directly",
style: TextStyle(fontWeight: FontWeight.w700,
fontSize: 20,
color: Colors.black),),
Form(
key: formKey,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 15),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
TextFormField(controller: fullNameController,
keyboardType: TextInputType.text,
decoration: InputDecoration(labelText: "Full Name",
hintText: "Full Name",
),
validator: (inputFieldFullName)
{
if(inputFieldFullName!.isEmpty)
{
return "Please enter your Full Name";
}
else
{
return null;
}
},
),
TextFormField(controller: contactNumberController,
keyboardType: TextInputType.number,
decoration: InputDecoration(labelText: "Contact Number",
hintText: "Contact Number",
),
validator: (inputFieldContactNumber)
{
if(inputFieldContactNumber!.isEmpty)
{
return "Please enter your contact number";
}
else
{
return null;
}
},
),
SizedBox(height: 5,),
ElevatedButton(
onPressed: () {
if(formKey.currentState!.validate())
{
//Send the email
}
else
{
const SnackBar snackBar = SnackBar(duration: Duration(seconds: 2), content: Text("Please correct the errors"));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
},
child: Text("Submit"),
),
SizedBox(height: 20,),
],
),
),
),
//getContactForm(context, formKey),
],
),
)
],
)
),
);
}
}
The end result should be that we display the entire list of parent expansion tile, and then only after the textform fields
Regards
You have to use this structure:
CustomScrollView(
slivers: <Widget>[
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return ** first listview **
},
childCount: top.length,
),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return ** second listview **
},
childCount: bottom.length,
),
),
],
),

How to change from Stateless Widget to Stateful Widget?

I have an app screen that uses Checkboxes and a Drop down Menu. However, I have realised I'd coded it inside a StatelessWidget so I am unable to change the state when an option is selected. How do I get this working so that when a Checkbox is selected then it will display as being "checked" rather than empty?
I have tried pasting in my code into a Stateful Widget, however keep running into errors, as I am not totally sure on which parts should go where.
import 'package:carve_brace_app/model/activity.dart';
import 'package:flutter/material.dart';
class DetailPage extends StatelessWidget {
final Activity activity;
DetailPage({Key key, this.activity}) : super(key: key);
#override
Widget build(BuildContext context) {
final levelIndicator = Container(
child: Container(
child: LinearProgressIndicator(
backgroundColor: Color.fromRGBO(209, 224, 224, 0.2),
value: 2.0,
valueColor: AlwaysStoppedAnimation(Colors.green)),
),
);
final topContentText = Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(height: 120.0),
Container(
width: 90.0,
child: new Divider(color: Colors.green),
),
SizedBox(height: 10.0),
Text(
activity.activityName,
style: TextStyle(color: Colors.white, fontSize: 45.0),
),
SizedBox(height: 30.0),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Expanded(
flex: 6,
child: Padding(
padding: EdgeInsets.only(left: 10.0),
child: Text(
"Last Run: 3-2-19\n"+
"Last Avg Strain: 34%\n"+
"Last Run Time: 00:45:23",
style: TextStyle(color: Colors.white),
))),
// Expanded(flex: 1, child: newRow)
],
),
],
);
final topContent = Stack(
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height * 0.45,
padding: EdgeInsets.all(40.0),
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [
Color.fromRGBO(33, 147, 176, 100),
Color.fromRGBO(109, 213, 237, 100)
],
),
),
child: Center(
child: topContentText,
),
),
Positioned(
left: 235.0,
top: 180.0,
child: InkWell(
onTap: () {
Navigator.pop(context);
},
child: new CircleAvatar(
radius: 80.0,
backgroundImage: NetworkImage(activity.icon),
backgroundColor: Colors.white,
),
),
),
Positioned(
left: 8.0,
top: 60.0,
child: InkWell(
onTap: () {
Navigator.pop(context);
},
child: Icon(Icons.arrow_back, color: Colors.white),
),
)
],
);
final bottomContentText = Text(
"Config:",
style: TextStyle(fontSize: 18.0),
);
final mappedCheckbox = CheckboxListTile(
title: Text("Mapped"),
value: false,
onChanged: (newValue) { },
controlAffinity: ListTileControlAffinity.leading, // <-- leading Checkbox
);
final rtCheckBox = CheckboxListTile(
title: Text("Real-time Tracking"),
value: false,
onChanged: (newValue) { },
controlAffinity: ListTileControlAffinity.leading, // <-- leading Checkbox
);
final descriptionText = Text(
"Description:",
style: TextStyle(fontSize: 12.0),
);
final description = TextFormField(
decoration: InputDecoration(
hintText: 'Enter an activity description',
),
);
final scheduledFor = Text(
"Scheduled for:",
style: TextStyle(fontSize: 12.0),
);
final dropdown = new DropdownButton<String>(
items: <String>['Now (Default)', 'B', 'C', 'D'].map((String value) {
return new DropdownMenuItem<String>(
value: value,
child: new Text(value),
);
}).toList(),
hint: Text("Now (Default)"),
onChanged: (_) {},
);
final readButton = Container(
padding: EdgeInsets.symmetric(vertical: 16.0),
width: 170,//MediaQuery.of(context).size.width,
child: RaisedButton(
onPressed: () => {},
color: Colors.lightBlue,
child:
Text("Start", style: TextStyle(color: Colors.white, fontSize: 20)),
));
final bottomContent = Container(
width: MediaQuery.of(context).size.width,
padding: EdgeInsets.all(40.0),
child: Center(
child: Column(
children: <Widget>[bottomContentText, mappedCheckbox, rtCheckBox, descriptionText, description, Text("\n"), scheduledFor, dropdown, readButton],
),
),
);
return Scaffold(
body: Column(
children: <Widget>[topContent, bottomContent],
),
);
}
}
Hover on to the StatelessWidget class and use
Android Studio:
Mac: option + enter
Windows: alt + enter
Visual Studio Code:
Mac: cmd + .
Windows: ctrl + .
Output (Your solution):
Here is the working code.
class DetailPage extends StatefulWidget {
final Activity activity;
DetailPage({Key key, this.activity}) : super(key: key);
#override
_DetailPageState createState() => _DetailPageState();
}
class _DetailPageState extends State<DetailPage> {
bool _tracking = false, _mapped = false; // you need this
String _schedule;
#override
Widget build(BuildContext context) {
final levelIndicator = Container(
child: Container(
child: LinearProgressIndicator(backgroundColor: Color.fromRGBO(209, 224, 224, 0.2), value: 2.0, valueColor: AlwaysStoppedAnimation(Colors.green)),
),
);
final topContentText = Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(height: 120.0),
Container(
width: 90.0,
child: Divider(color: Colors.green),
),
SizedBox(height: 10.0),
Text(
widget.activity.activityName,
style: TextStyle(color: Colors.white, fontSize: 45.0),
),
SizedBox(height: 30.0),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Expanded(
flex: 6,
child: Padding(
padding: EdgeInsets.only(left: 10.0),
child: Text(
"Last Run: 3-2-19\n" + "Last Avg Strain: 34%\n" + "Last Run Time: 00:45:23",
style: TextStyle(color: Colors.white),
))),
// Expanded(flex: 1, child: newRow)
],
),
],
);
final topContent = Stack(
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height * 0.45,
padding: EdgeInsets.all(40.0),
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [Color.fromRGBO(33, 147, 176, 100), Color.fromRGBO(109, 213, 237, 100)],
),
),
child: Center(
child: topContentText,
),
),
Positioned(
left: 235.0,
top: 180.0,
child: InkWell(
onTap: () {
Navigator.pop(context);
},
child: CircleAvatar(
radius: 80.0,
backgroundColor: Colors.white,
),
),
),
Positioned(
left: 8.0,
top: 60.0,
child: InkWell(
onTap: () {
Navigator.pop(context);
},
child: Icon(Icons.arrow_back, color: Colors.white),
),
)
],
);
final bottomContentText = Text(
"Config:",
style: TextStyle(fontSize: 18.0),
);
final mappedCheckbox = CheckboxListTile(
title: Text("Mapped"),
value: _mapped,
onChanged: (newValue) => setState(() => _mapped = newValue),
controlAffinity: ListTileControlAffinity.leading, // <-- leading Checkbox
);
final rtCheckBox = CheckboxListTile(
title: Text("Real-time Tracking"),
value: _tracking,
onChanged: (newValue) => setState(() => _tracking = newValue),
controlAffinity: ListTileControlAffinity.leading, // <-- leading Checkbox
);
final descriptionText = Text(
"Description:",
style: TextStyle(fontSize: 12.0),
);
final description = TextFormField(
decoration: InputDecoration(
hintText: 'Enter an activity description',
),
);
final scheduledFor = Text(
"Scheduled for:",
style: TextStyle(fontSize: 12.0),
);
final dropdown = DropdownButton<String>(
value: _schedule,
items: <String>['Now (Default)', 'B', 'C', 'D'].map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
hint: Text("Now (Default)"),
onChanged: (newValue) {
setState(() {
_schedule = newValue;
});
},
);
final readButton = Container(
padding: EdgeInsets.symmetric(vertical: 16.0),
width: 170, //MediaQuery.of(context).size.width,
child: RaisedButton(
onPressed: () => {},
color: Colors.lightBlue,
child: Text("Start", style: TextStyle(color: Colors.white, fontSize: 20)),
));
final bottomContent = Container(
width: MediaQuery.of(context).size.width,
padding: EdgeInsets.all(40.0),
child: Center(
child: Column(
children: <Widget>[bottomContentText, mappedCheckbox, rtCheckBox, descriptionText, description, Text("\n"), scheduledFor, dropdown, readButton],
),
),
);
return Scaffold(
body: Column(
children: <Widget>[topContent, bottomContent],
),
);
}
}
For VSCode (Visual Studio Code) use ctrl + '.' keys while the cursor on the stateless widget to convert it to stateful widget.
You could use intellij's or vscode shortcut by hitting alt + enter or selecting the bulb icon while your cursor is on the name of the stateless widget then select convert to stateful widget
For Android Studio in Mac:
1.Place the marker on the Stateless widget name
2.Hit Alt+Enter
3.Select Convert to Stateful widget
4.Configure your Stateful widget based on your requirements
Adding a solution for Android Studio since I didn't find one here.
Place the marker on the Stateless widget name:
Hit Alt+Enter
Select Convert to Stateful widget
Configure your Stateful widget based on your requirements

Flutter - Implementing a listView search feature

I've been trying to implement a search bar into my app for bringing selected listView items to the top of a list. The list contains quite a few items, around approximately 1700 so the addition of a search bar is essential. I'd like the listView search box to appear from a search icon on the right hand side of the top appBar. Below is a picture of the current view for reference.
When you click the search iconButton a search field should replace the title in the appBar. It's going to be evident to the user that this is for the crypto listView as I'll add a hint in the search view identifying this.
I'm not including all my code as this would be cumbersome for a stack question, but below is my home_page.dart file, where as the rest of my classes for the bottom crypto listView can be found at this GitHub repo.
This is what my 'home_page.dart` looks like;
import 'package:cryptick/cryptoData/crypto_data.dart';
import 'package:cryptick/cryptoData/trending_data.dart';
import 'package:cryptick/modules/crypto_presenter.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'background.dart';
//FOLLOWING DART CODE COPYRIGHT OF 2017 - 2018 SQUARED SOFTWARE LONDON
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => new _HomePageState();
}
class ServerStatusScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
iconTheme: new IconThemeData(color: Colors.white),
centerTitle: true,
backgroundColor: Colors.black,
title: new Text(
'API Server Status',
textAlign: TextAlign.center,
style: new TextStyle(
color: Colors.white, fontSize: 27.5, fontFamily: 'Kanit'),
),
),
body: new Center(
child: new Column(
children: [
new Divider(color: Colors.white),
new Text(
'News Feed: ',
textAlign: TextAlign.center,
style: new TextStyle(
color: Colors.black,
fontSize: 27.5,
fontFamily: 'Kanit',
),
),
new Divider(),
new Text(
'Crypto Feed: ',
textAlign: TextAlign.center,
style: new TextStyle(
color: Colors.black,
fontSize: 27.5,
fontFamily: 'Kanit',
),
),
new Divider(),
new Wrap(
alignment: WrapAlignment.center,
children: <Widget>[
new Chip(
backgroundColor: Colors.black,
label: new Text(
'© 2017-2018 Squared Software',
style: new TextStyle(
fontSize: 15.0,
fontFamily: 'Poppins',
color: Colors.white,
),
),
),
],
),
],
),
),
);
}
}
class MoreInfoScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
final ThemeData themeData = Theme.of(context);
final TextStyle aboutTextStyle = themeData.textTheme.body2;
final TextStyle linkStyle =
themeData.textTheme.body2.copyWith(color: themeData.accentColor);
return new Scaffold(
appBar: new AppBar(
iconTheme: new IconThemeData(color: Colors.white),
centerTitle: true,
backgroundColor: Colors.black,
title: new Text(
'More Info',
textAlign: TextAlign.center,
style: new TextStyle(
color: Colors.white, fontSize: 27.5, fontFamily: 'Kanit'),
),
),
body: new Center(
child: new Column(
children: [
new Divider(color: Colors.white),
new ListTile(
title: new Text('Squared Software',
style: new TextStyle(
fontWeight: FontWeight.w500,
fontFamily: 'Poppins',
)
),
leading: new CircleAvatar(
radius: 30.0,
backgroundImage: new AssetImage(
'images/sqinterlock.png'
)
)
),
new Divider(),
new Text('Where do we get our information?',
style: new TextStyle(
color: Colors.black,
fontFamily: 'Poppins',
fontSize: 16.5,
)
),
new Divider(color: Colors.white),
new Text(
"News Feed: bit.ly/2MFpzHX",
style: new TextStyle(
fontFamily: 'Poppins',
fontSize: 16.5,
),
),
new Divider(color: Colors.white),
new Text(
"Crypto Feed: bit.ly/2iIdJht",
style: new TextStyle(
fontFamily: 'Poppins',
fontSize: 16.5,
),
),
new Divider(color: Colors.white),
new Wrap(
alignment: WrapAlignment.center,
children: <Widget>[
new Chip(
backgroundColor: Colors.black,
label: new Text(
'© 2017-2018 Squared Software',
style: new TextStyle(
fontSize: 15.0,
fontFamily: 'Poppins',
color: Colors.white,
),
),
),
],
),
],
),
),
);
}
}
class _HomePageState extends State<HomePage> implements CryptoListViewContract {
CryptoListPresenter _presenter;
List<Crypto> _currencies;
bool _isLoading;
final List<MaterialColor> _colors = [Colors.blue, Colors.indigo, Colors.red];
_HomePageState() {
_presenter = new CryptoListPresenter(this);
}
#override
void onLoadTrendingComplete(Trending trending) {
// TODO:
articlesMap = trending.articles;
for (Map articleMap in articlesMap) {
articles.add(Articles.fromMap(articleMap));
}
if (mounted) setState(() {});
}
#override
void onLoadTrendingError() {
// TODO:
}
List articlesMap = [];
List<Articles> articles = [];
#override
void initState() {
super.initState();
_isLoading = true;
_presenter.loadCurrencies();
_presenter.loadTrending();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(
"Cryp - Tick Exchange",
style: new TextStyle(
color: Colors.white,
fontFamily: 'Poppins',
fontSize: 22.5,
),
),
iconTheme: new IconThemeData(color: Colors.white),
backgroundColor: const Color(0xFF273A48),
elevation: 0.0,
centerTitle: true,
),
drawer: new Drawer(
child: new ListView(padding: EdgeInsets.zero, children: <Widget>[
new DrawerHeader(
child: new CircleAvatar(
child: new Image.asset('images/ctavatar.png'),
),
decoration: new BoxDecoration(
color: Colors.black,
),
),
new MaterialButton(
child: new Text(
'Server Status',
textAlign: TextAlign.center,
style: new TextStyle(fontSize: 27.5, fontFamily: 'Kanit'),
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ServerStatusScreen()),
);
}),
new Divider(),
new MaterialButton(
child: new Text(
'More Info',
textAlign: TextAlign.center,
style: new TextStyle(fontSize: 27.5, fontFamily: 'Kanit'),
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => MoreInfoScreen()),
);
}),
new Divider(),
new Wrap(
alignment: WrapAlignment.center,
children: <Widget>[
new Chip(
backgroundColor: Colors.black,
label: new Text(
'v0.0.1',
style: new TextStyle(
fontSize: 15.0,
fontFamily: 'Poppins',
color: Colors.white,
),
),
),
],
),
]),
),
body: _isLoading
? new Center(child: new CupertinoActivityIndicator(radius: 15.0))
: _allWidget());
}
Widget _allWidget() {
final _width = MediaQuery.of(context).size.width;
final _height = MediaQuery.of(context).size.height;
//CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED
final headerList = new ListView.builder(
itemBuilder: (context, index) {
EdgeInsets padding = index == 0
? const EdgeInsets.only(
left: 20.0, right: 10.0, top: 4.0, bottom: 30.0)
: const EdgeInsets.only(
left: 10.0, right: 10.0, top: 4.0, bottom: 30.0);
return new Padding(
padding: padding,
child: new InkWell(
onTap: () {
print('#url');
},
child: new Container(
decoration: new BoxDecoration(
borderRadius: new BorderRadius.circular(10.0),
color: const Color(0xFF273A48),
boxShadow: [
new BoxShadow(
color: Colors.black.withAlpha(70),
offset: const Offset(3.0, 10.0),
blurRadius: 15.0)
],
image: new DecorationImage(
image: new NetworkImage(articles[index].urlToImage),
fit: BoxFit.fitHeight,
),
),
height: 200.0,
width: 275.0,
child: new Stack(
children: <Widget>[
new Align(
alignment: Alignment.bottomCenter,
child: new Container(
padding: new EdgeInsets.only(left: 10.0),
decoration: new BoxDecoration(
color: const Color(0xFF273A48),
borderRadius: new BorderRadius.only(
bottomLeft: new Radius.circular(10.0),
bottomRight: new Radius.circular(10.0)),
),
height: 50.0,
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Expanded(child: new Text(
articles[index].title,
overflow: TextOverflow.ellipsis,
maxLines: 2,
style: new TextStyle(
color: Colors.white,
fontFamily: 'Poppins',
),
),
),
],
)
),
)
],
),
),
),
);
},
scrollDirection: Axis.horizontal,
itemCount: articles.length,
);
final body = new Scaffold(
backgroundColor: Colors.transparent,
body: new Container(
child: new Stack(
children: <Widget>[
new Padding(
padding: new EdgeInsets.only(top: 10.0),
child: new Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new Align(
alignment: Alignment.centerLeft,
child: new Padding(
padding: new EdgeInsets.only(
left: 10.0,
),
child: new Text(
"Trending News",
style: new TextStyle(
letterSpacing: 0.8,
fontFamily: 'Kanit',
fontSize: 17.5,
color: Colors.white,
),
)),
),
new Container(
height: 300.0, width: _width, child: headerList),
new Expanded(child: ListView.builder(
itemBuilder: (BuildContext context, int index) {
final int i = index;
final Crypto currency = _currencies[i];
final MaterialColor color = _colors[i % _colors.length];
return new ListTile(
title: new Column(
children: <Widget>[
new Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Container(
height: 72.0,
width: 72.0,
decoration: new BoxDecoration(
color: Colors.white,
boxShadow: [
new BoxShadow(
color: Colors.black.withAlpha(80),
offset: const Offset(2.0, 2.0),
blurRadius: 15.0)
],
borderRadius: new BorderRadius.all(
new Radius.circular(35.0)),
image: new DecorationImage(
image: new ExactAssetImage(
"cryptoiconsBlack/" +
currency.symbol.toLowerCase() +
"#2x.png",
),
fit: BoxFit.cover,
)),
),
new SizedBox(
width: 8.0,
),
new Expanded(
child: new Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Text(
currency.name,
style: new TextStyle(
fontSize: 15.0,
fontFamily: 'Poppins',
color: Colors.black87,
fontWeight: FontWeight.bold),
),
_getSubtitleText(currency.price_usd,
currency.percent_change_1h),
],
)),
],
),
new Divider(),
],
),
);
}))
],
),
),
],
),
),
);
return new Container(
decoration: new BoxDecoration(
color: const Color(0xFF273A48),
),
child: new Stack(
children: <Widget>[
new CustomPaint(
size: new Size(_width, _height),
painter: new Background(),
),
body,
],
),
);
}
// CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED CRYPTO FEED
Widget _getSubtitleText(String priceUSD, String percentageChange) {
TextSpan priceTextWidget = new TextSpan(
text: "\$$priceUSD\n",
style: new TextStyle(
color: Colors.black,
fontSize: 14.0,
));
String percentageChangeText = "1 hour: $percentageChange%";
TextSpan percentageChangeTextWidget;
if (double.parse(percentageChange) > 0) {
percentageChangeTextWidget = new TextSpan(
text: percentageChangeText,
style: new TextStyle(
color: Colors.green,
fontFamily: 'PoppinsMediumItalic',
));
} else {
percentageChangeTextWidget = new TextSpan(
text: percentageChangeText,
style: new TextStyle(
color: Colors.red,
fontFamily: 'PoppinsMediumItalic',
));
}
return new RichText(
text: new TextSpan(
children: [priceTextWidget, percentageChangeTextWidget]));
}
//Works with cryptoListViewContract implimentation in _MyHomePageState
#override
void onLoadCryptoComplete(List<Crypto> items) {
// TODO: implement onLoadCryptoComplete
setState(() {
_currencies = items;
_isLoading = false;
});
}
#override
void onLoadCryptoError() {
// TODO: implement onLoadCryptoError
}
}
Thanks for the help, Jake
There are probably many ways to implement this based on the resulting experience you want. A simple solution is to create activeSearch state that toggles a 'search app bar' and a 'normal app bar'
Here's the normal app bar:
return AppBar(
title: Text("My App"),
actions: <Widget>[
IconButton(
icon: Icon(Icons.search),
onPressed: () => setState(() => activeSearch = true),
),
],
);
And here's the search app bar:
return AppBar(
leading: Icon(Icons.search),
title: TextField(
decoration: InputDecoration(
hintText: "here's a hint",
),
),
actions: <Widget>[
IconButton(
icon: Icon(Icons.close),
onPressed: () => setState(() => activeSearch = false),
)
],
);
Note: if you don't want to have a leading icon when search is active you may want to disable the default behavior for a drawer and back button icon with:
automaticallyImplyLeading: false
Full example:
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
bool activeSearch;
#override
void initState() {
super.initState();
activeSearch = false;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: _appBar(),
drawer: _drawer(),
);
}
PreferredSizeWidget _appBar() {
if (activeSearch) {
return AppBar(
leading: Icon(Icons.search),
title: TextField(
decoration: InputDecoration(
hintText: "here's a hint",
),
),
actions: <Widget>[
IconButton(
icon: Icon(Icons.close),
onPressed: () => setState(() => activeSearch = false),
)
],
);
} else {
return AppBar(
title: Text("My App"),
actions: <Widget>[
IconButton(
icon: Icon(Icons.search),
onPressed: () => setState(() => activeSearch = true),
),
],
);
}
}
Widget _drawer() {
return Container();
}
}
UPDATE: Here's a hint at handling results
return AppBar(
...
title: TextField(
onChanged: _search,
),
);
And what _search could look like:
List<MyResultObject> _results;
void _search(String queryString) {
// do some searching and sorting
// then call setState() with the results
// and then in your ListView you can read from results
// (handle empty, default case as well in view)
setState(() {
_results = ...
});
}
List<Widget> _resultWidgets() {
if (_results.isEmpty) return _defaultWidgets();
_results.map((r) => _buildRowWidget(s)).toList();
}
Can u refer a simple search view in this answer. In that example, as the user types, the list will get filtered.

Card overlapping raised button in flutter

friends, I am thinking to make this type of view but I can't able to set the button overlapping like the given image I am using stack widget which is containing the text fields and the buttons as given image please check and help me out I also tried to use the center widgets as well but the view is coming as required in it also i had used the positioned widget but its getting button bottom of the screen like this but i need as the above image
MyLayoutDesign
class MyApp extends StatefulWidget {
#override
State<StatefulWidget> createState() {
MyAppState myAppState() => new MyAppState();
return myAppState();
}
}
class MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return new MaterialApp(home: new Scaffold(body: new Builder(
builder: (BuildContext context) {
return new Stack(
children: <Widget>[
new Image.asset(
'assets/images/bg.png',
fit: BoxFit.cover,
),
new Center(
child: new Container(
child: new Card(
color: Colors.white,
elevation: 6.0,
margin: EdgeInsets.only(right: 15.0, left: 15.0),
child: new Wrap(
children: <Widget>[
Center(
child: new Container(
margin: EdgeInsets.only(top: 20.0),
child: new Text(
'Login',
style: TextStyle(
fontSize: 25.0, color: secondarycolor),
),
),
),
new ListTile(
leading: const Icon(Icons.person),
title: new TextFormField(
decoration: new InputDecoration(
hintText: 'Please enter email',
labelText: 'Enter Your Email address',
),
keyboardType: TextInputType.emailAddress,
),
),
new ListTile(
leading: const Icon(Icons.lock),
title: new TextFormField(
decoration: new InputDecoration(
hintText: 'Please enter password',
labelText: 'Enter Your Password',
),
keyboardType: TextInputType.emailAddress,
obscureText: true,
),
),
Container(
margin: EdgeInsets.only(top: 10.0, bottom: 15.0),
child: Center(
child: Text(
"FORGOT PASSWORD",
style: TextStyle(
decoration: TextDecoration.underline,
color: Colors.black,
fontSize: 16.0),
),
),
),
Center(
child: Container(
margin: EdgeInsets.only(bottom: 40.0, top: 10.0),
child: Text.rich(
TextSpan(
children: const <TextSpan>[
TextSpan(
text: 'NEW USER ? ',
style: TextStyle(
fontSize: 16.0, color: Colors.black)),
TextSpan(
text: 'REGISTER',
style: TextStyle(
fontSize: 16.0,
decoration: TextDecoration.underline,
color: Colors.black)),
],
),
),
),
),
],
),
),
),
),
new RaisedButton(
onPressed: () {
print('Login Pressed');
},
color: primarycolor,
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0)),
child: new Text('Login',
style: new TextStyle(
color: Colors.white,
fontSize: 16.0,
fontWeight: FontWeight.bold)),
),
],
);
},
)));
}
}
this is just one the many ways you can achieve the expected result.
In this case, i assume you know the height of the background.
Again, there are many ways to achieve what you want. There is nothing wrong with your code, you just have to get an understanding of how 'things' work in Flutter
Widget demo = Stack(
children: <Widget>[
//First thing in the stack is the background
//For the backgroud i create a column
Column(
children: <Widget>[
//first element in the column is the white background (the Image.asset in your case)
DecoratedBox(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20.0),
color: Colors.white
),
child: Container(
width: 300.0,
height: 400.0,
)
),
//second item in the column is a transparent space of 20
Container(
height: 20.0
)
],
),
//for the button i create another column
Column(
children:<Widget>[
//first element in column is the transparent offset
Container(
height: 380.0
),
Center(
child: FlatButton(
color: Colors.red,
child: Text("Press Me"),
onPressed: () {},
),
)
]
)
],
);
Here you can find your solution code below.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
State<StatefulWidget> createState() {
MyAppState myAppState() => new MyAppState();
return myAppState();
}
}
class MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return new MaterialApp(home: new Scaffold(body: new Builder(
builder: (BuildContext context) {
return new Stack(
children: <Widget>[
new Image.asset(
'assets/images/bg.jpeg',
fit: BoxFit.fitWidth,
),
new Center(
child: new Container(
height: 370.0,
child: Container(
height:250.0,
child: new Card(
color: Colors.white,
elevation: 6.0,
margin: EdgeInsets.only(right: 15.0, left: 15.0),
child: new Wrap(
children: <Widget>[
Center(
child: new Container(
margin: EdgeInsets.only(top: 20.0),
child: new Text(
'Login',
style: TextStyle(
fontSize: 25.0, color: Colors.red),
),
),
),
new ListTile(
leading: const Icon(Icons.person),
title: new TextFormField(
decoration: new InputDecoration(
hintText: 'Please enter email',
labelText: 'Enter Your Email address',
),
keyboardType: TextInputType.emailAddress,
),
),
new ListTile(
leading: const Icon(Icons.lock),
title: new TextFormField(
decoration: new InputDecoration(
hintText: 'Please enter password',
labelText: 'Enter Your Password',
),
keyboardType: TextInputType.emailAddress,
obscureText: true,
),
),
Container(
margin: EdgeInsets.only(top: 10.0, bottom: 15.0),
child: Center(
child: Text(
"FORGOT PASSWORD",
style: TextStyle(
decoration: TextDecoration.underline,
color: Colors.black,
fontSize: 16.0),
),
),
),
Center(
child: Container(
margin: EdgeInsets.only(bottom: 40.0, top: 10.0),
child: Text.rich(
TextSpan(
children: const <TextSpan>[
TextSpan(
text: 'NEW USER ? ',
style: TextStyle(
fontSize: 16.0, color: Colors.black)),
TextSpan(
text: 'REGISTER',
style: TextStyle(
fontSize: 16.0,
decoration: TextDecoration.underline,
color: Colors.black)),
],
),
),
),
),
Padding(padding: EdgeInsets.only(left: 120.0)),
],
),
),
),
padding: EdgeInsets.only(bottom: 30),
),
),
new Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(padding: EdgeInsets.only(top: 310.0)),
RaisedButton(
onPressed: () {
print('Login Pressed');
},
color: Colors.green,
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0)),
child: new Text('Login',
style: new TextStyle(
color: Colors.white,
fontSize: 16.0,
fontWeight: FontWeight.bold)),
),
],
)
)
],
);
},
)));
}
}
#ibhavikmakwana propsed a better solution to your question. The other answers all depend on the size of the background and are not screen independent. They both create an invisible object above the button (either by adding a Container or a Padding).
I was having that question too and did not find your question first.
His simple solution is to wrap the button in a Positioned widget and give it a bottom of 0 or < 0.
Positioned(
child: FlatButton(
color: Colors.red,
child: Text("Press Me"),
onPressed: () {},
),
right: 0,
left: 0,
bottom: 0,
)
I found out that the "bottom" attribute set to 0 will offset the widget by exactly 0.5*height of the widget.

Unable to display on column 2

I have the below display and data is coming from JSON. But, the problem is data is showing only on one column all the time. How do I make sure it is like left to right till all the data is filled?
this is the code. As you can see that I am creating a card and having the rest of the details inside the card and then in another code I am looping till I have all the JSON details.
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:elegal_dart/models/items.dart';
import 'package:elegal_dart/services/api.dart';
class LostPage extends StatefulWidget {
#override
_LostPage createState() => new _LostPage();
}
class _LostPage extends State<LostPage> {
List<Item> _items = [];
#override
void initState() {
super.initState();
_loadLostItems();
}
_loadLostItems() async {
String fileData =
await DefaultAssetBundle.of(context).loadString("assets/items.json");
setState(() {
_items = ItemApi.allItemsFromJson(fileData);
});
print(_items.toString());
}
Widget _buildLostItems(BuildContext context, int index) {
Item item = _items[index];
return GridView.count(
shrinkWrap: true,
crossAxisCount: 2,
children: <Widget>[
Card(
child: Column(
// mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: Stack(
fit: StackFit.expand,
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height / 4,
width: MediaQuery.of(context).size.height / 2.5,
child: DecoratedBox(
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(
item.item_DispPic),
fit: BoxFit.cover),
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Align(
alignment: FractionalOffset.topLeft,
child: CircleAvatar(
backgroundColor: Colors.redAccent,
radius: 15.0,
child: Text(
"NEW",
textScaleFactor: 0.5,
),
),
),
),
Align(
alignment: FractionalOffset.topRight,
child: Container(
color: Colors.blueAccent,
height: 35.0,
width: 35.0,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.account_circle),
Text(
"1P",
textScaleFactor: 0.5,
),
],
),
),
),
),
],
),
),
Center(
child: Container(
padding: const EdgeInsets.all(8.0),
alignment: FractionalOffset.bottomCenter,
child: Text(
"MEGADISH",
style: TextStyle(
fontWeight: FontWeight.w700,
),
),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
FlatButton(
child: Text(
"Add To Cart",
style: TextStyle(color: Colors.grey[500]),
),
onPressed: () => null,
),
Text(
"\$5",
style: TextStyle(color: Colors.grey[500]),
)
],
)
],
),
),
],
);
}
Widget _getAppTitleWidget() {
return new Text(
'Lost Items',
style: new TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 32.0,
),
);
}
Widget _buildBody() {
return new Container(
margin: const EdgeInsets.fromLTRB(
8.0, // A left margin of 8.0
56.0, // A top margin of 56.0
8.0, // A right margin of 8.0
0.0 // A bottom margin of 0.0
),
child: new Column(
// A column widget can have several
// widgets that are placed in a top down fashion
children: <Widget>[
//_getAppTitleWidget(),
_getListViewWidget()
],
),
);
}
Future<Null> refresh() {
_loadLostItems();
return new Future<Null>.value();
}
Widget _getListViewWidget() {
return new Flexible(
child: new RefreshIndicator(
onRefresh: refresh,
child: new ListView.builder(
physics: const AlwaysScrollableScrollPhysics(),
itemCount: _items.length,
itemBuilder: _buildLostItems
)
)
);
}
#override
Widget build(BuildContext context) {
return new Scaffold(
backgroundColor: Colors.blue,
body: _buildBody(),
);
}
}
I made it work as follows (if I understood correctly your objective which was to display as a 2-column grid).
It also scrolls, which with your code did not work.
#override
Widget build(BuildContext context) {
return new SafeArea(
top: false,
bottom: false,
child: new Scaffold(
appBar: new AppBar(
title: _getAppTitleWidget(),
),
backgroundColor: Colors.blue,
body: _buildBody(),
),
);
}
Widget _buildBody() {
int numberOfColumns = 2;
return new Container(
padding: const EdgeInsets.all(8.0),
child: new GridView.builder(
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: numberOfColumns),
itemBuilder: _buildLostItems,
itemCount: _items.length,
),
);
}
Widget _buildLostItems(BuildContext context, int index) {
Item item = _items[index];
return new GridTile(
child: Card(
child: Column(
// mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: Stack(
fit: StackFit.expand,
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height / 4,
width: MediaQuery.of(context).size.height / 2.5,
child: DecoratedBox(
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(
item.item_DispPic),
fit: BoxFit.cover),
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Align(
alignment: FractionalOffset.topLeft,
child: CircleAvatar(
backgroundColor: Colors.redAccent,
radius: 15.0,
child: Text(
"NEW",
textScaleFactor: 0.5,
),
),
),
),
Align(
alignment: FractionalOffset.topRight,
child: Container(
color: Colors.blueAccent,
height: 35.0,
width: 35.0,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.account_circle),
Text(
"1P",
textScaleFactor: 0.5,
),
],
),
),
),
),
],
),
),
Center(
child: Container(
padding: const EdgeInsets.all(8.0),
alignment: FractionalOffset.bottomCenter,
child: Text(
"MEGADISH",
style: TextStyle(
fontWeight: FontWeight.w700,
),
),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
FlatButton(
child: Text(
"Add To Cart",
style: TextStyle(color: Colors.grey[500]),
),
onPressed: () => null,
),
Text(
"\$5",
style: TextStyle(color: Colors.grey[500]),
)
],
)
],
),
),
);
}
Here is the output:
Hope this helps.
***** Refer to other solution *****
Could you please try the following?
Update the numberOfColumns as you wish.
int numberOfColumns = 2;
List<Item> _items = <Item>[ ... ];
#override
Widget build(BuildContext context){
GridView gridView = new GridView.builder(
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: numberOfColumns),
itemBuilder: _buildLostItems,
itemCount: _items.length,
);
return new SafeArea(
top: false,
bottom: false,
child: new Scaffold(
appBar: new AppBar(
title: new Text('title'),
),
body: gridView,
),
);
}
_buildLostItems(BuildContext context, int index){
Item item = _items[index];
return new Card(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Expanded(
child: new Stack(
fit: StackFit.expand,
children: <Widget>[
new Container(
height: MediaQuery.of(context).size.height / 4,
width: MediaQuery.of(context).size.height / 2.5,
child: DecoratedBox(
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(item.item_DispPic),
fit: BoxFit.cover),
),
),
),
),
new Padding(
padding: const EdgeInsets.all(8.0),
child: new Align(
alignment: FractionalOffset.topLeft,
child: new CircleAvatar(
backgroundColor: Colors.redAccent,
radius: 15.0,
child: const Text(
"NEW",
textScaleFactor: 0.5,
),
),
),
),
],
),
),
new Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
new FlatButton(
child: new Text(
"Add To Cart",
style: new TextStyle(color: Colors.grey[500]),
),
onPressed: () {},
),
new Text(
"\$5",
style: new TextStyle(color: Colors.grey[500]),
)
],
),
],
),
);
}

Resources