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.
Related
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()
),
),
],
)
],
),
),
)
],
)
),
),
);
}
}
I have a ListView in which I will dynamically add in some children of same type. Inside every children widget has a button. What I want to implement is, that, when user presses the button on a child widget, this child widget will be removed from the ListView. I can do this in C# using events, but I'm a total noob to Dart and Flutter.
Here is my ListView
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text('Edit Plan'),
backgroundColor: Colors.green,
actions: <Widget>[
Builder(
builder: (context) => IconButton(
icon: Icon(Icons.add),
onPressed: () {
setState(() {
txts.add('set');
});
},
),
)
],
),
backgroundColor: Colors.white,
body: ListView(
children: txts.map((string) =>
new ListViewItem()).toList(growable: false),
),
);
}
And here is my listViewItem:
class ListViewItem extends StatelessWidget {
final Workout workout;
ListViewItem({Key key, #required this.workout})
: assert(workout != null),
super(key: key);
#override
Widget build(BuildContext context) {
// TODO: implement build
final theme = Theme.of(context);
return Padding(
padding: EdgeInsets.all(12),
child: Card(
elevation: 12,
color: Colors.green,
child: Padding(
padding: EdgeInsets.only(top: 4, bottom: 4, left: 8, right: 8),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const ListTile(
leading: Icon(Icons.album),
title: Text(
'The Enchanted Nightingale',
style: TextStyle(color: Colors.white),
),
subtitle: Text(
'Music by Julie Gable. Lyrics by Sidney Stein.',
style: TextStyle(color: Colors.white),
),
),
TextFormField(
decoration: InputDecoration(
labelText: 'Name your workout',
labelStyle: TextStyle(color: Colors.white)),
),
ButtonTheme.bar(
// make buttons use the appropriate styles for cards
child: ButtonBar(
children: <Widget>[
FlatButton(
child: const Text(
'DELETE',
style: TextStyle(color: Colors.white),
),
onPressed: () {},
),
],
),
),
],
),
)),
);
}
}
I edited your code to use a ListView.builder, you need to remove the item at index from the List (txts) you are using, your code will be as follows:
List<String> txts = List();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Edit Plan'),
backgroundColor: Colors.green,
actions: <Widget>[
Builder(
builder: (context) =>
IconButton(
icon: Icon(Icons.add),
onPressed: () {
setState(() {
txts.add('set');
});
},
),
)
],
),
backgroundColor: Colors.white,
body: new ListView.builder(
itemCount: txts.length,
itemBuilder: (BuildContext context, int index) {
return ListViewItem(
workout: workout,
onDelete: (){
setState(() {
txts.removeAt(index);
});
},
);
},
),
);
}
in addition to that you need to add an ondelete callback in the ListViewItem, the code in the ListViewItem class will be as follows:
class ListViewItem extends StatelessWidget {
final Workout workout;
final VoidCallback onDelete;
ListViewItem({Key key, #required this.workout, this.onDelete})
: assert(workout != null),
super(key: key);
#override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Padding(
padding: EdgeInsets.all(12),
child: Card(
elevation: 12,
color: Colors.green,
child: Padding(
padding: EdgeInsets.only(top: 4, bottom: 4, left: 8, right: 8),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const ListTile(
leading: Icon(Icons.album),
title: Text(
'The Enchanted Nightingale',
style: TextStyle(color: Colors.white),
),
subtitle: Text(
'Music by Julie Gable. Lyrics by Sidney Stein.',
style: TextStyle(color: Colors.white),
),
),
TextFormField(
decoration: InputDecoration(
labelText: 'Name your workout',
labelStyle: TextStyle(color: Colors.white)),
),
ButtonTheme.bar(
// make buttons use the appropriate styles for cards
child: ButtonBar(
children: <Widget>[
FlatButton(
child: const Text(
'DELETE',
style: TextStyle(color: Colors.white),
),
onPressed: () =>onDelete(),
),
],
),
),
],
),
)),
);
}
}
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.
My Listview items are going out of the view and showing in ListTile that is below my Listview, I am not getting what I am doing wrong in my code. Please have a look at below images, you can see ending point of list view and in another image my items are going out of this ending point. I am posting my code below, please have a look and help me to resolve this issue.
Here is my Listview items are going out of the view.
Below is the code:
class _CartFinalSummaryState extends State<CartFinalSummary> {
final cartSummary = new StoreConnector<List<CartItem>, List<CartItem>>(
converter: (store) => store.state,
builder: (context, list) => new Padding(
padding: const EdgeInsets.all(8.0),
child: new Container(
margin: new EdgeInsets.only(top: 5.0, left: 5.0, right: 5.0),
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
new Text(
"Quantity: (${getTotalQuantity(list)})",
style: new TextStyle(
fontSize: 15.0,
fontWeight: FontWeight.w700
),
),
],
),
),
),);
final listCartItem = new StoreConnector<List<CartItem>,
List<CartItem>>(
converter: (store) => store.state,
builder: (context, list) => new Container(
child: new Flexible(
child: new Stack(
children: <Widget>[
new ListView.builder(
scrollDirection: Axis.vertical,
itemCount: list ==0 ? null : list.length,
itemBuilder: (context, index){
return new Column(
children: <Widget>[
new ListTile(
title: new Text(
list[index].product
.name.toString(),
style: new TextStyle(fontWeight: FontWeight.bold,
fontSize: 18.0),),
subtitle: new Text(list[index].quantity.toString()
+ " x " + list[index].product.price.toString()),
trailing: new Text("€"+(list[index].product.price *
list[index].quantity).toString(),
style: new TextStyle(fontWeight: FontWeight.bold,
fontSize: 18.0)),
),
new Divider(
)
],
);
}),
],
),
),
));
#override
Widget build(BuildContext context) {
return new Scaffold(
bottomNavigationBar: new GestureDetector(
onTap: () {
/*Navigator.push(
context,
new MaterialPageRoute(builder: (context) =>
new SelectTable()));*/
},
child:new StoreConnector<List<CartItem>, List<CartItem>>(
converter: (store) => store.state,
builder: (context, list) => new Container(
padding: const EdgeInsets.all(10.0),
color: Colors.green,
child: new Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new GestureDetector(
child: new Text("Proceed to Pay ${
"( €"+getTotal(list).toStringAsFixed(2)+" )"}", style:
new TextStyle(
color: Colors.white,
fontSize: 18.0),),
)
],
)
)),
),
appBar: new AppBar(
iconTheme: new IconThemeData(color: Colors.white),
title: new Text('Cart Summary', style: new TextStyle(
color: Colors.white
),),
),
body: new Container(
child: new Column(
children: <Widget>[
cartSummary,
new Divider(
color: Colors.black,
height: 3.0,
),
listCartItem,
new Divider(
color: Colors.black,
height: 5.0,
),
new ListTile(
title: new Text("Table Selected",
style: new TextStyle(fontWeight: FontWeight.bold,
fontSize: 18.0)),
trailing: new Text("5",
style: new TextStyle(fontWeight: FontWeight.bold,
fontSize: 18.0)),
),
new Divider(
color: Colors.black,
),
new ListTile(
title: new Text("Sub Total",
style: new TextStyle(fontWeight: FontWeight.bold,
fontSize: 18.0)),
trailing: new Text("5",
style: new TextStyle(fontWeight: FontWeight.bold,
fontSize: 18.0)),
),
],
),
),
);
}
}
I've resolved the issue by replacing this piece of code. I am still not sure what was the problem, I think the ListTiles that I was using were transparent, I've used ListTile as child of Container widget and set the background color of container.
new Divider(
color: Colors.black,
height: 0.1,
),
new Container(
color: const Color(0xFFD6D6D6),
child: new ListTileTheme(
child: new ListTile(
onTap: (){
Navigator.pushReplacement(
context,
new MaterialPageRoute(builder: (context) =>
new SelectTable()));
},
title: new Text("Table Selected",
style: new TextStyle(fontWeight: FontWeight.bold,
fontSize: 17.0)),
trailing: new Text(widget.tableNumber.toString(),
style: new TextStyle(fontWeight: FontWeight.bold,
fontSize: 17.0)),
),
),
),
new Divider(
height: 0.1,
color: Colors.black,
),
new Container(
color: const Color(0xFFD6D6D6),
child: new ListTile(
title: new Text("Grand Total",
style: new TextStyle(fontWeight: FontWeight.bold,
fontSize: 17.0)),
trailing: new Text("€"+getTotal(list).toString(),
style: new TextStyle(fontWeight: FontWeight.bold,
fontSize: 17.0)),
),
),
I want to scale the text in my flutter application according to various devices size or devicePixelRatio value. I know flutter should scale text according to devicePixelRatio value, so I change my code in that way, but it's not working in my code.
Here is my code:
class MyHomePage extends StatefulWidget {
#override
MyHomePageState createState() => new MyHomePageState();
}
class MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
TextStyle style50 = new TextStyle(
inherit: true,
fontSize: 50.0,
color: Colors.white,
);
TextStyle style19 = new TextStyle(
inherit: true,
color: Colors.white,
fontSize: 19.0,
fontFamily: 'helvetica_neue',
);
TextStyle style15White = new TextStyle(
inherit: true,
color: Colors.white,
fontSize: 15.0,
fontFamily: 'helvetica_neue',
);
TextStyle style15Green = new TextStyle(
inherit: true,
color: Colors.green,
fontSize: 15.0,
fontFamily: 'helvetica_neue',
);
return new Scaffold(
body: new Container(
decoration: new BoxDecoration(
image: new DecorationImage(
image: new AssetImage("assets/images/home_page_background.png"),
fit: BoxFit.cover,
),
),
child: new Container(
child: new Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Container(
margin: new EdgeInsets.only(top: 160.0),
child: new Text(
'JAHMAIKA',
textAlign: TextAlign.center,
style: style50,
),
),
new Container(
margin: new EdgeInsets.only(top: 230.0),
child: new FlatButton(
child: new Container(
padding: new EdgeInsets.only(
left: 45.0, right: 45.0, top: 15.0, bottom: 15.0),
decoration: new BoxDecoration(
shape: BoxShape.rectangle,
borderRadius: new BorderRadius.all(
new Radius.elliptical(40.0, 50.0)),
border: new Border.all(
color: Colors.white,
),
),
child: new Text(
'Create an account',
style: style19,
),
),
onPressed: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => new SignUpPage()),
);
}),
),
new Container(
margin: new EdgeInsets.only(top: 16.0),
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Container(
child: new Text(
'Already have an account?',
textAlign: TextAlign.center,
style: style15White,
),
),
new GestureDetector(
onTap: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => new SignInPage()),
);
},
child: new Container(
margin: new EdgeInsets.only(left: 16.0),
child: new Text('Login',
textAlign: TextAlign.center, style: style15Green),
),
),
],
),
),
],
),
)),
);
}
}
But this is not working. There is no change in the text font size in various devices. Please help me.
Have you tried computing the fontSize based on a proportion of MediaQuery.of(context).size.width ?
Set the sizes using a base device, and use it's width to calculate the other devices proportional sizes.
...
Widget build(BuildContext context) {
// 414.0 is the width of an iPhone 7plus
double fs = 50.0 * MediaQuery.of(context).size.width / 414.0;
// print("MediaQuery.of(context).size.width=${MediaQuery.of(context).size.width}");
// print("fs=$fs");
TextStyle style50 = new TextStyle(
inherit: true,
fontSize: fs,
color: Colors.white,
);
...