I was testing the "tap function" for items within a ListView, but it does not seem to work. The print function does not work when I tap upon the list.
return Scaffold(
appBar: AppBar(
// App Bar
title: Text(
"ListView On-Click Event",
style: TextStyle(color: Colors.grey),
),
elevation: 0,
backgroundColor: Colors.white,
),
// Main List View With Builder
body: ListView.builder(
itemCount: imgList.length,
itemBuilder: (context, index) {
return GestureDetector(
onTap: () {
print("button pressed");
print(index);
},
child: Container(
margin: const EdgeInsets.symmetric(
vertical: 2.0,
horizontal: 8.0,
),
child: Stack(
children: <Widget>[
cardDesign,
cardImage,
],
),
),
); // gesturedetector
}));
Where am I going wrong?
Try to used Column instead of Stack
ListView.builder(
shrinkWrap: true,
itemCount: 10,
itemBuilder: (context, index) {
return GestureDetector(
onTap: () {
print("button pressed");
print(index);
},
child: Container(
margin: const EdgeInsets.symmetric(
vertical: 2.0,
horizontal: 8.0,
),
child: Column(
children: <Widget>[
Text(index.toString()),//put your widgets here
],
),
),
); // gesturedetector
}),
you can use ListTile inside ListView,because ListTile have onTap function, same here :
ListView.builder(
itemCount: data.length,
itemBuilder: (BuildContext context, int index) {
return Card(
child: ListTile(
title: Text('TextHere'),
onTap: () {
log('on tap');
},
),
);
});
Related
Is it possible to configure a ExpansationTile to have 2 actions:
Expand when clicking on the trailing icon
Going to another screen when clicking anywhere else?
Also, is it possible to omit the trailing icon IF the children of the item doesn't have information to display (eg, sublist is empty)?
Here's what I have ATM:
Expanded(
child: ListView.builder(
itemBuilder: (context, index) {
return Card(
child: ExpansionTile(
leading: Image.asset('images'),
title: Text('Text'),
subtitle: Text('Text'),
children: [
ListView.builder(
itemBuilder: (context, index2) {
return Card(
child: ListTile(
onTap: () => print('test'),
leading: Image.asset('images'),
title: Text('Text'),
subtitle: Text('Text'),
);
},
itemCount: list[index].sublist.length,
shrinkWrap: true,
padding: EdgeInsets.all(5),
scrollDirection: Axis.vertical,
),
],
),
);
},
itemCount: list.length,
shrinkWrap: true,
padding: EdgeInsets.all(5),
scrollDirection: Axis.vertical,
),
)
You can achieve it by adding IconButton to the trailing part of the ExpansionTile.
Here's an example code snippet for the same.
ExpansionTile(
title: const Text('Hello'),
trailing: IconButton(
onPressed: () => log('Hello');
icon: const Icon(Icons.arrow_drop_down),
),
children: const [Text('World')],
),
as of the picture down below, I would like to make listview, where it is possible to add more lines(red) under each listview card.
I have implemented the overall listview(green), with the button that should add a list inside the list. Code is at the bottom
The picture is taken from the Strong app
My design right now is as follows:
Expanded(
// ignore: unnecessary_new
child: new ListView.builder(
itemCount: litems.length,
itemBuilder: (BuildContext ctxt, int Index) {
return Card(
child: Padding(
padding: EdgeInsets.all(10),
child: ExpansionTile(
initiallyExpanded: true,
title: Text(
litems[Index],
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
children: <Widget>[
ElevatedButton(
onPressed: () {
litems.add('hei');
setState(() {});
},
child: const Text('Add Set')),
SizedBox(height: 5),
],
leading: IconButton(
icon: const Icon(
Icons.close,
color: Colors.red,
),
onPressed: () {
litems.removeAt(Index);
setState(() {});
},
),
)));
})),
ElevatedButton(
onPressed: () {
litems.add('hei');
setState(() {});
},
child: const Text('Add Exercises')),
Try my code:
List<List<String>> parent = [];//init Parent
//Parent(Exercises) layout
Column(
children: [
ListView.builder(
itemCount: parent.length,
shrinkWrap: true,
itemBuilder: (context, index) {
return _buildList(parent[index]);
}),
TextButton(
onPressed: () {
parent.add([]);
setState(() {});
},
child: Text("Add Parent"))
],
)
//build children
_buildList(List<String> list) {
return Column(
children: [
ListView.builder(
itemCount: list.length,
shrinkWrap: true,
padding: EdgeInsets.all(0),
physics: const NeverScrollableScrollPhysics(),
itemExtent: 50,
itemBuilder: (context, index) {
return Container(
color: Colors.red.withOpacity((index * 5) / 100),
margin: EdgeInsets.symmetric(vertical: 0),
child: Text('Item'),
);
},
),
TextButton(
onPressed: () {
list.add("value");
setState(() {});
},
child: Text("Add Item"))
],
);
}
In documentation of Hive we have delete method for deleting something from database, but this method don't delete from database and it only do null on index of found data and it cause some problem when we want to listen to database changes or making ListView with null data,
another problem is .values that return non-nullable data and when we try to make a ListView we get null error
late Box<Sal> _sal;
useEffect((){
_sal = Hive.box<Sal>('sal') ;
});
// ...
ValueListenableBuilder(
valueListenable: _sal.listenable(),
builder: (_, Box<Sal> sal, __) => ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
padding: EdgeInsets.zero,
itemBuilder: (context, index) {
return Container(
height: 50.0,
margin: EdgeInsets.symmetric(vertical: 0.0),
child: Card(
color: DefaultColors.$lightBrown,
child: Row(
children: [
CText(
text: _sal.get(index)!.salName,
color: Colors.white,
style: AppTheme.of(context).thinCaption(),
).pOnly(right: 16.0),
const Spacer(),
IconButton(
icon: Icon(
Icons.edit,
color: Colors.yellow,
),
onPressed: () => showGeneralDialog(
//...
),
),
IconButton(
icon: Icon(
Icons.delete,
color: Colors.white,
),
onPressed: () => showGeneralDialog(
//...
),
),
],
),
),
);
},
itemCount: _sal.values.length,
),
).pSymmetric(
h: 16,
),
//...
}
I found solution for this problem
late Box<Sal> _sal;
late List<Sal> _data;
useEffect(() {
_sal = Hive.box<Sal>('sal');
_data = _sal.values.toList();
});
//...
ValueListenableBuilder(
valueListenable: Hive.box<Sal>('sal').listenable(),
builder: (_, Box<Sal> sal, __) {
_data = _sal.values.toList();
return ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
padding: EdgeInsets.zero,
itemBuilder: (context, index) {
return Container(
height: 50.0,
margin: EdgeInsets.symmetric(vertical: 0.0),
);
},
itemCount: _data.length,
);
},
),
//...
I have a simple json parser and listing the news and their categories
now I am trying to do some optimisations on ListTile because I would like to use the news Images bigger and put the news title under but ListTile provide only trailing which it is unusable for me. But I can't add any styling in whole code (new child, Row, etc gives error.) Is it possible to do that in this structure or should I make a customListTile on another page and link the current mechanism to new page?
any help would be really nice
body: Container(
padding: const EdgeInsets.all(
10.0,
),
child: FutureBuilder<Articles>(
future: _futureArticles,
builder: (BuildContext context, AsyncSnapshot<Articles> snapshot) {
if (snapshot.hasData) {
final articles = snapshot.data?.data;
return ListView.builder(
padding: const EdgeInsets.all(
10.0,
),
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: articles!.length,
itemBuilder: (BuildContext context, int index) {
return Card(
elevation: 4.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
child: ListTile(
title: Text(
'Title: ${articles[index].title}',
),
subtitle:
Text('Category: ${articles[index].category?.name}'),
trailing: Image.network(articles[index].imageUrl!),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => NewsViewDetail(
id: articles[index].id!,
),
fullscreenDialog: true,
),
);
},
),
);
},
);
} else if (snapshot.hasError) {
return NewsError(
errorMessage: '${snapshot.hasError}',
);
} else {
return const NewsLoading(
text: 'Loading...',
);
}
},
),
),
);
}
}
Try below answer hope its help to you ,use GridView.builder() instead of ListView.builder()
Container(
padding: EdgeInsets.all(10),
child: GridView.builder(
itemCount: 5,//use your length here(articles!.length)
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 1),
itemBuilder: (context, index) {
return Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.grey.shade200),
),
margin: EdgeInsets.all(5),
padding: EdgeInsets.all(5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
child: Image.network(
'your network image here',
fit: BoxFit.fill,
),
),
SizedBox(
height: 15,
),
Text(
'Your headline here',
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
),
),
],
),
);
},
),
);
your screen look like ->
I have a scrollable list with a FloatingActionButton. I would like to make the list to finish before the FloatingActionButton because the last item of the list isn't visible anymore just like in the Gmail application.
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
backgroundColor: Colors.white,
resizeToAvoidBottomInset: false,
appBar: AppBar(
brightness: Brightness.light,
elevation: 0.0,
backgroundColor: Colors.transparent,
title: Text(
'OnePictura',
style: TextStyle(color: dark, fontSize: 20),
),
actions: [
Padding(
padding: const EdgeInsets.all(8),
child: Container(
decoration:
BoxDecoration(shape: BoxShape.circle, color: textWhite),
child: IconButton(
icon: Image.asset(
'graphics/setting_icon.png',
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => new SettingPage(),
),
);
},
),
),
),
],
),
body: LoadingIndicatorPage(
loading: _loading,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Align(
alignment: Alignment.topLeft,
child: IconButton(
icon: ImageIcon(
AssetImage("graphics/icon_search.png"),
),
onPressed: () {
showSearch(context: context, delegate: DataSearch(albumList, _userId));
},
),
),
xyz(),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () async {
var result = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => new CreateAlbumPage(),
),
);
if (result) {
_getAllAlbum();
setState(() {
albumList.clear();
});
}
},
backgroundColor: Colors.white,
child: Icon(
Icons.add,
color: purpleishBlueTwo,
),
),
);
}
Widget xyz() {
if (albumList.length == 0) {
return Expanded(
child: SmartRefresher(
onRefresh: _onRefresh,
controller: _refreshController,
enablePullDown: true,
enablePullUp: false,
child: Center(
child: Text(_message),
),
),
);
} else {
return Expanded(
child: SmartRefresher(
onRefresh: _onRefresh,
controller: _refreshController,
enablePullDown: true,
enablePullUp: false,
child: GridView.builder(
controller: _scrollController,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: MediaQuery.of(context).size.width /
(MediaQuery.of(context).size.height / 1.5),
),
itemCount: albumList.length,
itemBuilder: (BuildContext context, int index) {
return buildRow(index);
},
),
),
);
}
}
Widget buildRow(int index) {
return Padding(
padding: EdgeInsets.only(top: 10.0, right: 10.0, left: 10.0, bottom: 10.0),
child: GestureDetector(
onTap: () async {
var result = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
new AlbumPage(tabIndex: index, albumList: albumList),
),
);
if (result) {
_getAllAlbum();
_getSubscriptionDetails();
setState(() {
albumList.clear();
});
}
},
child: AlbumTile(
index: index,
currentUser: _userId,
albumList: albumList,
deleteAlbum: _deleteDialog,
),
),
);
}
child: GridView.builder(
controller: _scrollController,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: MediaQuery.of(context).size.width /
(MediaQuery.of(context).size.height / 1.5),
),
itemCount: albumList.length,
itemBuilder: (BuildContext context, int index) {
return buildRow(index);
},
),
to
child: GridView.builder(
controller: _scrollController,
padding: EdgeInsets.only(bottom: 70),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: MediaQuery.of(context).size.width /
(MediaQuery.of(context).size.height / 1.5),
),
itemCount: albumList.length,
itemBuilder: (BuildContext context, int index) {
return buildRow(index);
},
),