Related
So i added the files in flutter and also correctly added them under assets in the pubspec.yaml file, the names are also correct and it does not give me any errors but the images still don't show.
I added some other images in other screens and they seem to work just fine.
The logo.png is also shown in another screen with no issue but not on this screen.
Essentially the code creates two input fields and a button for a register screen and below that 3 bubbles with the facebook icon, google icon and twitter icon. It should also have the app logo above the input fields but nothing is showing.
Another question i wanted to ask is how would i change the background colour to black in a screen like this? Do i wrap the container with a scaffold?
class RegisterScreenMain extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Scaffold(
body: Body(),
),
);
}
}
class Body extends StatelessWidget {
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Column(children: <Widget>[
Text(
"Sign Up",
style: TextStyle(fontWeight: FontWeight.bold, color: Colors.white),
),
Image.asset(
"lib/assets/images/logo.png",
height: size.height * 0.35,
),
RoundedInputField(
hintText: "Your Email",
onChanged: (value) {},
),
RoundedPasswordField(
onChanged: (value) {},
),
roundedButton(
text: "Register",
press: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return UserRegisterPreferences();
}),
);
},
),
AlreadyHaveAnAccountCheck(
login: false,
press: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return LoginScreenMain();
}),
);
},
),
OrDivider(),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SocialIcon(
iconSrc: "lib/assets/images/facebook.png",
press: () {},
),
SocialIcon(
iconSrc: "lib/assets/images/twittter.png",
press: () {},
),
SocialIcon(
iconSrc: "lib/assets/images/google.png",
press: () {},
),
],
)
]);
}
}
To load image
Stop debugging app -> run flutter clean -> run flutter pub get -> uninstall app -> Start debug again
Add following line to you scaffod widget-
backgroundColor: Colors.red,
Prabanshu's answer is correct on your problem. But for the latter part of your problem, in which you asked how to change the color of the background to black, try to wrap the column of your custom body widget in a scaffold. Then you will be able to change the background color.
This will work
class RegisterScreenMain extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Scaffold(
body: Body(),
),
);
}
}
class Body extends StatelessWidget {
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Scaffold(
body: Column(children: <Widget>[
Text(
"Sign Up",
style: TextStyle(fontWeight: FontWeight.bold, color: Colors.white),
),
Image.asset(
"lib/assets/images/logo.png",
height: size.height * 0.35,
),
RoundedInputField(
hintText: "Your Email",
onChanged: (value) {},
),
RoundedPasswordField(
onChanged: (value) {},
),
roundedButton(
text: "Register",
press: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return UserRegisterPreferences();
}),
);
},
),
AlreadyHaveAnAccountCheck(
login: false,
press: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return LoginScreenMain();
}),
);
},
),
OrDivider(),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SocialIcon(
iconSrc: "lib/assets/images/facebook.png",
press: () {},
),
SocialIcon(
iconSrc: "lib/assets/images/twittter.png",
press: () {},
),
SocialIcon(
iconSrc: "lib/assets/images/google.png",
press: () {},
),
],
)
]);
backgroundColor: Colors.black,
)
}
}
Is there a way to merge dynamically loaded image file to one image file in flutter?
I have added the image.
I needed to merge the loaded image to one image the code I have used is given below
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image/image.dart' as immg;
import 'package:image_cropper/image_cropper.dart';
import 'package:image_picker/image_picker.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:merge_images/merge_images.dart';
class SingleImageUpload extends StatefulWidget {
#override
_SingleImageUploadState createState() {
return _SingleImageUploadState();
}
}
class _SingleImageUploadState extends State<SingleImageUpload> {
List<Object> images = List<Object>();
List<File> imgList = List<File>();
List<Image> listimg = List<Image>();
File _selectedFile;
bool _inProcess = false;
Map data = {};
Readerservice _readerservice;
#override
void initState() {
// TODO: implement initState
super.initState();
setState(() {
images.add("Add Image");
images.add("Add Image");
images.add("Add Image");
images.add("Add Image");
});
}
#override
Widget build(BuildContext context) {
return new MaterialApp(
debugShowCheckedModeBanner: false,
home: new Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
leading: Padding(
padding: EdgeInsets.only(left: 12),
child: IconButton(
icon: Icon(Icons.arrow_back_ios,
color: Colors.black,
size: 30,),
onPressed: () {
Navigator.pushNamed(context, '/Mainpage');
},
),
),
title: Row(
mainAxisAlignment: MainAxisAlignment.center,
children:<Widget>[
Text('Basic AppBar'),
]
),
actions: <Widget>[
IconButton(
icon: Icon(Icons.more_vert,
color: Colors.black,
size: 30,),
onPressed: () {
print('Click start');
},
),
],
),
body:
SizedBox(height: 40),
Expanded(
child: buildGridView(),
),
RaisedButton(
textColor: Colors.white,
color: Colors.orange,
child: Text("Finish",
style: TextStyle(fontSize: 15),),
onPressed: () {
pasimage();
},
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(8.0),
),
),
],
),
),
);
}
Widget buildGridView() {
return GridView.count(
shrinkWrap: true,
crossAxisCount: 3,
childAspectRatio: 1,
children: List.generate(images.length, (index) {
if (images[index] is ImageUploadModel) {
ImageUploadModel uploadModel = images[index];
return Card(
clipBehavior: Clip.antiAlias,
child: Stack(
children: <Widget>[
Image.file(
uploadModel.imageFile,
width: 300,
height: 300,
),
Positioned(
right: 5,
top: 5,
child: InkWell(
child: Icon(
Icons.remove_circle,
size: 20,
color: Colors.red,
),
onTap: () {
setState(() {
images.replaceRange(index, index + 1, ['Add Image']);
});
},
),
),
],
),
);
} else {
return Card(
child: IconButton(
icon: Icon(Icons.add),
onPressed: () {
//popup
showDialog(
context: context,
builder: (context) {
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10)),
elevation: 16,
child: Container(
height: 180.0,
width: 330.0,
child: ListView(
children: <Widget>[
SizedBox(height: 20),
//Center(
Padding(
padding: const EdgeInsets.only(left: 15.0),
child: Text(
"Add a Receipt",
textAlign: TextAlign.left,
style: TextStyle(
fontSize: 24,
color: Colors.black,
fontWeight: FontWeight.bold),
),
),
// ),
SizedBox(height: 20),
FlatButton(
child: Text(
'Take a photo..',
textAlign: TextAlign.left,
style: TextStyle(fontSize: 20),
),
onPressed: () {
_onAddImageClick(index,ImageSource.camera);
Navigator.of(context).pop();
// picker.getImage(ImageSource.camera);
},
textColor: Colors.black,
),
FlatButton(
child: Text(
'Choose from Library..',
style: TextStyle(fontSize: 20),
textAlign: TextAlign.left,
),
onPressed: () {
_onAddImageClick(index,ImageSource.gallery);
Navigator.of(context).pop();
},
textColor: Colors.black,
),
],
),
),
);
},
);
//pop ends
//_onAddImageClick(index);
},
),
);
}
}),
);
}
Future _onAddImageClick(int index, ImageSource source ) async {
setState(() {
_inProcess = true;
});
File image = await ImagePicker.pickImage(source: source);
if(image != null){
File cropped = await ImageCropper.cropImage(
sourcePath: image.path,
maxWidth: 1080,
maxHeight: 1080,
compressFormat: ImageCompressFormat.jpg,
androidUiSettings: AndroidUiSettings(
toolbarColor: Colors.black,
toolbarWidgetColor: Colors.white,
//toolbarTitle: "RPS Cropper",
statusBarColor: Colors.deepOrange.shade900,
backgroundColor: Colors.black,
initAspectRatio: CropAspectRatioPreset.original,
lockAspectRatio: false
),
iosUiSettings: IOSUiSettings(
minimumAspectRatio: 1.0,
)
);
this.setState((){
_selectedFile = cropped ;
_inProcess = false;
});
} else {
this.setState((){
_inProcess = false;
});
}
getFileImage(index);
}
void getFileImage(int index) async {
// var dir = await path_provider.getTemporaryDirectory();
setState(() {
ImageUploadModel imageUpload = new ImageUploadModel();
imageUpload.isUploaded = false;
imageUpload.uploading = false;
imageUpload.imageFile = _selectedFile ;
imageUpload.imageUrl = '';
imgList.add(imageUpload.imageFile);
images.replaceRange(index, index + 1, [imageUpload]);
print(imgList);
});
}
void pasimage(){
for(var i=0;i<imgList.length;i++){
final imaes = immg.decodeImage(imgList[i].readAsBytesSync()) as Image;
listimg.add(imaes);
}
Navigator.pushReplacementNamed(context, '/crop',arguments: {
'imageList':ImagesMerge(
listimg,///required,images list
direction: Axis.vertical,///direction
backgroundColor: Colors.black26,///background color
fit: false,///scale image to fit others
//controller: captureController,///controller to get screen shot
),
});
}
}
class ImageUploadModel {
bool isUploaded;
bool uploading;
File imageFile;
String imageUrl;
ImageUploadModel({
this.isUploaded,
this.uploading,
this.imageFile,
this.imageUrl,
});
}
I have used image merge package from pub.dev I have implemented it in pasimage() function but I got the error.
** The argument type 'List (where Image is defined in C:\src\flutter\packages\flutter\lib\src\widgets\image.dart)' can't be assigned to the parameter type 'List (where Image is defined in C:\src\flutter\bin\cache\pkg\sky_engine\lib\ui\painting.dart)'. **
the error image is attached
import 'dart:ui' as ui;
List<ui.Image> listimg = List<ui.Image>();
...
void pasimage(){
for(var i=0;i<imgList.length;i++){
final imaes = await ImagesMergeHelper.loadImageFromFile(imgList[i]) as ui.Image;
listimg.add(imaes);
}
Navigator.pushReplacementNamed(context, '/crop',arguments: {
'imageList':ImagesMerge(
listimg,///required,images list
direction: Axis.vertical,///direction
backgroundColor: Colors.black26,///background color
fit: false,///scale image to fit others
//controller: captureController,///controller to get screen shot
),
});
}
Try this code.
I am implementing a custom radio button with validation and values are passed in those buttons. There is a run time error which i am not able to figure out. I am getting the following error
The following assertion was thrown during performLayout():
I/flutter (10799): An InputDecorator, which is typically created by a TextField, cannot have an unbounded width.
I/flutter (10799): This happens when the parent widget does not provide a finite width constraint. For example, if the
I/flutter (10799): InputDecorator is contained by a Row, then its width must be constrained. An Expanded widget or a
I/flutter (10799): SizedBox can be used to constrain the width of the InputDecorator or the TextField that contains it.
I/flutter (10799): 'package:flutter/src/material/input_decorator.dart':
I/flutter (10799): Failed assertion: line 945 pos 7: 'layoutConstraints.maxWidth < double.infinity'
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter FormBuilder Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
inputDecorationTheme: InputDecorationTheme(
labelStyle: TextStyle(color: Colors.purple),
),
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
MyHomePageState createState() {
return MyHomePageState();
}
}
class MyHomePageState extends State<MyHomePage> {
var data;
bool autoValidate = true;
bool readOnly = false;
bool showSegmentedControl = true;
final GlobalKey<FormBuilderState> _fbKey = GlobalKey<FormBuilderState>();
final GlobalKey<FormFieldState> _specifyTextFieldKey =
GlobalKey<FormFieldState>();
ValueChanged _onChanged = (val) => print(val);
// var genderOptions = ['Male', 'Female', 'Other'];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("FormBuilder Example"),
),
body: Padding(
padding: EdgeInsets.all(10),
child: SingleChildScrollView(
child: Row(
children: <Widget>[
FormBuilder(
// context,
key: _fbKey,
autovalidate: true,
//initialValue: {
// 'movie_rating': 5,
// },
readOnly: false,
child: Row(
children: <Widget>[
FormBuilderRadio(
decoration:
InputDecoration(labelText: 'My chosen language'),
attribute: "best_language",
leadingInput: true,
onChanged: _onChanged,
validators: [FormBuilderValidators.required()],
options:
["Delete", "Approve", "Revert"]
.map((lang) => FormBuilderFieldOption(
value: lang,
child: Text('$lang'),
))
.toList(growable: false),
),
],
),
),
Row(
children: <Widget>[
Expanded(
child: MaterialButton(
color: Theme.of(context).accentColor,
child: Text(
"Submit",
style: TextStyle(color: Colors.white),
),
onPressed: () {
if (_fbKey.currentState.saveAndValidate()) {
print(_fbKey.currentState.value);
} else {
print(_fbKey.currentState.value);
print("validation failed");
}
},
),
),
SizedBox(
width: 20,
),
Expanded(
child: MaterialButton(
color: Theme.of(context).accentColor,
child: Text(
"Reset",
style: TextStyle(color: Colors.white),
),
onPressed: () {
_fbKey.currentState.reset();
},
),
),
],
),
],
),
),
),
);
}
}
void changeIndex() {
setState(() {
selectedIndex = 1;
print("Value passed is delete");
});
}
void changeIndex1() {
setState(() {
selectedIndex = 1;
print("Value passed is a");
});
}
void changeIndex2() {
setState(() {
selectedIndex = 1;
print("Value passed is r");
});
}
Widget customRadio1() => OutlineButton(
onPressed: () => changeIndex(),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10.0)),
borderSide: BorderSide(
color: selectedIndex == 0 ? Colors.red : Colors.grey),
child: Text(lst[0], style: TextStyle(
color: selectedIndex == 0 ? Colors.red : Colors.grey),),
);
Widget customRadio2() => OutlineButton(
onPressed: () => changeIndex1(),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10.0)),
borderSide: BorderSide(
color: selectedIndex == 1 ? Colors.green : Colors.grey),
child: Text(lst[1], style: TextStyle(
color: selectedIndex == 1 ? Colors.green : Colors.grey),),
);
Widget customRadio3() {
return OutlineButton(
onPressed: () => changeIndex2(),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10.0)),
borderSide: BorderSide(
color: selectedIndex == 2 ? Colors.cyan : Colors.grey),
child: Text(lst[2], style: TextStyle(
color: selectedIndex == 2 ? Colors.cyan : Colors.grey),),
);
}
}
An InputDecorator cannot have an unbounded width as mentioned in the logs. The cause of this is that the InputDecorator is in a Scrollable Row and has an undefined width. To solve this issue, you can wrap the child widgets in the Row with a Container with a width configured.
I tried to add resizeToAvoidBottomPadding: false below Scaffold but it doesn't change anything.
Could anyone help me figure out how to fix this?
Here is the entire code of the file:
class showAll extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _showAllState();
}
}
class _showAllState extends State<showAll> {
navigateToDetail(DocumentSnapshot indexedData, context) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailPage(itemSelected: indexedData)));
}
Widget build(BuildContext context) {
return Scaffold(
// resizeToAvoidBottomPadding: false, <-- it does not work...
// resizeToAvoidBottomInset: false, <-- it does not work...
appBar: AppBar(
title: Text('All Items'),
backgroundColor: Colors.teal,
actions: <Widget>[
IconButton(
icon: Icon(Icons.search),
onPressed: () {
showSearch(
context: context,
delegate: CustomSearchDelegate(),
);
},
),
],
),
body: StreamBuilder(
stream: Firestore.instance
.collection('ARC_items')
.orderBy('name')
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) return const Text('loading...');
return ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (BuildContext context, int index) => ListTile(
title: Text(
snapshot.data.documents[index].data['name'].toString()),
subtitle: Text(
'Total amount: ${snapshot.data.documents[index].data['# of items'].toString()}'),
onTap: () {
navigateToDetail(snapshot.data.documents[index], context);
// testingReservations(
// snapshot.data.documents[index].documentID);
},
),
);
}),
);
}
}
class CustomSearchDelegate extends SearchDelegate {
navigateToDetail(DocumentSnapshot indexedData, context) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailPage(itemSelected: indexedData)));
}
displayGrids(data, context) {
return Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Flexible(
child: Padding(
padding: EdgeInsets.all(5.0),
child: GridView.count(
crossAxisCount: 2,
childAspectRatio: 1.0,
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
children: data.map<Widget>(
(categoryInfo) {
return GestureDetector(
child: GridTile(
child: CustomCell(categoryInfo),
),
onTap: () {
navigateToDetail(categoryInfo, context);
},
);
},
).toList(),
),
),
),
],
);
}
#override
List<Widget> buildActions(BuildContext context) {
return [
IconButton(
icon: Icon(Icons.clear),
onPressed: () {
query = '';
},
),
];
}
#override
Widget buildLeading(BuildContext context) {
return IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
close(context, null);
},
);
}
#override
Widget buildResults(BuildContext context) {
// TODO: implement buildResults
return null;
}
#override
Widget buildSuggestions(BuildContext context) {
// If you want to add search suggestions as the user enters their search term, this is the place to do that.
return StreamBuilder(
stream: Firestore.instance.collection('ARC_items').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) return const Text('loading...');
final results = snapshot.data.documents.where(
(DocumentSnapshot a) =>
a.data['name'].toString().toLowerCase().contains(
query.trim().toLowerCase(),
),
);
return displayGrids(results, context);
});
}
}
I made a form in my apps, but the image field didn't parse any image to server. I use image picker from gallery.
This is my get image code from gallery:
Future getImageFromGallery() async {
var image = await ImagePicker.pickImage(source: ImageSource.gallery);
setState(() {
_image = image;
});
}
and this is my body apps code with text field and image picker from gallery:
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: new TextFormField(
maxLines: 3,
decoration: new InputDecoration(
labelText: "Keterangan"),
onSaved: (String val) => description = val,
),
),
Padding(
padding: const EdgeInsets.all(15.0),
child: SizedBox(
width: 100.0,
height: 100.0,
child: RaisedButton(
child: _image == null
? Icon(Icons.add_a_photo)
: Image.file(_image),
onPressed: () {
this.getImageFromGallery();
},
),
),
),
Padding(
padding: const EdgeInsets.only(top: 40.0),
child: RaisedButton(
child: Text("Submit"),
color: Colors.blue,
onPressed: () {
newPost();
},
And this is my newPost method :
void newPost() async {
Map data = {
"destination": destination,
"start": start,
"finish": finish,
"person": person,
"route": route,
"descrption": description,
"image": image
};
var body = json.encode(data);
String token = await getToken();
var response = await http.post('https://api-wisapedia.herokuapp.com/posts/',
headers: {HttpHeaders.authorizationHeader: 'Bearer $token'},
body: body);
_newPostResponse =
NewPostResponse.fromJson(json.decode(response.body.toString()));
if (token != null) {
if (destination.isEmpty ||
start.isEmpty ||
finish.isEmpty ||
person.isEmpty ||
route.isEmpty ||
description.isEmpty ||
image.isEmpty) {
showDialog(
builder: (context) => AlertDialog(
content: Text('Please fill the form'),
actions: <Widget>[
FlatButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('OK'),
)
],
),
context: context);
} else {
_formkey.currentState.save();
Navigator.push(
context, MaterialPageRoute(builder: (context) => MainScreen()));
}
} else {
showDialog(
builder: (context) => AlertDialog(
content: Text('You need to authenticate'),
actions: <Widget>[
FlatButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('$token'),
)
],
),
context: context);
}
}
There is onSaved method in text field that makes values of this field can be uploaded by API, but there isn't onSaved method for image. I'm confused is : Image.file(_image) have a same role as onSaved or not? Then when I run this code, I don't know why but the image non uploaded. how can I solve this problem?
I think you should await your function, since it's returning a Future. Something like this:
onPressed: () async {
await this.getImageFromGallery();
},