Why isn't the image changing using the Provider Package? - image

I'm working with the Provider Package on Flutter but can't work out why it's not changing the background image when I call mymodel.image. It should access the MyModal class and change the existing image: Image.asset('images/background_image.jpeg', fit: BoxFit.fill) with the one in the SmallImage screen.
mymodel.image = Image.asset('images/hello_image.png', fit: BoxFit.fill);
Which replaces the background image on the HomePage.
HomePage Screen
import 'package:flutter/material.dart';
import 'package:flutter_app_background/small_images.dart';
import 'package:flutter/cupertino.dart';
import 'package:provider/provider.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ChangeNotifierProvider<MyModel>(
create: (context) => MyModel(),
child: MaterialApp(
title: 'Title',
home: HomePage(),
),
);
}
}
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: true,
appBar: AppBar(
title: Text('Background Image', style: TextStyle(
color: Colors.black,
fontSize: 16,
fontWeight: FontWeight.bold),
),
iconTheme: IconThemeData(color: Colors.white),
actions: <Widget>[
IconButton(
icon: Icon(Icons.settings, color: Colors.black,),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SmallImages()),
);
},
),
],
backgroundColor: Colors.transparent,
elevation: 0.0,
),
body: Stack(
children: <Widget>
[
Positioned.fill(
child: GestureDetector(
child: Consumer<MyModel>(
builder: (context, myModel, child) {
return myModel.image = Image.asset('images/background_image.jpeg', fit: BoxFit.fill);
},
),
),
),
],
),
);
}
}
class MyModel extends ChangeNotifier {
Image _image;
set image(Image value) {
_image = value;
notifyListeners();
}
Image get image => _image;
}
SmallImage Screen
import 'package:flutter/material.dart';
import 'package:flutter_app_background/main.dart';
import 'package:provider/provider.dart';
class SmallImages extends StatefulWidget {
static int tappedGestureDetector = 1;
#override
_SmallImagesState createState() => _SmallImagesState();
}
class _SmallImagesState extends State<SmallImages> {
List<bool> isSelected;
void initState() {
isSelected = [true, false, false, false, false, false, false, false, false];
super.initState();
}
#override
Widget build(BuildContext context) {
final mymodel = Provider.of<MyModel>(context,listen:false); //default for listen is `true`
return Scaffold(
appBar: AppBar(
title: Text('Small Image', style: TextStyle(
color: Colors.black, fontSize: 16, fontWeight: FontWeight.bold),
),
iconTheme: IconThemeData(color: Colors.white),
actions: <Widget>[
IconButton(
icon: Icon(Icons.arrow_left, color: Colors.black,),
onPressed: () {
Navigator.pop(
context,
MaterialPageRoute(builder: (context) => HomePage()),
);
},
),
],
backgroundColor: Colors.transparent,
elevation: 0.0,
),
body: Material(
child: GestureDetector(
child: MaterialApp(
builder: (context, snapshot) {
return GridView.count(
crossAxisCount: 1,
childAspectRatio: 1.0,
padding: const EdgeInsets.all(4.0),
mainAxisSpacing: 0.0,
crossAxisSpacing: 0.0,
children: [
GridView(
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3,
childAspectRatio: MediaQuery
.of(context)
.size
.width /
(MediaQuery
.of(context)
.size
.height / 2),
),
children: [
GestureDetector(
onTap: () {
// return myValue;
setState(() {
SmallImages.tappedGestureDetector = 1;
});
return mymodel.image = Image.asset('images/hello_image.png', fit: BoxFit.fill);
print('hi');
},
child: Container(
height: 100,
width: 107,
decoration: BoxDecoration(border: SmallImages
.tappedGestureDetector == 1
? Border.all(
color: Color(0xff2244C7), width: 1.0)
: Border
.all(color: Colors.transparent,),),
child: Image.asset(
'images/nightsky_image.png',
),
),
),
Consumer<MyModel>(
builder: (context, myModel, child) {
return GestureDetector(
onTap: () {
setState(() {
SmallImages.tappedGestureDetector = 2;
}); // <-- replaced 'tapped' and 'other'
},
child: Container(
height: 100,
width: 107,
decoration: BoxDecoration(border: SmallImages
.tappedGestureDetector == 2
? Border.all(
color: Color(0xff2244C7), width: 1.0)
: Border
.all(color: Colors.transparent,),),
child: Image.asset(
'images/own_image.png',
),
),
);
},
),
Consumer<MyModel>(
builder: (context, myModel, child) {
return GestureDetector(
onTap: () {
setState(() {
SmallImages.tappedGestureDetector = 3;
}); // <-- replaced 'tapped' and 'other'
},
child: Container(
height: 100,
width: 107,
decoration: BoxDecoration(border: SmallImages
.tappedGestureDetector == 3
? Border.all(
color: Color(0xff2244C7), width: 1.0)
: Border
.all(color: Colors.transparent,),),
child: Image.asset(
'images/iceland_image.png',
),
),
);
},
),
].toList(),
),
],
);
}),
),
),
);
}
}

You have to call notifyListeners in your model when the image has changed otherwise the changenotifierprovider will not know that it needs to rebuild.
One way of doing the would be to wrap the image field with a getter and setter and call notifyListeners in the setter after updating the underlying field.
var Image _image;
set image(Image value) {
_image = value;
notifyListeners();
}
Image get image => _image;

Related

upload image using multipart in flutter

i want to upload a image which has come from signature pad which is in the form of unit8list and i want to upload that image using multipart in flutter.
my signature pad code is:-
import 'dart:typed_data';
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_app/Screens/next.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:signature/signature.dart';
class signature_pad extends StatefulWidget {
#override
_signature_padState createState() => _signature_padState();
}
class _signature_padState extends State<signature_pad> {
var file;
String bytes2;
GlobalKey _globalKey = GlobalKey();
final SignatureController _controller = SignatureController(
penStrokeWidth: 5,
penColor: Colors.black,
exportBackgroundColor: Colors.white,
);
setsignePref(var sign) async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
setState(() {
sharedPreferences.setString("sign", sign);
});
}
#override
void initState() {
super.initState();
_controller.addListener(() => print('Value changed'));
}
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Builder(
builder: (BuildContext context) => Scaffold(
body: ListView(
children: <Widget>[ // SIGNATURE CANVAS
Signature(
controller: _controller,
height: MediaQuery.of(context).size.height/1.12,
backgroundColor: Colors.white,
),
//OK AND CLEAR BUTTONS
Container(
decoration: const BoxDecoration(color: Colors.black),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
//SHOW EXPORTED IMAGE IN NEW ROUTE
IconButton(
icon: const Icon(Icons.check),
color: Colors.blue,
onPressed: () async {
if (_controller.isNotEmpty) {
final Uint8List data = await _controller.toPngBytes();
await Navigator.of(context).push(
MaterialPageRoute<void>(
builder: (BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
children: [
Center(
child: Container(
color: Colors.grey[300],
child: Image.memory(data),
),
),
Padding(
padding: const EdgeInsets.all(20),
child: new RaisedButton(
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (context)=> next(image : data)));
},
child: new Text('Submit'),
),
), ],
),
);
},
),
);
}
},
),
//CLEAR CANVAS
IconButton(
icon: const Icon(Icons.clear),
color: Colors.blue,
onPressed: () {
setState(() => _controller.clear());
},
),
],
),
),
],
),
),
),
);
}
}
and my upload page is:-
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_app/Screens/navidrawer.dart';
import 'package:flutter_app/Screens/signature_pad.dart';
import 'package:flutter_app/Url.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path_provider/path_provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:http/http.dart' as http;
class next extends StatefulWidget {
final String CompanyCode;
final Uint8List image;
final String docketno;
next({Key key,this.CompanyCode,this.image,this.docketno}) : super(key: key);
#override
_nextState createState() => _nextState();
}
class _nextState extends State<next> {
List<OriginModel> OriginModelList = [];
String selectedOrigin;
// final networkHandler = NetworkHandler();
bool circular = false;
final _globalkey = GlobalKey<FormState>();
final ImagePicker _picker = ImagePicker();
PickedFile _imageFile;
bool _obscuredText = true;
var okData;
var user_id;
var responseResult;
var loading = false;
var count = 0;
var myData;
final _formKey = GlobalKey<FormState>();
var bytes;
Future<String> getUserIdPref() async{
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
setState(() {
user_id = sharedPreferences.getString("user_id");
});
return user_id;
}
void UploadImage() async {
var request = http.MultipartRequest('POST', Uri.parse(URLs.image));
request.fields['CompanyCode']= "${widget.CompanyCode}";
request.fields['empCode'] = "$user_id";
request.fields['documentType']= "POD";
if (_imageFile != null && widget.image == null) {
print('AddingUserProfilePic ${_imageFile.path}and $user_id');
request.files
.add(await http.MultipartFile.fromPath('file', _imageFile.path));
}
else if(widget.image !=null && _imageFile == null){
bytes = (await rootBundle.load(Image.memory(widget.image).toString())).buffer.asUint8List();
request.files.add(http.MultipartFile.fromBytes('file', bytes));
}
var response = await request.send();
var responseBody = await http.Response.fromStream(response);
myData = json.decode(responseBody.body);
print('Status code is : ${response.statusCode} && ${response}');
if (response.statusCode == 200) {
Fluttertoast.showToast(msg: 'Uploaded Successfully');
Navigator.popUntil(context, (route) {
return count++ == 2;
});
} else {
Fluttertoast.showToast(msg: 'Upload Failed');
}
}
#override
void initState() {
super.initState();
this .getUserIdPref();
}
List<Widget> _buildForm(BuildContext context) {
var l = List<Widget>();
// Image img = Image.memory(widget.image);
Container container = Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
alignment: AlignmentDirectional.topCenter,
child:Form(
key: _formKey,
child: SingleChildScrollView(
child: Container(
child:Column(
children: [
SizedBox(height: MediaQuery.of(context).size.height/20 ),
Container(
margin: EdgeInsets.only(top: 15),
child:
_imageFile == null && widget.image == null ? CircleAvatar(
radius: 80.0,
backgroundImage: NetworkImage(
"https://img.freepik.com/free-vector/illustration-document-icon_53876-37007.jpg?size=626&ext=jpg&ga=GA1.2.1768032709.1573116529")
) :
_imageFile != null && widget.image == null ?
CircleAvatar(
radius: 80.0,
backgroundImage: FileImage(File(_imageFile.path)),)
: Container(
color: Colors.grey[300],
child: Image.memory(widget.image),
),
),
SizedBox(height: MediaQuery.of(context).size.height/30 ),
Column(
crossAxisAlignment : CrossAxisAlignment.start,
children: [
Container( margin: EdgeInsets.only(left: 10,right: 10),
child: Text(
'DOCUMENT TYPE'.toUpperCase(),
style: TextStyle(
color: Colors.black,
fontSize: 16,
fontWeight: FontWeight.bold),
),
),
SizedBox(height: MediaQuery.of(context).size.height/40 ),
Container(margin: EdgeInsets.only(left: 10,right: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.0),
color: Colors.cyan,
border: Border.all()),
width: MediaQuery.of(context).size.width,
padding: const EdgeInsets.all(10.0),
child: DropdownButtonHideUnderline(
child: Theme(
data: Theme.of(context).copyWith(
canvasColor: Colors.cyan,
),
child: new DropdownButton<String>(
hint: new Text("Select Document Type",style: TextStyle(color: Colors.white) ,),
value: selectedOrigin,
isDense: true,
onChanged: (String newValue) {
setState(() {
selectedOrigin = newValue;
});
print(selectedOrigin);
},
items: OriginModelList.map((OriginModel map) {
return new DropdownMenuItem<String>(
value: map.id,
child: new Text(map.name,
style: new TextStyle(color: Colors.white)),
);
}
).toList(),
),
),
),
),
],
),
GestureDetector(
onTap: (){
Navigator.push(context, MaterialPageRoute(builder: (context)=> signature_pad()));
},
child: Container(
margin: EdgeInsets.only(left: 10,right: 10,top: 30),
width: MediaQuery.of(context).size.width,
height: 70,
color: Colors.cyan,
child: Row(
children: [
Container(
child: Image.asset(
"assets/register.png"
),
height: 60,
margin: EdgeInsets.only(left: 5),
),
Container(margin:EdgeInsets.only(left: 10),child: Text("Signature",style: TextStyle(color: Colors.white))),
],
),
),
),
GestureDetector(
onTap: (){
_showAlertDialog();
},
child: Container(
margin: EdgeInsets.only(left: 10,right: 10,top: 20),
width: MediaQuery.of(context).size.width,
height: 70,
color: Colors.cyan,
child: Row(
children: [
Container(
child: Image.asset(
"assets/upload.png"
),
height: 60,
margin: EdgeInsets.only(left: 5),
),
Container(margin:EdgeInsets.only(left: 10),child: Text("Image",style: TextStyle(color: Colors.white))),
],
),
),
),
SizedBox(height: MediaQuery.of(context).size.height/30 ),
Padding(
padding: const EdgeInsets.all(30.0),
child: GestureDetector(
onTap: (){
if (_formKey.currentState.validate()) {
setState(() {
loading = true;
});
UploadImage();
}
},
child: Container(
height: 55.0,
width: 600.0,
child: Text(
'SAVE',
style: TextStyle(
color: Colors.white,
letterSpacing: 0.2,
fontFamily: "Sans",
fontSize: 18.0,
fontWeight: FontWeight.w800),
),
alignment: FractionalOffset.center,
decoration: BoxDecoration(
boxShadow: [
BoxShadow(color: Colors.black38, blurRadius: 15.0)
],
borderRadius: BorderRadius.circular(30.0),
gradient: LinearGradient(colors: <Color>[
Colors.cyan[300],
Colors.cyan[600],
])),
),
),
),
],
),
),
),
),
);
l.add(container);
if (loading) {
var modal = Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: Stack(
children: [
Opacity(
opacity: 0.3,
child: const ModalBarrier(dismissible: false, color: Colors.grey),
),
Center(
child: new CircularProgressIndicator(),
),
],
),
);
l.add(modal);
}
return l;
}
#override
Widget build(BuildContext context) {
OriginModelList = [
OriginModel('1', "POD"),
OriginModel('2', "SIGNATURE"),
];
return Scaffold(
appBar: AppBar(
title: Text(
'OPERATIONS',
style: TextStyle(color: Colors.white, fontSize: 16),
),
actions: <Widget>[
Padding(
padding: EdgeInsets.only(right: 20.0),
child: GestureDetector(
onTap: () {},
child: Icon(
Icons.chat,
size: 26.0,
),
)
),
Padding(
padding: EdgeInsets.only(right: 20.0),
child: GestureDetector(
onTap: () {},
child: Icon(
Icons.call,
),
)
),
],
elevation: 0,
backgroundColor:Colors.cyan,
brightness: Brightness.light,
),
body: Stack(
alignment: AlignmentDirectional.bottomCenter,
children: _buildForm(context),
),
drawer: NaviDrawer(),
);
}
void _showAlertDialog()
{
showDialog(
context: context,
barrierDismissible: true,
builder: (BuildContext context)
{
return AlertDialog(
title: new Text('Make your choice!'),
content: Container(
height: 80,
child: Column(
children: [
GestureDetector(
onTap: (){
takePhoto(ImageSource.camera);
},
child: Row(
children: [
Icon(Icons.camera),
Container(
margin: EdgeInsets.only(left: 5),
child: new Text('Camera')),
],
),
),
GestureDetector(
onTap: (){
takePhoto(ImageSource.gallery);
},
child: Container(
margin: EdgeInsets.only(top: 10),
child: Row(
children: [
Icon(Icons.image),
Container( margin: EdgeInsets.only(left: 5),
child: new Text('Gallery')),
],
),
),
),
],
),
),
);
}
);
}
void takePhoto(ImageSource source) async {
final pickedFile = await _picker.getImage(
source: source,
);
setState(() {
_imageFile = pickedFile;
});
}
}
class OriginModel {
String id;
String name;
#override
String toString() {
return '$id $name';
}
OriginModel(this.id, this.name);
}
and the image type like Image.memory(widget.image) is uploading because it is a iamge type and like widget.image is also not uploading because it is unit8list type.
so how can i upload that?
thank you in advance.....

is there a way to merge dynamically loaded image file to one image file in flutter?

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.

How do I change the background image that is on a different screen with OnTap in Flutter?

Problem:
I have a GridView of small images, when the user taps on them it needs to change the background image on a different screen.
Here is the Homepage screen with the background image:
class HomePage extends StatelessWidget {
Image defaultImage;
#override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: true,
appBar: AppBar(
title: Text('Background Image', style: TextStyle(
color: Colors.black, fontSize: 16, fontWeight: FontWeight.bold),
),
iconTheme: IconThemeData(color: Colors.white),
actions: <Widget>[
IconButton(
icon: Icon(Icons.settings, color: Colors.black,),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SmallImages()),
);
},
),
],
backgroundColor: Colors.transparent,
elevation: 0.0,
),
body: Stack(
children: <Widget>
[
Positioned.fill(
child: GestureDetector(
child: defaultImage = Image.asset('images/background_image.jpeg', fit: BoxFit.fill),
),
),
],
),
);
}
}
Here is the SmallImage screen where the user can click on a small image and it would change the background image on the HomePage. The background image would then have a different image for example 'defaultImage = Image.asset('images/background_image25.jpeg', fit: BoxFit.fill)'
class SmallImages extends StatefulWidget {
static int tappedGestureDetector = 0;
#override
_SmallImagesState createState() => _SmallImagesState();
}
class _SmallImagesState extends State<SmallImages> {
List<bool> isSelected;
void initState() {
isSelected = [true, false, false, false, false, false, false, false, false];
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Small Image', style: TextStyle(
color: Colors.black, fontSize: 16, fontWeight: FontWeight.bold),
),
iconTheme: IconThemeData(color: Colors.white),
actions: <Widget>[
IconButton(
icon: Icon(Icons.arrow_left, color: Colors.black,),
onPressed: () {
Navigator.pop(
context,
MaterialPageRoute(builder: (context) => HomePage()),
);
},
),
],
backgroundColor: Colors.transparent,
elevation: 0.0,
),
body: Material(
child: GestureDetector(
child: MaterialApp(
builder: (context, snapshot) {
return GridView.count(
crossAxisCount: 1,
childAspectRatio: 1.0,
padding: const EdgeInsets.all(4.0),
mainAxisSpacing: 0.0,
crossAxisSpacing: 0.0,
children: [
GridView(
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3,
childAspectRatio: MediaQuery
.of(context)
.size
.width /
(MediaQuery
.of(context)
.size
.height / 2),
),
children: [
GestureDetector(
onTap: () {
setState(() {
SmallImages.tappedGestureDetector = 2;
}); // <-- replaced 'tapped' and 'other'
},
child: Container(
height: 100,
width: 107,
decoration: BoxDecoration(border: SmallImages
.tappedGestureDetector == 2 ? Border.all(
color: Color(0xff2244C7), width: 1.0) : Border
.all(color: Colors.transparent,),),
child: Image.asset('images/smallImage1.png',
),
),
),
GestureDetector(
onTap: () {
setState(() {
SmallImages.tappedGestureDetector = 3;
}); // <-- replaced 'tapped' and 'other'
},
child: Container(
height: 100,
width: 107,
decoration: BoxDecoration(border: SmallImages
.tappedGestureDetector == 3 ? Border.all(
color: Color(0xff2244C7), width: 1.0) : Border
.all(color: Colors.transparent,),),
child: Image.asset('images/smallImage2.png',
),
),
),
GestureDetector(
onTap: () {
setState(() {
SmallImages.tappedGestureDetector = 4;
}); // <-- replaced 'tapped' and 'other'
},
child: Container(
height: 100,
width: 107,
decoration: BoxDecoration(border: SmallImages
.tappedGestureDetector == 4 ? Border.all(
color: Color(0xff2244C7), width: 1.0) : Border
.all(color: Colors.transparent,),),
child: Image.asset('images/smallImage3.png',
),
),
),
].toList(),
),
],
);
}),
),
),
);
}
}

Flutter Let the user add images in carousel

Is there any way to let the user add manually images in the image carousel?
This is the image list that I already show to the user:
final List<String> imgList = [
'https://cdn.pixabay.com/photo/2016/04/15/08/04/strawberries-1330459_960_720.jpg',
'https://cdn.pixabay.com/photo/2019/12/01/16/56/cookies-4665910_960_720.jpg',
'https://cdn.pixabay.com/photo/2017/05/23/22/36/vegetables-2338824_960_720.jpg'
];
final List<Widget> imageSliders = imgList
.map(
(item) => Container(
child: Container(
margin: EdgeInsets.all(5.0),
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(5.0)),
child: Stack(
children: <Widget>[
Image.network(item, fit: BoxFit.cover, width: 1000.0),
Positioned(
bottom: 0.0,
left: 0.0,
right: 0.0,
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Color.fromARGB(200, 0, 0, 0),
Color.fromARGB(0, 0, 0, 0)
],
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
),
),
padding: EdgeInsets.symmetric(
vertical: 10.0, horizontal: 20.0),
),
),
],
)),
),
),
)
.toList();
CarouselSlider(
options: CarouselOptions(
autoPlay: false,
aspectRatio: 2.0,
enlargeCenterPage: true,
enlargeStrategy: CenterPageEnlargeStrategy.height,
pauseAutoPlayOnManualNavigate: true,
pauseAutoPlayOnTouch: true,
scrollDirection: Axis.horizontal),
items: imageSliders,
),
Is it not okay that I have used CarouselSlider widget? I didn't found any way that you could've let the user add a image from his phone directly into the image carousel, that I've created.
You can copy paste run full code below
Step 1: You can use class ImageConfig to classify image source
Step 2: check image source type when show
item.source == "http"
? Image.network(item.path,
fit: BoxFit.cover, width: 1000.0)
: Image.file(File(item.path),
fit: BoxFit.cover, width: 1000.0),
code snippet
class ImageConfig {
String source;
String path;
ImageConfig({this.source, this.path});
}
class _MyHomePageState extends State<MyHomePage> {
List<ImageConfig> imgList = [
ImageConfig(
source: "http",
path:
'https://cdn.pixabay.com/photo/2016/04/15/08/04/strawberries-1330459_960_720.jpg'),
...
Future getImage() async {
final pickedFile = await picker.getImage(source: ImageSource.gallery);
setState(() {
imgList.add(ImageConfig(source: "file", path: pickedFile.path));
});
}
working demo
full code
import 'dart:io';
import 'package:carousel_slider/carousel_slider.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class ImageConfig {
String source;
String path;
ImageConfig({this.source, this.path});
}
class _MyHomePageState extends State<MyHomePage> {
List<ImageConfig> imgList = [
ImageConfig(
source: "http",
path:
'https://cdn.pixabay.com/photo/2016/04/15/08/04/strawberries-1330459_960_720.jpg'),
ImageConfig(
source: "http",
path:
'https://cdn.pixabay.com/photo/2019/12/01/16/56/cookies-4665910_960_720.jpg'),
ImageConfig(
source: "http",
path:
'https://cdn.pixabay.com/photo/2017/05/23/22/36/vegetables-2338824_960_720.jpg')
];
List<Widget> imageSliders;
final picker = ImagePicker();
Future getImage() async {
final pickedFile = await picker.getImage(source: ImageSource.gallery);
setState(() {
imgList.add(ImageConfig(source: "file", path: pickedFile.path));
});
}
#override
Widget build(BuildContext context) {
imageSliders = imgList
.map(
(item) => Container(
child: Container(
margin: EdgeInsets.all(5.0),
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(5.0)),
child: Stack(
children: <Widget>[
item.source == "http"
? Image.network(item.path,
fit: BoxFit.cover, width: 1000.0)
: Image.file(File(item.path),
fit: BoxFit.cover, width: 1000.0),
Positioned(
bottom: 0.0,
left: 0.0,
right: 0.0,
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Color.fromARGB(200, 0, 0, 0),
Color.fromARGB(0, 0, 0, 0)
],
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
),
),
padding: EdgeInsets.symmetric(
vertical: 10.0, horizontal: 20.0),
),
),
],
)),
),
),
)
.toList();
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CarouselSlider(
options: CarouselOptions(
autoPlay: false,
aspectRatio: 2.0,
enlargeCenterPage: true,
enlargeStrategy: CenterPageEnlargeStrategy.height,
pauseAutoPlayOnManualNavigate: true,
pauseAutoPlayOnTouch: true,
scrollDirection: Axis.horizontal),
items: imageSliders,
)
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: getImage,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}

Flutter: hide and display app bar in scrolling detected

I'm having trouble with app bar animation, I'm using SilverAppBar, in my app. So, the problem is when I'm in the middle of my list and I scroll up, the app bar does not appear, but it appears just when scrolling reaches the top of the items list. I already tested the snap parameter and give it true, but not the result I expect. I have ideas about creating a custom animation for this, but I'm not too experienced in Flutter, and also if there is a way to add parameters, or another widget that will work for my situation, it would be great.
The actual code of the demo I'm using:
Widget _search() => Container(
color: Colors.grey[400],
child: SafeArea(
child: Container(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
enabled: false,
style: TextStyle(fontSize: 16, color: Colors.white),
decoration: InputDecoration(
prefix: SizedBox(width: 12),
hintText: "Search",
contentPadding:
EdgeInsets.symmetric(horizontal: 32.0, vertical: 14.0),
border: InputBorder.none,
),
),
),
)),
);
Container _buildBody() {
return Container(
child: new GridView.count(
crossAxisCount: 2,
children: List.generate(100, (index) {
return Center(
child: Text(
'Item $index',
style: Theme.of(context).textTheme.headline,
),
);
}),
));
}
#override
Widget build(BuildContext context) {
return new Scaffold(
resizeToAvoidBottomPadding: false,
body: new NestedScrollView(
headerSliverBuilder:
(BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
new SliverAppBar(
title: Text("Demo",
style: TextStyle(
color: Colors.white,
)),
pinned: false,
floating: true,
forceElevated: innerBoxIsScrolled,
),
];
},
body: new Column(children: <Widget>[
_search(),
new Expanded(child: _buildBody())
])));
}
The result I have now:
Image 1
The result I got after giving true to the snap parameter:
Image 2
Plenty of applications like WhatsApp, Facebook, LinkedIn ... have this animating app bar. To explain more what exactly I expect with this animating app bar, I added an example of Google Play Store, showing the wanted animation: Play Store example
I had a similar issue with CustomScrollView and SliverAppbar using refresh indicator i ended up creating my own custom appbar.
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
class HomeView extends StatefulWidget {
#override
HomeState createState() => HomeState();
}
class HomeState extends State<HomeView> with SingleTickerProviderStateMixin {
bool _isAppbar = true;
ScrollController _scrollController = new ScrollController();
#override
void initState() {
super.initState();
_scrollController.addListener(() {
if (_scrollController.position.userScrollDirection ==
ScrollDirection.reverse) {
appBarStatus(false);
}
if (_scrollController.position.userScrollDirection ==
ScrollDirection.forward) {
appBarStatus(true);
}
});
}
void appBarStatus(bool status) {
setState(() {
_isAppbar = status;
});
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(kToolbarHeight),
child: AnimatedContainer(
height: _isAppbar ? 55.0 : 0.0,
duration: Duration(milliseconds: 200),
child: CustomAppBar(),
),
),
body: ListView.builder(
controller: _scrollController,
itemCount: 20,
itemBuilder: (BuildContext context, int index) {
return container();
},
),
),
);
}
}
Widget container() {
return Container(
height: 80.0,
color: Colors.pink,
margin: EdgeInsets.all(8.0),
width: 100,
child: Center(
child: Text(
'Container',
style: TextStyle(
fontSize: 18.0,
),
)),
);
}
class CustomAppBar extends StatefulWidget {
#override
AppBarView createState() => new AppBarView();
}
class AppBarView extends State<CustomAppBar> {
#override
Widget build(BuildContext context) {
return AppBar(
backgroundColor: Colors.white,
leading: InkWell(
onTap: () => {},
child: new Padding(
padding: const EdgeInsets.all(8.0),
child: CircleAvatar(
backgroundColor: Colors.white,
child: ClipOval(
child: Image.network(
'https://images.squarespace-cdn.com/content/5aee389b3c3a531e6245ae76/1530965251082-9L40PL9QH6PATNQ93LUK/linkedinPortraits_DwayneBrown08.jpg?format=1000w&content-type=image%2Fjpeg'),
),
),
),
),
actions: <Widget>[
IconButton(
alignment: Alignment.centerLeft,
icon: Icon(
Icons.search,
color: Colors.black,
),
onPressed: () {},
),
],
title: Container(
alignment: Alignment.centerLeft,
child: Text("Custom Appbar", style: TextStyle(color: Colors.black),)
),
);
}
}
To get this functionality to work, you will need to use the CustomScrollView widget instead of NestedScrollView. Google Documentation
Here is a working example:
class MyHomeState extends State<MyHome> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: <Widget>[
const SliverAppBar(
pinned: false,
snap: false,
floating: true,
flexibleSpace: FlexibleSpaceBar(
title: Text('Demo'),
),
),
SliverGrid(
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 200.0,
mainAxisSpacing: 10.0,
crossAxisSpacing: 10.0,
childAspectRatio: 4.0,
),
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
alignment: Alignment.center,
color: Colors.teal[100 * (index % 9)],
child: Text('grid item $index'),
);
},
childCount: 50,
),
),
],
)
);
}
}
Example of this running here
I was able to make the floating Appbar with Tabbar similar to that of WhatsApp by using SliverAppbar with NestedScrollView. Do remember to add floatHeaderSlivers: true, in NestedScrollView. Link to sample code
import 'dart:math';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: CustomSliverAppbar(),
);
}
}
class CustomSliverAppbar extends StatefulWidget {
#override
_CustomSliverAppbarState createState() => _CustomSliverAppbarState();
}
class _CustomSliverAppbarState extends State<CustomSliverAppbar>
with SingleTickerProviderStateMixin {
TabController _tabController;
#override
void initState() {
_tabController = TabController(
initialIndex: 0,
length: 2,
vsync: this,
);
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: NestedScrollView(
floatHeaderSlivers: true,
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
title: Text(
"WhatsApp type sliver appbar",
),
centerTitle: true,
pinned: true,
floating: true,
bottom: TabBar(
indicatorColor: Colors.black,
labelPadding: const EdgeInsets.only(
bottom: 16,
),
controller: _tabController,
tabs: [
Text("TAB A"),
Text("TAB B"),
]),
),
];
},
body: TabBarView(
controller: _tabController,
children: [
TabA(),
const Center(
child: Text('Display Tab 2',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
),
],
),
),
);
}
#override
void dispose() {
_tabController.dispose();
super.dispose();
}
}
class TabA extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scrollbar(
child: ListView.separated(
separatorBuilder: (context, child) => Divider(
height: 1,
),
padding: EdgeInsets.all(0.0),
itemCount: 30,
itemBuilder: (context, i) {
return Container(
height: 100,
width: double.infinity,
color: Colors.primaries[Random().nextInt(Colors.primaries.length)],
);
},
),
);
}
}

Resources