This is the List View Builder of Chat Messages below here--
child: new ListView.builder(
padding: new EdgeInsets.all(8.0),
reverse: true,
itemCount: _messages.length,
itemBuilder: (context, int index) => _messages[index]),
),
Here I defined _messages as under--
final List<ChatMessage> _messages = <ChatMessage>[];
But When I am Applying "Dismissible" Widget in this, It iS not PIcking Up that correctly..
Here Is What I did..
child: new ListView.builder(
padding: new EdgeInsets.all(8.0),
reverse: true,
itemCount: _messages.length,
itemBuilder: (context, int index) => _messages[index]){
return new Dismissible(
key: new Key(_messages[index]),
onDismissed: (direction) {
items.removeAt(index);
Scaffold.of(context).showSnackBar(new SnackBar(
content: new Text("Item is Dismissed"),
));
},
background: new Container(
color: Colors.lightBlueAccent,
),
child: new ListTile(
title: new Text("${_messages[index]}")
)
);
}
But IT IS Showing error. Please Help me in this!!
Related
I am building a listview from a Firestore Database. I originally wanted to separate my items by ListTiles since I know they can do separators, but I was not getting the height that I wanted out of the tiles, so I moved to transparent Cards.
Problem is I cannot figure out how to add a separator or divider after each card.
Here is my code so far
Widget build(BuildContext context) {
if (snapshot == null) return CircularProgressIndicator();
return Scaffold(
body: ListView.builder(
itemCount: snapshot.length,
itemBuilder: (context, index){
return Card(
elevation: 0,
color: Colors.transparent,
child: Row(
children: <Widget>[
Padding(padding: EdgeInsets.all(10.0),),
Column(
children: <Widget>[
Padding(padding: EdgeInsets.all(10.0),),
Text(snapshot[index].data["month"], style:
TextStyle(fontSize: 30, fontWeight:
FontWeight.w300),),
Text(snapshot[index].data["day"], style:
TextStyle(fontSize: 20),),
],
)
],
),
);
}
),
);
}
}
Desired
Current
I would think list tiles would work better, but I tried what I knew how to do to build custom list tiles and i could not replicate the results.
Use ListView.separated
ListView.separated(
separatorBuilder: (context, index) => Divider(
color: Colors.black,
),
itemCount: 20,
itemBuilder: (context, index) => Padding(
padding: EdgeInsets.all(8.0),
child: Center(child: Text("Index $index")),
),
)
or divideTiles()
ListView(
children: ListTile.divideTiles(
context: context,
tiles: [
// your widgets here
]
).toList(),
)
I want to place a listview(1000+ items) into a column, I tried Expanded, not worked.
In the column, there is a swiper and a listview.
Is there any solution?
Here is my code:
Widget build(BuildContext context) {
return DefaultTabController(
length: _list.length,
child: Scaffold(
appBar: AppBar(
title: Text("ListView in Column"),
centerTitle: true,
bottom: TabBar(
isScrollable: false,
tabs: _list.map((String ss) {
return Tab(text: ss);
}).toList(),
),
),
body: Column(
children: <Widget>[
Container(
height: 200,
width: MediaQuery.of(context).size.width,
child: Swiper(
itemBuilder: (BuildContext context, int index) {
return _swiperImage[index];
},
itemCount: _swiperImage.length,
autoplay: true,
loop: true,
pagination: SwiperPagination(),
control: SwiperControl(),
onTap: (index) =>
Fluttertoast.showToast(msg: 'Clicked ${index + 1}'),
),
),
Expanded(
child: ListView.builder(
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return ListItemExamStrategyWidget(_listExamStrategy[index]);
},
itemCount: _listExamStrategy.length,
),
)
],
),
),
);
}
A few changes:
Wrap your Column inside SingleChildScrollView.
body: SingleChildScrollView(
child: Column(
Remove Expanded widget parent from your ListView
Set the physics of your ListView to NeverScrollableScrollPhysics
ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
It works in a column with swiper and expanded widget that holds listview with 1000 texts
Here is my working code
final List<String> _list = <String>['tab-1', 'tab-2'];
final List<String> _swiperImage = <String>[
'http://via.placeholder.com/350x150',
'http://via.placeholder.com/350x150'
];
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: _list.length,
child: Scaffold(
appBar: AppBar(
title: const Text('ListView in Column'),
centerTitle: true,
bottom: TabBar(
isScrollable: false,
tabs: _list.map((String ss) {
return Tab(text: ss);
}).toList(),
),
),
body: Column(
children: <Widget>[
Container(
height: 200,
width: MediaQuery.of(context).size.width,
child: Swiper(
itemBuilder: (BuildContext context, int index) {
return new Image.network(
_swiperImage[index],
fit: BoxFit.fill,
);
},
itemCount: _swiperImage.length,
autoplay: true,
loop: true,
pagination: const SwiperPagination(),
control: const SwiperControl(),
onTap: (int index) {
print('----------$index');
}),
),
new Expanded(
child: ListView.builder(
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return new Container(
padding: const EdgeInsets.all(15.0),
child: new Text('index ${index.toString()}'),
);
},
itemCount: 100,
),
)
],
),
),
);
}
am new to flutter ... and am calling an api in my app and i want to display a loading indicator while the api function is finished and every thing is retrieved from the api .. how to achieve this?
class _CompaniesPageState extends State<CompaniesPage> {
getcompanies() async {
var url = 'my link';
http
.post(url, body: json.encode({ 'token': globals.token }))
.then((response) {
// print("Response body: ${response.body}");
Map data = json.decode(response.body);
final companies =
(data['Companies'] as List).map((i) => new Company.fromJson(i));
setState(() {
for (final company in companies) {
if (!company.category.contains("الراعي") &&
!company.category.contains("الشريك") &&
!company.category.contains("الداعم")) {
if (company.logo != "") {
names.add(company.name);
logos.add(company.logo);
}
}
}
});
});
}
#override
Widget build(BuildContext context) {
getcompanies();
if (globals.isguest) {
return new Directionality(
.....
);
}
}
List<Widget> createCompaniesChildren() {
List<Widget> children = List<Widget>();
for (int i = 0; i < names.length; i++) {
children.add(
new Padding(
padding: new EdgeInsets.only(right: 15.0, left: 15.0),
child: new Image.network(
logos[i],
width: 346.0,
height: 180.0,
),
),
);
children.add(
new Padding(
padding: new EdgeInsets.only(right: 15.0, left: 15.0),
child: new Center(
child: new Text(
names[i],
style: new TextStyle(color: Colors.black, fontSize: 17.0),
textAlign: TextAlign.center,
),
),
),
);
children.add(new Divider());
}
return children;
}
how can i display a loading indicator while the list is being populating and then dismiss it once it's finished??
Tried this:
body: new Padding(
padding: new EdgeInsets.only(top: 15.0),
child: new Center(
child: new FutureBuilder(
future:
getcompanies(), // your async method that returns a future
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
// if data is loaded
if (snapshot.data != null) {
return new ListView.builder(
padding: new EdgeInsets.all(8.0),
itemExtent: 20.0,
itemBuilder: (BuildContext context, int i) {
return new Center(
child: new Text(
snapshot.data[i].name,
style: new TextStyle(
color: Colors.black, fontSize: 17.0),
textAlign: TextAlign.center,
),
);
},
);
} else {
// if data not loaded yet
return new CircularProgressIndicator();
}
}
},
),
),
),
but got this error: I/flutter (31276): Another exception was thrown: A build function returned null.
You could use the FutureBuilder class for that purpose.
Also instead of manually creating the companies list you could use a ListView.
Something like this:
new FutureBuilder(
future: getcompanies(), // your async method that returns a future
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
// if data is loaded
return new ListView.builder(
padding: new EdgeInsets.all(8.0),
itemExtent: 20.0,
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int i) {
return new Center(
child: new Text(
snapshot.data[i].name,
style: new TextStyle(color: Colors.black, fontSize: 17.0),
textAlign: TextAlign.center,
),
);
},
).build(context);
} else {
// if data not loaded yet
return new CircularProgressIndicator();
}
},
)
Although you have already solved or got the answer. I will show you 2 Ways.
1. Using any builder like FutureBuilder, StreamBuilder....
FutureBuilder(
future: getcompanies(), // your async method that returns a future
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.active:
case ConnectionState.waiting:
return Padding(
padding: const EdgeInsets.only(top: 20),
child: Center(
child: CircularProgressIndicator()
),
);
case ConnectionState.none:
return Center(child: Text("Unable to connect right now"));
case ConnectionState.done:
if (snapshot.hasError) {
print("Error: ${snapshot.error}");
}
return ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: snapshot.data!.length,
itemBuilder: (BuildContext context, int i) {
return new Center(
child: new Text(
snapshot.data[i].name,
style: new TextStyle(color: Colors.black, fontSize: 17.0),
textAlign: TextAlign.center,
),
);
},
);
}
},
),
2. Without using builder
Put this code before API call, Like
AlertDialog alert = AlertDialog(
content: Row(children: [
CircularProgressIndicator(
backgroundColor: Colors.red,
),
Container(margin: EdgeInsets.only(left: 10), child: Text("Loading...")),
]),
);
showDialog(
barrierDismissible: false,
context: context,
builder: (BuildContext context) {
return alert;
},
);
api.getcompanies();
And after getting API response
var response = api.getcompanies();
Navigator.pop(context);
Note : You can put the code into a method and then call it here
i'hve a flutter project,
when i tried to make a invinite listview but scroll controller not work, no error.
also refresh indicator not work to, but if primary false on listview refresh work.
for information, my listview not work if primary set to false, because this listview inside listview on main.dart
code
List<dynamic> list = [];
ScrollController _scrollController = ScrollController();
void initState() {
super.initState();
_loadData();
_scrollController.addListener(() {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent - 50) {
_loadData();
}
});
}
#override
void dispose() {
_scrollController.dispose();
super.dispose();
}
Future<dynamic> _loadData() {
var offset = list.length;
return Api().postData("resto",
body: <String, String>{"offset": "$offset"}).then((dynamic res) {
if (res["error"]) throw new Exception(res["msg"]);
setState(() {
list.addAll(res['data']);
});
});
}
#override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
FlatButton(
child: Text(
"Filter Popularity",
style: TextStyle(color: Colors.red),
),
onPressed: () {},
),
Padding(
padding: const EdgeInsets.all(8.0),
child: list.length == 0 ? _shimmer() : _listResto()),
],
);
}
Widget _listResto() {
return ListView.builder(
controller: _scrollController,
primary: false,
shrinkWrap: true,
itemCount: list == null ? 0 : list.length,
itemBuilder: (context, i) {
add physics: const AlwaysScrollableScrollPhysics() to RefreshIndicator
body: RefreshIndicator(
onRefresh: _refreshList,
child: ListView.builder(
controller: _scrollController,
physics: const AlwaysScrollableScrollPhysics(),
itemCount: items.length,
itemBuilder: (context, index) => ListTile(
title: Text('Item ${items[index]}'),
),
),
)
new Expanded(
child: _searchResult.length != 0 || controller.text.isNotEmpty
? new ListView.builder(
itemCount: _searchResult.length,
itemBuilder: (context, int i) {
return new Card(
child: new Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new Row(children: <Widget>[
//new GestureDetector(),
new Container(
width: 45.0,
height: 45.0,
decoration: new BoxDecoration(
shape: BoxShape.circle,
image: new DecorationImage(
fit: BoxFit.fill,
image: new NetworkImage(
"https://raw.githubusercontent.com/flutter/website/master/_includes/code/layout/lakes/images/lake.jpg")))),
new Text(
" " +
userDetails[returnTicketDetails[i]
["user_id"]]["first_name"] +
" " +
(userDetails[returnTicketDetails[i]
["user_id"]]["last_name"]),
style: const TextStyle(
fontFamily: 'Poppins', fontSize: 20.0)),
]),
new Column(
children: <Widget>[
new Align(
alignment: FractionalOffset.topRight,
child: new FloatingActionButton(
onPressed: () {
groupId = returnTicketDetails[i]["id"];
print(returnTicketDetails[i]["id"]);
print(widget.id);
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => new Tickets(groupId,widget.id)));
},
heroTag: null,
backgroundColor: Color(0xFF53DD6C),
child: new Icon(Icons.arrow_forward),
)),
new Padding(padding: new EdgeInsets.all(3.0)),
],
)
]));
},
)
: new ListView.builder(
itemCount: _searchResult.length,
itemBuilder: (context, int i) {
return new Card(
child: new ListTile(
//title: new Text(userDetails[returnTicketDetails[i]["user_id"]]["first_name"]),
),
margin: const EdgeInsets.all(0.0),
);
},
),
),
Hi everyone! As I am building dynamically a Card in a ListView, I was thinking rather than keep the FloatingActionButton in each of them as I already do, to implement a onTap method in each card and trigger something.
In other words, I would like to keep the card as simple as possible without many widget around.
Thank you in advance!
As Card is "a sheet of Material", you probably want to use InkWell, which includes Material highlight and splash effects, based on the closest Material ancestor.
return Card(
child: InkWell(
onTap: () {
// Function is executed on tap.
},
child: ..,
),
);
You should really be wrapping the child in InkWell instead of the Card:
return Card(
child: InkWell(onTap: () {},
child: Text("hello")));
This will make the splash animation appear correctly inside the card rather than outside of it.
Just wrap the Card with GestureDetector as below,
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return new ListView.builder(
itemBuilder: (context, i) {
new GestureDetector(
child: new Card(
....
),
onTap: onCardTapped(i),
);
},
);
}
onCardTapped(int position) {
print('Card $position tapped');
}
}