Insert an image StaggeredGridView that is upload by the user !! The argument type 'File' can't be assigned to the parameter type 'String' - string

I want to create a StaggeredGridView and fill it with images that the user uploads. The problem is that the type of StaggeredGridView is String or ImageProvider<Object> and the file is PickedFile or File
What is the solution ??
class GalleryClassOneState extends State<GalleryClassOne> {
List<File> arrayImage = [];
File sampleImage;
final _picker = ImagePicker();
// #override
// void initState() {
// super.initState();
// DatabaseReference images =
// FirebaseDatabase.instance.reference().child("NeuralNetwork");
// }
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Galeria clase 1'),
),
body: Container(padding: EdgeInsets.all(8), child: galeria(arrayImage)),
floatingActionButton: FloatingActionButton(
onPressed: _optionsDialogBox,
tooltip: 'Pick Image',
child: Icon(Icons.add_outlined),
),
);
}
Widget galeria(List<File> arrayImage) {
return StaggeredGridView.countBuilder(
crossAxisCount: 4,
itemCount: 11,
itemBuilder: (BuildContext context, int index) {
return ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Container(
color: Colors.deepPurple,
child: Column(
children: <Widget>[
Image.network(arrayImage[index])
],
),
),
);
},
// staggeredTileBuilder: (int index) => new StaggeredTile.fit(1),
staggeredTileBuilder: (int index) =>
new StaggeredTile.count(2, index.isEven ? 2 : 1),
mainAxisSpacing: 10.0,
crossAxisSpacing: 10.0,
);
}
}

We will need to work with the images as bytes instead of files. First, make arrayImage a List<Uint8List>. Here we will store a list of the byte arrays representing an image loaded in memory. Update the galeria() method to accept a List<Uint8List> as well.
Now in the optionsDialogBox() method, we will use the results of the _picker like so:
_picker.getImage(source: ImageSource.gallery).then((pickedFile) {
// read the bytes from the PickedFile
pickedFile.readAsBytes().then((bytes) {
// add the image as bytes to the arrayImage list and update the UI
setState(() => arrayImage.add(bytes));
});
});
When we create our Image widget, we will use the Image.memory() constructor passing to it the bytes representing our image.
Image.memory(arrayImage[index])

Related

Blank Screen when fetching data from api

I am fetching a data from api and display it in list using ListView builder, it's working properly on emulator but when I run app on my android phone it is displaying blank screen, here it looks.
below Leave History label, I am displaying data from api, but it looks like this now.
It looks like this on emulator
Here is the code:
Fetching api data and inserting it into list
List<leaveHistory> historyList = [];
var loader = 0;
Future<List<leaveHistory>> _getRecord() async {
Dio dio = new Dio();
var data = {
'username': getname,
'token': getaccesstoken,
};
return dio
.post(localhostUrlLeaveHistoryON, data: json.encode(data))
.then((onResponse) async {
Map<String, dynamic> map = onResponse.data;
List<dynamic> data = map["data"];
for (var historyData in data) {
leaveHistory history = leaveHistory(
historyData["Date"],
historyData["description"],
historyData["type"],
historyData['fromdate'],
historyData["todate"],
historyData["noofleavedays"],
historyData["leave"]);
historyList.add(history);
loader = 0;
}
if (historyList.length == 0) {
loader = 1;
}
return historyList;
}).catchError((onerror) {
loader = 1;
print(onerror.toString());
});
}
display the data using ListView.builder
Widget build(BuildContext context) {
return Scaffold(
appBar: new MyAppBar(
title: Text("Leaves Tracker"),
onpressed: () {
Navigator.push(
context, MaterialPageRoute(builder: (context) => Profile()));
}),
drawer: NavigationDrawerWidget(),
body: Stack(overflow: Overflow.visible, children: <Widget>[
Container(
padding: EdgeInsets.fromLTRB(20, 10, 0, 0),
child: Text(
"Leave History",
style: TextStyle(fontSize: 30, fontFamily: 'RaleWay'),
),
),
Container(
padding: EdgeInsets.fromLTRB(10, 30, 0, 0),
child: FutureBuilder(
future: _getRecord(),
builder: (BuildContext context,
AsyncSnapshot<List<leaveHistory>> snapshot) {
if (snapshot.hasData) {
if (historyList.length != 0) {
return Container(
padding: EdgeInsets.fromLTRB(0, 30, 0, 0),
child: Expanded(
child: ListView.builder(
itemCount: snapshot.data.length,
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
Color c = Colors.red;
//changing the avatar color
if (i == 0)
i++;
else if (i == 1) {
c = Colors.blue;
i++;
} else if (i == 2) {
c = Color(int.parse(annualboxcolor));
i = 0;
}
Color c1 = Colors.green;
if (snapshot.data[index].Status == "Approved") {
c1 = Colors.green;
} else if (snapshot.data[index].Status ==
"Not Approved") {
c1 = Colors.red;
} else if (snapshot.data[index].Status ==
"Pending") {
c1 = Color(int.parse(pendingrequestcolor));
}
return SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: [
ListTile(
leading: CircleAvatar(
radius: 25,
backgroundColor: c,
child: Container(
padding: EdgeInsets.fromLTRB(
0, 10, 0, 0),
child:
Column(children: <Widget>[
Text(
snapshot
.data[index].noofdays
.toString(),
style: TextStyle(
fontSize: 15.0,
fontWeight:
FontWeight.bold,
color: Colors.white),
),
Text(
int.parse(snapshot
.data[index]
.noofdays) >
1
? "Days"
: "Day",
style: TextStyle(
fontSize: 10.0,
color: Colors.white),
)
]),
)),
title:
Text(snapshot.data[index].type),
isThreeLine: true,
subtitle: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
snapshot.data[index].fromdate +
" To " +
snapshot.data[index].todate,
),
Text(snapshot.data[index].Status,
style: TextStyle(
color: c1,
fontWeight:
FontWeight.bold)),
Text(
snapshot
.data[index].description,
)
],
)),
Divider(
color: Colors.grey,
height: 10,
),
],
));
},
)));
}
}
if (loader == 1) {
print("run");
return Nodatafound();
} else {
return Center(
child: CircularProgressIndicator(
color: Colors.blue[500],
));
}
}),
),
]));
}
}
history class
class leaveHistory {
final String date;
final String fromdate;
final String todate;
final String description;
final String type;
final String Status;
final String noofdays;
leaveHistory(this.date, this.description, this.type, this.fromdate,
this.todate, this.noofdays, this.Status);
}
When i redirect to this screen from drawer it first display this error
DioError [DioErrorType.response]: Http status error [300]
on this catchError this line print(onerror.toString());
Update:
When i connect my phone with my laptop with datacable, it's working fine, but when i install apk problem occurs.
Please help where i am doing wrong.
If #Huthaifa was not the answer you're looking, have you tried to update the value of: localhostUrlLeaveHistoryON?
If you're using something like: http://localhost
Please try to change this to your computer's ip address.
Your error is caused by incorrect use of parent data widget. And that is from using expanded inside container. Remove your Expanded from here:
return Container(
padding: EdgeInsets.fromLTRB(0, 30, 0, 0),
child: Expanded(
child: ListView.builder(
You will also notice that the error in console is gone. Always read the errors and understand them. The error will 100% say, incorrect use of parent widget. Just remove the expanded.

flutter listview with radio not showing in alertDialog

This is the code.
code:
class ThemeChangerWidget extends StatelessWidget {
final List<String> string = ['Light', 'Dark', 'Amoled'];
#override
Widget build(BuildContext context) {
final stateData = Provider.of<ThemeNotifier>(context);
final ThemeData state = stateData.getTheme();
return Theme(
data: state.copyWith(unselectedWidgetColor: state.accentColor),
child: AlertDialog(
backgroundColor: state.primaryColor,
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
title: Text('Select Theme', style: state.textTheme.body1),
content: ListView.builder(
shrinkWrap: true,
itemBuilder: (context, index) {
return RadioListTile(
value: index,
groupValue: themes.indexOf(state),
onChanged: (ind) {
onThemeChanged(ind, stateData);
},
title: Text(
string[index],
style: state.textTheme.body2,
),
);
},
itemCount: string.length,
)),
);
}
}'
errors-The following assertion was thrown during performLayout():
RenderShrinkWrappingViewport does not support returning intrinsic dimensions.
some times throw this error instead of above LayoutBuilder does not support returning intrinsic dimensions.
Calculating the intrinsic dimensions would require instantiating every child of the viewport, which defeats the point of viewports being lazy.
If you are merely trying to shrink-wrap the viewport in the main axis direction, you should be able to achieve that effect by just giving the viewport loose constraints, without needing to measure its intrinsic dimensions.
AlertDialog uses an IntrinsicWidth widget that doesn't allow ListView.builder. You have to give a specific width to your ListView Example:
return AlertDialog(
title: Text('Dialog'),
content: SizedBox(
width: double.maxFinite,
child: ListView(
children: <Widget>[
//Your content here
],
),
),
);

How to achieve coplanar card layout in flutter

I'm trying to achieve a coplanar/disallined card collection layout in flutter. This is on Card layout on material Design documentation https://imgur.com/miHhpFs
I''ve tried with a GridView.count layout, but can't figure out how to disalline items. I also found out that there are user created libraries like this https://pub.dev/packages/flutter_staggered_grid_view that can help with what I want to do, but I'd prefer an official solution since this layout is on the material design documentation.
I don't know what the "official solution" for creating this is, but I believe it would be something along the lines of "Create three list views with three scroll controllers, one of which is offset from the other two, and then sync up their scroll controllers, accounting for the offset."
I didn't know if this would work or not, so I created this dartpad in order to test it:
https://dartpad.dev/f9c8f00b78899d3c8c4a426d3466a8a3
Just in case the dartpad doesn't work, here is the code that I used:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: ScrollSync(),
);
}
}
class ScrollSync extends StatefulWidget {
#override
_ScrollSyncState createState() => _ScrollSyncState();
}
class _ScrollSyncState extends State<ScrollSync> {
CustomScrollController _controller1 =
CustomScrollController(keepScrollOffset: true);
CustomScrollController _controller2 = CustomScrollController(
initialScrollOffset: 150.0, keepScrollOffset: true);
CustomScrollController _controller3 =
CustomScrollController(keepScrollOffset: true);
#override
void initState() {
_controller1.addListener(() =>
_controller2.jumpToWithoutGoingIdleAndKeepingBallistic(
_controller1.offset, "1 listen 2"));
_controller1.addListener(() =>
_controller3.jumpToWithoutGoingIdleAndKeepingBallistic(
_controller1.offset, "1 listen 3"));
_controller2.addListener(() =>
_controller1.jumpToWithoutGoingIdleAndKeepingBallistic(
_controller2.offset, "2 listen 1"));
_controller2.addListener(() =>
_controller3.jumpToWithoutGoingIdleAndKeepingBallistic(
_controller2.offset, "2 listen 3"));
_controller3.addListener(() =>
_controller1.jumpToWithoutGoingIdleAndKeepingBallistic(
_controller3.offset, "3 listen 1"));
_controller3.addListener(() =>
_controller2.jumpToWithoutGoingIdleAndKeepingBallistic(
_controller3.offset, "3 listen 2"));
super.initState();
}
#override
void dispose() {
_controller1.dispose();
_controller2.dispose();
_controller3.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Scroll Sync"),
),
body: Row(
children: [
Flexible(
flex: 1,
child: ListView.builder(
controller: _controller1,
scrollDirection: Axis.vertical,
itemBuilder: (_, index) => Container(
color: Colors.blueGrey,
width: 150,
height: 300,
margin: EdgeInsets.all(10.0),
child: Center(
child: Text(
"$index",
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.display2,
),
),
),
),
),
Flexible(
flex: 1,
child: ListView.builder(
controller: _controller2,
itemBuilder: (_, index) => Container(
height: 300,
color: Colors.blueGrey,
margin: EdgeInsets.all(10.0),
child: Center(
child: Text(
"$index",
style: Theme.of(context)
.textTheme
.display2
.copyWith(color: Colors.white),
),
),
),
),
),
Flexible(
flex: 1,
child: ListView.builder(
controller: _controller3,
itemBuilder: (_, index) => Container(
height: 300,
color: Colors.blueGrey,
margin: EdgeInsets.all(10.0),
child: Center(
child: Text(
"$index",
style: Theme.of(context)
.textTheme
.display2
.copyWith(color: Colors.black),
),
),
),
),
),
],
),
);
}
}
class CustomScrollController extends ScrollController {
CustomScrollController(
{double initialScrollOffset = 0.0,
keepScrollOffset = true,
debugLabel,
String controller})
: super(
initialScrollOffset: initialScrollOffset,
keepScrollOffset: keepScrollOffset,
debugLabel: debugLabel,
);
#override
_SilentScrollPosition createScrollPosition(
ScrollPhysics physics,
ScrollContext context,
ScrollPosition oldPosition,
) {
return _SilentScrollPosition(
physics: physics,
context: context,
oldPosition: oldPosition,
initialPixels: initialScrollOffset,
);
}
void jumpToWithoutGoingIdleAndKeepingBallistic(
double value, String controller) {
assert(positions.isNotEmpty, 'ScrollController not attached.');
for (_SilentScrollPosition position
in new List<ScrollPosition>.from(positions))
position.jumpToWithoutGoingIdleAndKeepingBallistic(value, controller);
}
}
class _SilentScrollPosition extends ScrollPositionWithSingleContext {
_SilentScrollPosition({
ScrollPhysics physics,
ScrollContext context,
ScrollPosition oldPosition,
double initialPixels,
}) : super(
physics: physics,
context: context,
oldPosition: oldPosition,
initialPixels: initialPixels,
);
void jumpToWithoutGoingIdleAndKeepingBallistic(
double value, String controller) {
print(controller);
print(value);
print(pixels);
if (controller[0] == "2") {
if (pixels + 150.0 != value) {
forcePixels(value - 150.0);
}
} else if (controller[9] == "2") {
if (pixels - 150.0 != value) {
forcePixels(value + 150.0);
}
} else if (pixels != value) {
forcePixels(value);
}
}
}

Visibility won't toggle in flutter?

I've got a gridView where each grid has a FlatButton inside it. The button is supposed to trigger the visibility for another button I have outside the GridView. I've set the state in onPressed to change the bool showCard for everytime the GridView button is pressed. In my print statement, it's saying that it's working, producing true and false each time the button is pressed, but it's not changing the visibility of the other button called 'CheckoutCard()'. Can anyone help me?
import 'package:flutter/material.dart';
import 'package:flutter/painting.dart';
import 'package:bee/Cards/Items%20Card.dart';
import 'package:bee/Constants/Constants.dart';
import 'package:bee/MerchantCategories/My Categories.dart';
import 'package:bee/MenuButtons/Color Changer.dart';
import 'package:bee/Cards/Checkout Card.dart';
import 'package:bee/main.dart';
import 'Basket Menu.dart';
class MyMenu extends StatefulWidget {
#override
_MyMenuState createState() => _MyMenuState();
}
class _MyMenuState extends State<MyMenu> {
// bool showCard = _MyButtonState().showCard;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
brightness: Brightness.light,
leading: new IconButton(
icon: new Icon(Icons.arrow_back, color: Colors.black),
onPressed: () { Navigator.of(context).pop();},
),
backgroundColor: Colors.white,
title: Padding(
padding: const EdgeInsets.all(6.0),
child: Image(image: AssetImage('images/Merchants/My_Image.png'),),
),
elevation: 1.0,
centerTitle: true,
actions: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 15.0),
child: IconButton(icon: Icon(Icons.shopping_basket, color: Colors.blue[800],),
onPressed: (){ Navigator.push(context, MaterialPageRoute(builder: (context){return BasketMenu();})); }
),
),
],
),
body: Stack(
children: <Widget>[
Flex(
direction: Axis.vertical,
children: <Widget>[
Expanded(
flex: 1,
child: Padding(
padding: const EdgeInsets.all(5.0),
child: Container(
child: ListView(children: <Widget>[
MyCategories(categoryText: Text('Restaurants', style: categoryTextStyle),),
MyCategories(categoryText: Text('Bars', style: categoryTextStyle),),
MyCategories(categoryText: Text('Games', style: categoryTextStyle),),
],
scrollDirection: Axis.horizontal,
),
),
),
),
Expanded(
flex: 10,
child: Container(
child: GridView.count(
crossAxisCount: 2,
children: <Widget>[
ItemsCard(
categoryName: Text('Fast Food', style: secondCategoryTextStyle,),
itemText: FastFoodText,
priceText: Text('£21.67', style: priceTextStyle,),
gridOutline: MyButton(
tile: GridTile(
child: FastFoodImage,
),
),
),
ItemsCard(
itemText: SnubbText,
priceText: Text('£44.95', style: priceTextStyle,),
gridOutline: MyButton(
tile: GridTile(
child: SnubbImage,
),
),
),
ItemsCard(
itemText: FreshText,
priceText: Text('£41.23', style: priceTextStyle,),
gridOutline: MyButton(
tile: GridTile(
child: FreshImage,
),
),
),
Container(),
],
),
),
),
],
),
Visibility(visible: _MyButtonState().showCard ? _MyButtonState().showCard : !_MyButtonState().showCard, child: CheckoutCard()),
],
),
);
}
}
class MyButton extends StatefulWidget {
#override
State<StatefulWidget> createState(){
return _MyButtonState();
}
MyButton({this.tile});
final GridTile tile;
bool isVisible = false;
int itemNumber = 0;
bool showCheckoutCard(){
return isVisible = !isVisible;
}
int itemCounter(){
return itemNumber++;
}
}
class _MyButtonState extends State<MyButton> {
bool changeColor = false;
static var myNewButtonClass = MyButton();
bool showCard = myNewButtonClass.isVisible;
#override
Widget build(BuildContext context) {
return FlatButton(
shape: Border(bottom: BorderSide(color: changeColor ? Colors.blue[800] : Colors.transparent, width: 3.0)),
child: widget.tile,
onPressed: (){
setState(() {
changeColor = !changeColor;
myNewButtonClass.itemCounter();
print(myNewButtonClass.itemCounter());
setState(() {
showCard = !showCard;
print(showCard);
});
});
},
);
}
}
You are calling the setState method inside your Button. I don't think it will change the state of your MyMenu widget. I would suggest you to change your Button as following:
class MyButton extends StatelessWidget {
final Color color;
final GridTile tile;
final VoidCallback onPressed;
const MyButton({Key key, this.color, this.tile, this.onPressed})
: super(key: key);
#override
Widget build(BuildContext context) {
return FlatButton(
shape: Border(bottom: BorderSide(color: color)),
child: tile,
onPressed: onPressed,
);
}
}
After that, you need to declare two variable in your MyMenu widget as follows:
class _MyMenuState extends State<MyMenu> {
bool changeColor = false;
bool showCard = false;
#override
Widget build(BuildContext context) {
yourBuildMethod()
In your MyMenu widget you can call button like this:
MyButton(
tile: GridTile(child: SnubbImage),
color: changeColor
? Colors.blue[800]
: Colors.transparent,
onPressed: () {
setState(() {
changeColor = !changeColor;
showCard = !showCard;
});
},
),
And now check your Visibility like this:
Visibility(
visible: showCard,
child: CheckoutCard(),
)
Now your variables are in your MyMenu widget and you are calling setState function in MyMenu widget. So it will be able to update the state of your widget. I hope this will be helpful for you.
To trigger a rebuild of your view based when changing the value of a variable you need to use setState.
Where you are are changing the value of the isVisible variable, you need to surround it with a setState:
setState(() {
isVisible = !isVisible;
});

How to create a simple google maps address search with autocomplete in flutter and get latitude and longitude?

I'm new at Flutter and I'm trying to build a simple google maps app. I've already implemented google maps to the app and it is running perfect.
But now I want to add google maps autocomplete and I can't find a simple tutorial or example that is focused on it.
I have a TextField and I want to show places and addresses below it according to what the user types.
After showing the results, I need to get its latitude and longitude to mark on the map. The code below represents my BottomSheet, that contains my TexField and need to implement some list below it after some written text.
void _settingModalBottomSheet(context) {
double statusBarHeight = MediaQuery.of(context).padding.top;
showModalBottomSheet(
context: context,
builder: (builder) {
return Container(
padding: EdgeInsets.only(top: statusBarHeight),
color: Colors.transparent,
child: Container(
height: MediaQuery.of(context).size.height,
decoration: BoxDecoration(
color: Colors.blueAccent,
borderRadius: BorderRadius.only(
topLeft: const Radius.circular(10.0), topRight: const Radius.circular(10.0))),
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 8.0, left: 8.0, right: 8.0),
child: Container(
height: 50.0,
width: double.infinity,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.0),
color: Colors.white
),
child: TextField(
textInputAction: TextInputAction.search,
decoration: InputDecoration(
hintText: "Para onde vamos?",
border: InputBorder.none,
contentPadding: EdgeInsets.only(left: 15.0, top: 15.0),
suffixIcon: IconButton(
icon: Icon(Icons.search),
onPressed: searchAndNavigate,
iconSize: 30.0,
)
),
onChanged: (val) {
setState(() {
searchAddr = val;
}
);
},
onSubmitted: (term) {
searchAndNavigate();
},
),
),
),
],
)
),
);
}
);
}
You can use flutter_google_places plugin which shows the places in the autocomplete list as you type it and also returns lat and long of the place/address selected.
===== Working code =======
Add flutter_google_places plugin and import it in your dart file.
Add geo_coder plugin and import it in same dart file. (Required to access geocoding services)
Generate google api key for your project.
main.dart:
void main() => runApp(MyApp());
const kGoogleApiKey = "Api_key";
GoogleMapsPlaces _places = GoogleMapsPlaces(apiKey: kGoogleApiKey);
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: demo(),
),
);
}
}
class demo extends StatefulWidget {
#override
demoState createState() => new demoState();
}
class demoState extends State<demo> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
alignment: Alignment.center,
child: RaisedButton(
onPressed: () async {
// show input autocomplete with selected mode
// then get the Prediction selected
Prediction p = await PlacesAutocomplete.show(
context: context, apiKey: kGoogleApiKey);
displayPrediction(p);
},
child: Text('Find address'),
)
)
);
}
Future<Null> displayPrediction(Prediction p) async {
if (p != null) {
PlacesDetailsResponse detail =
await _places.getDetailsByPlaceId(p.placeId);
var placeId = p.placeId;
double lat = detail.result.geometry.location.lat;
double lng = detail.result.geometry.location.lng;
var address = await Geocoder.local.findAddressesFromQuery(p.description);
print(lat);
print(lng);
}
}
}
Result:
When you tap on Find Address button, it opens new screen with built-in search app bar in which you can type address / place you are looking for which shows corresponding results in autocomplete list and prints lat and long of the place you selected.
lat: 52.3679843
lng: 4.9035614

Resources