Adding Json Image to ListTile - flutter

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 ->

Related

Flutter HiveDB deleting from database

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,
);
},
),
//...

Make the ListView.builder() show a fraction of the next (or previous) element

How can Make the ListView.builder() show a fraction of the next (or previous) element.
I have a ListView.builder() and it works fine but I want the user to know that there is a scrolling functionality and that they need to scroll.
How can achieve that?
My output:-
Expected output:-
How can achieve that?
Here is my code
return FutureBuilder(
future: categories,
builder: (BuildContext context, AsyncSnapshot snapshot) {
return ListView.builder(
itemCount: snapshot.data.length,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
return GestureDetector(
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Container(
child: Padding(
padding:
const EdgeInsets.fromLTRB(16.0, 7.0, 16.0, 10.0),
child: Text(
snapshot.data[index].name,
style: TextStyle(
color: Colors.white,
fontSize: 18.0,
fontWeight: FontWeight.bold),
),
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25.0),
color: colors[index],
),
),
),
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Posts(
type: PostsFetchByType.categories,
categoryOrTagIds: [snapshot.data[index].id],
))),
);
});
});
Create a scrollcontroller with an initial offfset:
scrollController = ScrollController(
initialScrollOffset: 10 // put your value here
);
then add it to your ListViewBuilder:
return ListView.builder(
...
controller: scrollController,
...
)
But since you want to show that it is scrollable, you can also have a look at adding scrolling bar by wrapping ListViewBuilder as follows:
Scrollbar(
child: ListView.builder(...),
)

streambuilder not displaying data in list

I'm trying to display a list of employees in my app. Here's the code I got so far:
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(left: 20,top: 20),
child: Container(
height: 40,
width: 120,
decoration: BoxDecoration(
color: Colors.grey.withOpacity(0.12),
borderRadius: BorderRadius.circular(8)),
child: Padding(
padding: const EdgeInsets.all(10),
child: Text("Employees",
style: TextStyle(
fontSize: 22,
color: Colors.black,
fontWeight: FontWeight.w600,
)),
),
),
),
StreamBuilder(
stream: Firestore.instance.collection("Employees").snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(child: Text("Fetching data..."));
} else if(snapshot.connectionState == ConnectionState.done){
return ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(snapshot.data.documents[index]['name']));
},
);
} else {
return Text("hol up");
}
}),
],
);
When I run the app, it just shows 'Employees' and 'hol up' in a column. Why does the list of employees not show?
I solved the issue by simply adding shrinkWrap: true in my listview.
This should work. Also get the data from the indexed document.
ListTile(
title: Text(snapshot.data.documents[index].data['name']));

Flutter: Creating GridView From Firebase Realtime DB items

Currently, in my app's homescreen I have a firebase_animated_list widget which creates a listView. However, I want to show these items in a GridView because it'll look much better.
Here's my code snippet.👇🏼
body: Column(
children: <Widget>[
Flexible(
child: FirebaseAnimatedList(
query: firebaseRef,
itemBuilder: (BuildContext context, DataSnapshot snapshot,
Animation<double> animation, int index) {
return InkWell(
child: ListTile(
contentPadding: EdgeInsets.all(7),
title: Text(mynode[index].key),
leading: CircleAvatar(
radius: 30,
child: FittedBox(
child: Text(mynode[index].id),
),
),
trailing: Icon(Icons.play_arrow),
onTap: () => Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => DemoDb(
id: othernode[index].id,
),
),
),
),
);
},
),
),
],
),
This perfectly creates a list of items but how should I change it to a GridView? I tried using GridView.count in place of ListTile widget. but because it was nested inside the firebase_animated_list , Each grid is layed out inside this animated list.
Is there any plugins or libraries that can help me in this? perhaps a code snippet Or if someone can suggest me any better approach to achieve this, it would mean world to me.
Thank You.
try Using StreamBuilder to load the items in a map and then use a Gridview and then you can populate the Gridview with your data.
have a look at the following Example:
Here we have a model of the data that we're trying to pull from firebase.
class Product {
String key;
String cardid;
String cardname;
String cardimage;
int cardprice;
String carddiscription;
Product(this.key,this.cardid,this.cardname,this.cardimage,this.cardprice,this.carddiscription);
}
and here is how to implement a GridView inside a StreamBuilder and populate it with the data:
return StreamBuilder(
stream: FirebaseDatabase.instance
.reference()
.child("Products")
.onValue,
builder: (BuildContext context, AsyncSnapshot<Event> snapshot) {
if (snapshot.hasData) {
Map<dynamic, dynamic> map = snapshot.data.snapshot.value;
products.clear();
map.forEach((dynamic, v) =>
products.add( new Product(v["key"],v["cardid"] , v["cardname"],v["cardimage"] ,v["cardprice"], v["carddiscription"]))
);
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2),
itemCount: products.length,
padding: EdgeInsets.all(2.0),
itemBuilder: (BuildContext context, int index) {
return GestureDetector(
onTap: (){
},
child: Padding(
padding: EdgeInsets.all(5),
child: Container(
width: (screenWidth(context)/2)-15,
height: 150,
decoration: BoxDecoration(
shape: BoxShape.rectangle,
borderRadius: BorderRadius.all(Radius.circular(15.0)),
image: DecorationImage(
image: NetworkImage(products[index].cardimage),
fit: BoxFit.cover,
),
),
child: Padding(
padding: EdgeInsets.all(0),
child: Container(
decoration: BoxDecoration(
shape: BoxShape.rectangle,
borderRadius: BorderRadius.all(Radius.circular(15.0)),
gradient: new LinearGradient(
colors: [
Colors.black,
const Color(0x19000000),
],
begin: const FractionalOffset(0.0, 1.0),
end: const FractionalOffset(0.0, 0.0),
stops: [0.0, 1.0],
tileMode: TileMode.clamp),
),
child: Padding(
padding: EdgeInsets.all(10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(
products[index].cardname,
style: TextStyle(fontSize: 20, fontWeight: FontWeight.w500,color: Colors.white),
),
Text('Rs. ${products[index].cardprice}'
,
style: TextStyle(fontSize: 20, fontWeight: FontWeight.w200,color: Colors.white),
),
],
),
),
),
), /* add child content here */
),
),
);
},
);
} else {
return CircularProgressIndicator();
}
}),

displaying image from firestorage on ListView.builder

I m using firestore for data and firestorage for files and images, so i m using StreamBuilder to load list as per firestore data and i want to download images as per firestore file name, but its not happening
I tried is, created a new method there I did code to get download url , but it is not working
child: StreamBuilder(
stream: Firestore.instance.collection('data').snapshots(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData)
return Container(
child: Center(child: CircularProgressIndicator()));
return ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (BuildContext context, int index) {
return Card(
child: Column(
children: <Widget>[
Card(
semanticContainer: true,
clipBehavior: Clip.antiAliasWithSaveLayer,
child: Image.network(
imageLoader(snapshot.data.documents[index].data['flie_ref'].toString()),
fit: BoxFit.fill,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0),
),
elevation: 0,
margin: EdgeInsets.all(10),
),
Padding(
padding: EdgeInsets.only(left: 6, right: 6),
child: Card(
elevation: 0,
child: ExpansionTile(
leading: CircleAvatar(
child: Text(snapshot
.data.documents[index].data['amount']
.toString()),
),
title: Text(
snapshot
.data.documents[index].data['desc']
.toString(),
overflow: TextOverflow.ellipsis,
),
children: <Widget>[
Text(snapshot
.data.documents[index].data['desc']
.toString()),
SizedBox(
height: 10,
),
],
),
),
),
],
),
);
});
},
),
Future imageLoader(String string) async {
var url =
await FirebaseStorage.instance.ref().child(string).getDownloadURL();
setState(() {
return url;
});
}
I expect output load respective image but the output is Error: The argument type 'Future' can't be assigned to the parameter type 'Widget'