I am getting this error when trying to add Widget in tab bar. Please check following code
return Scaffold(
appBar: new AppBar(
bottom: PreferredSize(
child: _tabBar,
preferredSize: Size.fromHeight(_tabBar.preferredSize.height - 50),
),
),
body: new TabBarView(
controller: _tabController,
children: <Widget>[
new PicMee(),
new PicMee()
],
),
);
For Picmee file:
class PicMee extends StatefulWidget{
#override
_PicMeeState createState() => new _PicMeeState();
}
class _PicMeeState extends State<PicMee>{
#override
Widget build(BuildContext context) {
// TODO: implement build
return new Scaffold(
body: new ListView.builder(
itemCount: 20,
itemBuilder: (BuildContext context, int index){
return new CustomWidget(date: null, content: null, trailingIconOne: null, trailingIconTwo: null)
}
// https://stackoverflow.com/questions/47233209/flutter-group-listviews-with-separator?rq=1
),
);
}
}
class CustomWidget extends StatelessWidget {
String date;
String content;
Icon trailingIconOne;
Icon trailingIconTwo;
CustomWidget(
{#required this.date, #required this.content, #required this.trailingIconOne, #required this.trailingIconTwo});
#override
Widget build(BuildContext context) {
return new Container(
decoration: new BoxDecoration(
border: new Border.all(color: Colors.grey[500])
),
child: new Column(
children: <Widget>[
new Container (child: new Text(date), color: Colors.yellow[200],),
new Container(height: 15.0,),
new Text(content),
new Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
new IconButton(icon: trailingIconOne, onPressed: () {}),
new Container(width: 10.0,),
new IconButton(icon: trailingIconTwo, onPressed: () {})
],
)
],
),
);
}
}
I am getting this error:
flutter: Another exception was thrown:
'package:flutter/src/widgets/text.dart': Failed assertion: line 235
pos 15: 'data != null': is not true.
replace this line :
return new CustomWidget(date: null, content: null, trailingIconOne: null, trailingIconTwo: null)
to this :
return new CustomWidget(date: "date", content: "content", trailingIconOne: Icon(Icons.add), trailingIconTwo: Icon(Icons.add))
Related
I'm adding routing into my Flutter app and I would like to re-use some common Widgets across all of my routes.
For instance, the AppBar and Drawer instances should be defined on the top level view and the routed view should be in a contained Widget (the yellow part in the image)
Is is supported? currently all "Flutter Routing" references I find demonstrate replacement of the entire view => different instances of the common Widgets for every route.
void redirect(BuildContext context, name) {
Navigator.of(context).pushNamed(name);
}
getCommonDrawer(context) {
return Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
DrawerHeader(
child: Text('header'),
decoration: BoxDecoration(
color: Colors.greenAccent,
),
),
ListTile(
title: Text('foo'),
onTap: () {
Navigator.pop(context);
},
),
ListTile(
title: Text('bar'),
onTap: () {
Navigator.pop(context);
},
),
],
),
);
}
class Screen1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Screen 1"),
),
drawer: getCommonDrawer(context),
body: new Center(
child: new Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
new RaisedButton(
onPressed: () {
redirect(context, "/screen2");
},
child: new Text("screen2"),
)
],
),
),
);
}
}
class Screen2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Screen 2"),
),
drawer: getCommonDrawer(context),
body: new Center(
child: new Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
new RaisedButton(
onPressed: () {
redirect(context, "/screen1");
},
child: new Text("screen1"),
)
],
),
),
);
}
}
void main() { // 1
runApp( // 2
new MaterialApp( //3
home: new Screen1(), //4
routes: <String, WidgetBuilder> { //5
'/screen1': (BuildContext context) => new Screen1(), //6
'/screen2' : (BuildContext context) => new Screen2() //7
},
)
);
}
I am getting dirty state exception when redirecting on a new page after login. On this home page I am getting info from preferences.
class Home extends StatefulWidget{
#override
State<StatefulWidget> createState() => new _HomeState();
}
class _HomeState extends State<Home> {
Drawer drawer = new Drawer();
String strName, strEmail, strImageURL;
int userId;
Image imgProfile;
#override
void initState() {
super.initState();
_loadSharedPref();
}
//Loading Shared value on start
_loadSharedPref() async {
print('In Shared Profile');
try{
SharedPreferences prefs = await SharedPreferences.getInstance();
strName = prefs.getString('name');
print('Shared Profile Name '+strName);
setState(() {
strName = prefs.getString('name');
userId = prefs.getInt('userId');
strEmail = prefs.getString('email');
strImageURL = prefs.getString('avatar');
imgProfile = Image.network(Config.PROFILE_PIC+strImageURL);
print('Image URL ---- '+Config.PROFILE_PIC+strImageURL);
});
}catch(exception){
print('SharedProfile '+exception);
}
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: new Scaffold(
backgroundColor: whiteColor,
drawer: sideDrawer(),
appBar: new AppBar(
title: new Text('Test Page'),
),
),
);
}
//Profile Details
Widget profileDetail() {
return new DrawerHeader(
child: new Column(
children: <Widget>[
new CircleAvatar(
radius: 40,
backgroundColor : blueColor,
backgroundImage: new NetworkImage(Config.PROFILE_PIC+strImageURL),
),
],
)
);
}
//Side Drawer
Widget sideDrawer(){
return new Drawer(
child: new ListView(
children: <Widget>[
new Center(
child: profileDetail(),
),
new ListTile(
leading: new Icon(Icons.lightbulb_outline),
title: new Text('Requests'),
// onTap: () => _onListTileTap(context),
),
new ListTile(
leading: new Icon(Icons.lightbulb_outline),
title: new Text('Reviews'),
// onTap: () => _onListTileTap(context),
),
new ListTile(
leading: new Icon(Icons.lightbulb_outline),
title: new Text('Setting'),
// onTap: () => _onListTileTap(context),
),
new ListTile(
leading: new Icon(Icons.lightbulb_outline),
title: new Text('Tip'),
// onTap: () => _onListTileTap(context),
),
new ListTile(
leading: new Icon(Icons.lightbulb_outline),
title: new Text('Conditions'),
// onTap: () => _onListTileTap(context),
),
new ListTile(
leading: new Icon(Icons.lightbulb_outline),
title: new Text('About Us'),
// onTap: () => _onListTileTap(context),
),
new ListTile(
leading: new Icon(Icons.lightbulb_outline),
title: new Text('Log Out'),
// onTap: () => _onListTileTap(context),
),
],
),
);
}
}
Cross-link https://github.com/flutter/flutter/issues/25428
I went into the same kind of problem. Checking my variables having shared pref values for null or not worked for me.
Try checking strName, userId, strEmail, strImageURL, imgProfile are not null before using them in the widget.
if(strImageURL != null)
{
print('filepaths: '+strImageURL);
}
Try this out
//Profile Details
Widget profileDetail() {
return new DrawerHeader(
child: new Column(
children: <Widget>[
new CircleAvatar(
radius: 40,
backgroundColor : blueColor,
backgroundImage: strImageURL ?? AssetImage('some static file path') : NetworkImage(Config.PROFILE_PIC+strImageURL),
),
],
)
);
}
You probably didn't fill "name", "userId", "avatar" or "email" fields in your preferences and you are getting this error when trying to get with SharedPreferences.
just create statement everytime you trying to call the data from sharedPreference like this
body: yourDatainsharedPreference != null ?
//do something
:
// do something
I'm new to Flutter,
I want to destruct cards created initially and construct them again as per data provided in API call.
Basically when I tap on button in UI, it should call APIs and based on data from API call, if it is different from the data I already have, I want to destruct cards and construct them again.
How I can achieve this?
The cards will auto update their content when you make the call again, it is like refreshing your data.
I have made a simple example with a single card that shows data from this JSON Where I am calling the API first time in initState and then repeating the call each time I press on the FAB.
I am adding the index variable just to show you the updates (updating my single card with the next item in the list)
Also it is worth noting that I am handling the null or empty values poorly for the sake of time.
Also forget about the UI overflow ¯_(ツ)_/¯
class CardListExample extends StatefulWidget {
#override
_CardListExampleState createState() => new _CardListExampleState();
}
class _CardListExampleState extends State<CardListExample> {
Map cardList = {};
int index = 0;
#override
void initState() {
_getRequests();
super.initState();
}
_getRequests() async {
String url = "https://jsonplaceholder.typicode.com/users";
var httpClinet = createHttpClient();
var response = await httpClinet.get(
url,
);
var data = JSON.decode(response.body);
//print (data);
setState(() {
this.cardList = data[index];
this.index++;
});
print(cardList);
print(cardList["name"]);
}
#override
Widget build(BuildContext context) {
return new Scaffold(
floatingActionButton:
new FloatingActionButton(onPressed: () => _getRequests()),
appBar: new AppBar(
title: new Text("Card List Example"),
),
body: this.cardList != {}
? new ListView(children: <Widget>[
new Card(
child: new Column(
children: <Widget>[
new Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new Text(
cardList["name"] ?? '',
style: Theme.of(context).textTheme.display1,
),
new Text(
this.cardList['email'] ?? '',
maxLines: 50,
),
],
),
new Text(cardList["website"] ?? '')
],
),
),
])
: new Center(child: new CircularProgressIndicator()),
);
}
}
Yes, Answer from Aziza works.
Though I used the code as below :
void main() =>
runApp(new MaterialApp(
onGenerateRoute: (RouteSettings settings) {
switch (settings.name) {
case '/about':
return new FromRightToLeft(
builder: (_) => new _aboutPage.About(),
settings: settings,
);
}
},
home : new HomePage(),
theme: new ThemeData(
fontFamily: 'Poppins',
primarySwatch: Colors.blue,
),
));
class HomePage extends StatefulWidget{
#override
HomePageState createState() => new HomePageState();
}
class HomePageState extends State<HomePage>{
List data;
Future<String> getData() async{
var response = await http.get(
Uri.encodeFull(<SOMEURL>),
headers: {
"Accept" : "application/json"
}
);
this.setState((){
data = JSON.decode(response.body);
});
return "Success";
}
#override
void initState() {
// TODO: implement initState
super.initState();
this.getData();
}
#override
Widget build(BuildContext context){
return new Scaffold(
appBar : new AppBar(
title : new Text("ABC API"),
actions: <Widget>[
new IconButton( // action button
icon: new Icon(Icons.cached),
onPressed: () => getData(),
)],
),
drawer: new Drawer(
child: new ListView(
children: <Widget> [
new Container(
height: 120.0,
child: new DrawerHeader(
padding: new EdgeInsets.all(0.0),
decoration: new BoxDecoration(
color: new Color(0xFFECEFF1),
),
child: new Center(
child: new FlutterLogo(
colors: Colors.blueGrey,
size: 54.0,
),
),
),
),
new ListTile(
leading: new Icon(Icons.chat),
title: new Text('Support'),
onTap: () {
Navigator.pop(context);
Navigator.of(context).pushNamed('/support');
}
),
new ListTile(
leading: new Icon(Icons.info),
title: new Text('About'),
onTap: () {
Navigator.pop(context);
Navigator.of(context).pushNamed('/about');
}
),
new Divider(),
new ListTile(
leading: new Icon(Icons.exit_to_app),
title: new Text('Sign Out'),
onTap: () {
Navigator.pop(context);
}
),
],
)
),
body: this.data != null ?
new ListView.builder(
itemCount: data.length,
itemBuilder: (BuildContext context, int index){
return new Container(
padding: new EdgeInsets.fromLTRB(8.0,5.0,8.0,0.0),
child: new Card(
child: new Padding(
padding: new EdgeInsets.fromLTRB(10.0,12.0,8.0,0.0),
child: new Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new ListTile(
enabled: data[index]['active'] == '1' ? true : false,
title: new Text(data[index]['header'],
style:Theme.of(context).textTheme.headline,
),
subtitle: new Text("\n" + data[index]['description']),
),
new ButtonTheme.bar(
child: new ButtonBar(
children: <Widget>[
new FlatButton(
child: new Text(data[index]['action1']),
onPressed: data[index]['active'] == '1' ? _launchURL :null,
),
],
),
),
],
),
),
),
);
},
)
:new Center(child: new CircularProgressIndicator()),
);
}
}
_launchURL() async {
const url = 'http://archive.org';
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
}
class FromRightToLeft<T> extends MaterialPageRoute<T> {
FromRightToLeft({ WidgetBuilder builder, RouteSettings settings })
: super(builder: builder, settings: settings);
#override
Widget buildTransitions(
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child) {
if (settings.isInitialRoute)
return child;
return new SlideTransition(
child: new Container(
decoration: new BoxDecoration(
boxShadow: [
new BoxShadow(
color: Colors.black26,
blurRadius: 25.0,
)
]
),
child: child,
),
position: new Tween(
begin: const Offset(1.0, 0.0),
end: const Offset(0.0, 0.0),
)
.animate(
new CurvedAnimation(
parent: animation,
curve: Curves.fastOutSlowIn,
)
),
);
}
#override Duration get transitionDuration => const Duration(milliseconds: 400);
}
The above code includes Navigation drawer, page navigation animation and also answer to the above question.
I've the below code for entering some data, I do not know how to handle it!
i.e. What shall I write at the onPressed for the IconButton so that the data is read from all the elements (name, birthday, ...)? and how to display it in Dialog to check if read correctly?
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.deepOrange,
),
home: new MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var _value=false;
double _bodyHeight=0.0;
void onchange(bool value) {
setState(() {
_value = value;
this._bodyHeight = (value == true) ? 400.0 : 0.0;
});
}
#override
Widget build(BuildContext context) {
return new Scaffold(
backgroundColor: Colors.grey[500],
appBar: new AppBar(
title: new Text(widget.title),
),
body: new SingleChildScrollView(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Card(
child: new Container(
height: 50.0,
child: new Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
new Text("Select me pls"),
new Switch(value: _value, onChanged: (bool value) => onchange(value)),
],
),
),
),
new Card(
child: new AnimatedContainer(
child: new ListView(
children: <Widget>[
new ListTile(
leading: const Icon(Icons.person),
title: new TextField(
decoration: new InputDecoration(
hintText: "Name",
),
),
),
new ListTile(
leading: const Icon(Icons.phone),
title: new TextField(
decoration: new InputDecoration(
hintText: "Phone",
),
),
),
new ListTile(
leading: const Icon(Icons.email),
title: new TextField(
decoration: new InputDecoration(
hintText: "Email",
),
),
),
const Divider(
height: 1.0,
),
new ListTile(
leading: const Icon(Icons.label),
title: const Text('Nick'),
subtitle: const Text('None'),
),
new ListTile(
leading: const Icon(Icons.today),
title: const Text('Birthday'),
subtitle: const Text('February 20, 1980'),
),
new IconButton(icon: const Icon(Icons.save),
onPressed: null
/*
*
* What shall I write here to read the data in the elements
*
*
*
* */
),
],
),
curve: Curves.easeInOut,
duration: const Duration(milliseconds: 500),
height: _bodyHeight,
// color: Colors.red,
),
),
],
),
),
);
}
}
One way is that TextFields take a property called TextEditingController which allow you to access the value of the TextField.
And to show a dialog you can just call showDialog() function.
class TextFieldExample extends StatefulWidget {
#override
_TextFieldExampleState createState() => new _TextFieldExampleState();
}
class _TextFieldExampleState extends State<TextFieldExample> {
TextEditingController c1;
TextEditingController c2;
#override
void initState() {
c1 = new TextEditingController();
c2 = new TextEditingController();
super.initState();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new TextField (
controller: c1,
),
new TextField(
controller: c2,
),
new OutlineButton(onPressed: () {
showDialog(child: new AlertDialog(
content: new Text("You entered ${c1.text} ${c2.text} ")
),
context: context
);
},
child: new Text("Show Dialog"),
)
],
),
),
);
}
}
Can someone fire up a quick flutter project and replace main.dart with the following and see what I'm doing wrong? I'm trying to get drag and drop working in ListView.
I'm not even sure this is the right approach so if not, please let me know.
The error I'm getting now is:
Another exception was thrown: 'package:flutter/src/rendering/box.dart': Failed assertion: line 1446 pos 12: 'hasSize': is not true.
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
final title = 'Basic List';
var tile1 = new Material(child:
new ListTile(
leading: new Icon(Icons.photo),
title: new Text('Row 1'),
trailing: new Icon(Icons.reorder),
));
var tile2 = new Material(
child:
new ListTile(
leading: new Icon(Icons.photo),
title: new Text('Row 2'),
trailing: new Icon(Icons.reorder),
));
return new MaterialApp(
title: title,
home: new Scaffold(
appBar: new AppBar(
title: new Text(title),
),
body:
new GestureDetector(
onVerticalDragStart: startDrag,
onVerticalDragEnd: endDrag,
child: new ListView(
shrinkWrap: true,
children: [
new Flex (
children: <Widget>[
new Flexible(
child: new Draggable(child: tile1, feedback:
tile1),
),
new Flexible(
child: new Draggable(child: tile2, feedback:
tile2),
),
],
direction: Axis.vertical,
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
),
],
),
),
),
);
}
void startDrag(DragStartDetails event) {}
void endDrag(DragEndDetails event) {}
}
Thanks
With a little help along the way from #Darky to resolve the issue hasSize issue, here's the finished sortable ListView example:
https://github.com/marchampson/FluterSortableListView
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatefulWidget {
#override
MyAppState createState() => new MyAppState();
}
class MyAppState extends State<MyApp> {
List<String> rows = new List<String>()
..add('Row 1')
..add('Row 2')
..add('Row 3')
..add('Row 4');
void _handleAccept(int data, int index) {
setState(() {
String imageToMove = rows[data];
rows.removeAt(data);
rows.insert(index, imageToMove);
});
}
#override
Widget build(BuildContext context) {
final title = 'Sortable ListView';
return new MaterialApp(
title: title,
home: new Scaffold(
appBar: new AppBar(
title: new Text(title),
),
body:
new LayoutBuilder(builder: (context, constraint) {
return new ListView.builder(
itemCount: rows.length,
addRepaintBoundaries: true,
itemBuilder: (context, index) {
return new LongPressDraggable(
key: new ObjectKey(index),
data: index,
child: new DragTarget<int>(
onAccept: (int data) {
_handleAccept(data, index);
},
builder: (BuildContext context, List<int> data, List<dynamic> rejects) {
return new Card(
child: new Column(
children: <Widget>[
new ListTile(
leading: new Icon(Icons.photo),
title: new Text(rows[index])
),
],
)
);
},
onLeave: (int data) {
// Debug
print('$data is Leaving row $index');
},
onWillAccept: (int data) {
// Debug
print('$index will accept row $data');
return true;
},
),
onDragStarted: () {
Scaffold.of(context).showSnackBar(new SnackBar (
content: new Text("Drag the row onto another row to change places"),
));
},
onDragCompleted: () {
print("Finished");
},
feedback: new SizedBox(
width: constraint.maxWidth,
child: new Card (
child: new Column(
children: <Widget>[
new ListTile(
leading: new Icon(Icons.photo),
title: new Text(rows[index]),
trailing: new Icon(Icons.reorder),
),
],
),
elevation: 18.0,
)
),
childWhenDragging: new Container(),
);
},
);
}),
),
);
}
}