Reputation: 461
I created a listview in flutter to display a set of images that are already present in the database as follows:
The photos come correctly from the database, but I added a button to fetch additional pictures from the phone and add them to same listView.
Get the error in the following code:
onTap: () async {
PickedFile pickedFile = await picker.getImage(source: ImageSource.gallery, imageQuality: 50);
setState(() {
if (pickedFile != null) {
filteredUsers.add(pickedFile.path);
}
});
}
The argument type 'String' can't be assigned to the parameter type 'FlowerdataImage'.
Full code:
class _update extends State<UpdateItem> {
@override
void initState() {
super.initState();
GetImageOfTopic().then((value) {
setState(() {
users.addAll(value);
filteredUsers = users;
});
});
}
List<FlowerdataImage> users = List();
List<FlowerdataImage> filteredUsers = List();
List<String> photoPaths = [];
final picker = ImagePicker();
String apiURL;
Future<List<FlowerdataImage>> GetImage() async {
apiURL = '*****************.php';
var response = await http.post(Uri.parse(apiURL));
if (response.statusCode == 200) {
final items = json.decode(response.body).cast<Map<String, dynamic>>();
List<FlowerdataImage> listOfFruits = items.map<FlowerdataImage>((json) {
return FlowerdataImage.fromJson(json);
}).toList();
return listOfFruits;
throw Exception('Failed to load data from Server.');
}
}
@override
Widget build(BuildContext context) {
return new Scaffold(
body: Form(
child: new Center(
child: ListView(
children: <Widget>[
Card(
child: new Column(
children: <Widget>[
Container(
child: Center(
child: Column(
children: <Widget>[
SingleChildScrollView(
child: SizedBox(
child: Column(
children: <Widget>[
Padding(
padding:
EdgeInsets.only(right: 8.0, top: 8.0, ),
child: SizedBox(
height: 140,
child: Row(
children: [
Expanded(
child: Container(
child: ListView.builder(
itemCount: filteredUsers.length,
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContextcontext, int index) {
return InkWell(
child: Padding(
padding: EdgeInsets.only(top: 8.0, bottom: 8.0, left: 8.0, right: 8.0),
child:
Container(
height: 140, width: 140,
child:
ClipRRect(
borderRadius:
BorderRadius.circular(8),
child:
AspectRatio(
aspectRatio:
1.2,
child:
Image.network(
filteredUsers[index].ImageURL.toString(),
width: double.infinity,
height: 400,
fit: BoxFit.cover,
),
),
))),
);
},
),
),
),
Padding(
padding:
const EdgeInsets.only(left: 10, right: 10),
child: Container(
width: 50,
height: MediaQuery.of(
context)
.size
.height,
decoration:
BoxDecoration(
color:
Theme.of(context)
.accentColor,
borderRadius:
BorderRadius
.circular(8),
),
child: Material(
color: CustomColors.Background,
borderRadius:
BorderRadius
.circular(8),
child: InkWell(
borderRadius:
BorderRadius
.circular(
8),
child: Icon(
Icons.add_a_photo,
color: Theme.of(context).floatingActionButtonTheme.foregroundColor,
),
onTap: () async {
PickedFile pickedFile = await picker.getImage(source: ImageSource.gallery, imageQuality: 50);
setState(() {
if (pickedFile != null) {
filteredUsers.add(pickedFile.path);
}
});
}),
)),
)
],
),
),
),
],
),
),
),
],
),
),
),
],
),
),
],
),
)),
);
}
}
class FlowerdataImage {
int id;
String ImageURL;
FlowerdataImage({
this.id,
this.ImageURL,
});
factory FlowerdataImage.fromJson(Map<String, dynamic> json) {
return FlowerdataImage(
id: json['id'],
ImageURL: json['image'].toString(),
);
}
}
I tried to solve the problem for a long time, and it didn't work.
Upvotes: 1
Views: 699
Reputation: 17756
You are trying to add a String
to a collection of FlowerdataImage
. That's not possible.
In your line where you have:
filteredUsers.add(pickedFile.path);
You need to convert the path
to a valid FlowerdataImage
object so you can fit in the List
.
filteredUsers.add(FlowerdataImage(imageURL: pickedFile.path, isLocal: true));
Also update your class to:
class FlowerdataImage {
int id;
bool isLocal;
String ImageURL;
FlowerdataImage({
this.id,
this.ImageURL,
this.isLocal = false,
});
factory FlowerdataImage.fromJson(Map<String, dynamic> json) {
return FlowerdataImage(
id: json['id'],
ImageURL: json['image'].toString(),
);
}
}
And then, on your build
method update to:
filteredUsers[index].isLocal ?
Image.file(File(filteredUsers[index].ImageURL),
width: double.infinity,
height: 400,
fit: BoxFit.cover,
) : Image.network(
filteredUsers[index].ImageURL.toString(),
width: double.infinity,
height: 400,
fit: BoxFit.cover,
),
However, have in mind, that you should have a way to differentiate local assets (the ones picked) from remote (from API) so you can either use Image.network
or Image.file
accordingly.
Upvotes: 2