Related
Iam trying to make a flutter windows application that can connect to a scanner device and get the image data from it, but i can't seem to find any packages that help with that so if anyone can give me the link of a library or a tutorial that can help with that.
Thanks in advance.
i have tried searching but all the packages i have found are directed to android and ios only.
Is this what you want?
I've ported the C++ code from https://github.com/twain/twain-samples and created an open source project https://github.com/yushulx/flutter_twain_scanner.
The plugin is available on https://pub.dev/packages/flutter_twain_scanner
The full code to scan documents from a connected scanner on Windows desktop:
import 'dart:io';
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:flutter_twain_scanner/flutter_twain_scanner.dart';
import 'dart:ui' as ui;
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String _platformVersion = 'Unknown';
final _flutterTwainScannerPlugin = FlutterTwainScanner();
String? _documentPath;
List<String> _scanners = []; // Option 2
String? _selectedScanner;
#override
void initState() {
super.initState();
initPlatformState();
}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> initPlatformState() async {
String platformVersion;
// Platform messages may fail, so we use a try/catch PlatformException.
// We also handle the message potentially returning null.
try {
platformVersion = await _flutterTwainScannerPlugin.getPlatformVersion() ??
'Unknown platform version';
} on PlatformException {
platformVersion = 'Failed to get platform version.';
}
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;
setState(() {
_platformVersion = platformVersion;
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Flutter TWAIN Scanner'),
),
body: Stack(
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
SizedBox(
height: 100,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
MaterialButton(
textColor: Colors.white,
color: Colors.blue,
onPressed: () async {
List<String>? scanners =
await _flutterTwainScannerPlugin
.getDataSources();
if (scanners != null) {
setState(() {
_scanners = scanners;
});
}
},
child: const Text('List Scanners')),
DropdownButton(
hint: Text(
'Select a scanner'), // Not necessary for Option 1
value: _selectedScanner,
onChanged: (newValue) {
setState(() {
_selectedScanner = newValue;
});
},
items: _scanners.map((location) {
return DropdownMenuItem(
child: new Text(location),
value: location,
);
}).toList(),
),
MaterialButton(
textColor: Colors.white,
color: Colors.blue,
onPressed: () async {
if (_selectedScanner != null) {
int index =
_scanners.indexOf(_selectedScanner!);
String? documentPath =
await _flutterTwainScannerPlugin
.scanDocument(index);
setState(() {
_documentPath = documentPath;
});
}
},
child: const Text('Scan Document')),
]),
),
SizedBox(
height: 600,
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: _documentPath == null
? Image.asset('images/default.png')
: Image.file(
File(_documentPath!),
fit: BoxFit.contain,
width: 600,
height: 600,
),
))
],
),
],
),
),
);
}
}
i am getting type _file is not a subtype of type widget error and this is my code.
i am trying to move my cropped image that i cropped in cropImage to editImage widget.
_getFromGallery() async {
XFile? pickedFile = await ImagePicker().pickImage(
source: ImageSource.gallery,
maxWidth: 1800,
maxHeight: 1800,
);
_cropImage(pickedFile!.path);
}
_cropImage(pickedFile) async {
File? croppedImage = await ImageCropper.cropImage(
sourcePath: pickedFile,
maxWidth: 1080,
maxHeight: 1080,
);
if (croppedImage != null) {
image = croppedImage;
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => editImage(croppedImage)));
}
}
Widget editImage(croppedImage) {
final Future<String> _croppedImage = Future<String>.delayed(
const Duration(seconds: 2),
() => 'Data Loaded',
);
return FutureBuilder<String>(
future: _croppedImage,
builder: (BuildContext context, snapshot) {
if (snapshot.hasData) {}
return Center(
child: Scaffold(
appBar: AppBar(
title: Text('Edit Image'),
),
body: Container(child: image = croppedImage),
),
);
});
}
}
can i get the right code example? im stuck in this for weeks. please help.
flutter root tree can show only classes who inherited from the widget class. change your code to this :
Widget editImage(croppedImage) {
final Future<String> _croppedImage = Future<String>.delayed(
const Duration(seconds: 2),
() => 'Data Loaded',
);
return FutureBuilder<String>(
future: _croppedImage,
builder: (BuildContext context, snapshot) {
if (snapshot.hasData) {}
return Center(
child: Scaffold(
appBar: AppBar(
title: Text('Edit Image'),
),
body:croppedImage !=null? Container(child: Image.file(croppedImage!)):null,
),
);
});
} }
I'm trying to take an image from my gallery or capture with camera immediately the upload page is built. I created a dialog to show the two options but I'm getting the error
setState() or markNeedsBuild() called during build.
when I run on my emulator.
Any help will be appreciated. Thank you
This is my code
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
class UploadPage extends StatefulWidget {
#override
_UploadPageState createState() => _UploadPageState();
}
class _UploadPageState extends State<UploadPage> {
PickedFile image;
final picker=ImagePicker();
takeImage(mContext){
return showDialog(
context: mContext,
builder: (context){
return SimpleDialog(
title: Text("New post"),
children: [
SimpleDialogOption(
child: Text("Upload from from gallery"),
onPressed: ()async{
Navigator.pop(context);
final file=await picker.getImage(
source: ImageSource.gallery,
// maxHeight: 600,
// maxWidth: 970,
);
setState(() {
this.image=file;
});
},
),
SimpleDialogOption(
child: Text("Capture with camera"),
onPressed: ()async{
Navigator.pop(context);
final file=await picker.getImage(
source: ImageSource.camera,
maxHeight: 600,
maxWidth: 970,
);
setState(() {
this.image=file;
});
},
),
SimpleDialogOption(
child: Text("Cancel",style: TextStyle(color: Colors.red),),
onPressed: (){
Navigator.pop(context);
},
),
],
);
}
);
}
#override
Widget build(BuildContext context) {
return takeImage(context);
}
}
showDialog displays a dialog above the current contents of the app and it returns the future.
You can call showDialog after build
class UploadPage extends StatefulWidget {
#override
_UploadPageState createState() => _UploadPageState();
}
class _UploadPageState extends State<UploadPage> {
PickedFile image;
final picker = ImagePicker();
takeImage(mContext) {
return showDialog(
context: mContext,
builder: (context) {
return SimpleDialog(
title: Text("New post"),
children: [
SimpleDialogOption(
child: Text("Upload from from gallery"),
onPressed: () async {
Navigator.pop(context);
final file = await picker.getImage(
source: ImageSource.gallery,
// maxHeight: 600,
// maxWidth: 970,
);
setState(() {
this.image = file;
});
},
),
SimpleDialogOption(
child: Text("Capture with camera"),
onPressed: () async {
Navigator.pop(context);
final file = await picker.getImage(
source: ImageSource.camera,
maxHeight: 600,
maxWidth: 970,
);
setState(() {
this.image = file;
});
},
),
SimpleDialogOption(
child: Text(
"Cancel",
style: TextStyle(color: Colors.red),
),
onPressed: () {
Navigator.pop(context);
},
),
],
);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'Take Picture',
),
),
body: Center(
child: FlatButton(
color: Colors.blue,
onPressed: () {
takeImage(context);
},
child: Text(
'Select Image',
style: TextStyle(color: Colors.white),
),
),
),
);
}
}
I tried to find how to select and upload multiple images in flutter but most of the plugins are not working or I did not understand them well. I found little application but it selects and upload only one picture. How to change this code that user can select and upload multiple pictures or is there any other alternatives. Please write in details, i am freshman in coding. Thanks in advance.
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:http/http.dart' as http;
import 'package:image_picker/image_picker.dart';
import 'package:mime/mime.dart';
import 'dart:convert';
import 'package:http_parser/http_parser.dart';
import 'package:toast/toast.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Image Upload Demo',
theme: ThemeData(primarySwatch: Colors.pink),
home: ImageInput());
}
}
class ImageInput extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _ImageInput();
}
}
class _ImageInput extends State<ImageInput> {
// To store the file provided by the image_picker
File _imageFile;
// To track the file uploading state
bool _isUploading = false;
String baseUrl = 'http://YOUR_IPV4_ADDRESS/flutterdemoapi/api.php';
void _getImage(BuildContext context, ImageSource source) async {
File image = await ImagePicker.pickImage(source: source);
setState(() {
_imageFile = image;
});
// Closes the bottom sheet
Navigator.pop(context);
}
Future<Map<String, dynamic>> _uploadImage(File image) async {
setState(() {
_isUploading = true;
});
// Find the mime type of the selected file by looking at the header bytes of the file
final mimeTypeData =
lookupMimeType(image.path, headerBytes: [0xFF, 0xD8]).split('/');
// Intilize the multipart request
final imageUploadRequest =
http.MultipartRequest('POST', Uri.parse(baseUrl));
// Attach the file in the request
final file = await http.MultipartFile.fromPath('image', image.path,
contentType: MediaType(mimeTypeData[0], mimeTypeData[1]));
// Explicitly pass the extension of the image with request body
// Since image_picker has some bugs due which it mixes up
// image extension with file name like this filenamejpge
// Which creates some problem at the server side to manage
// or verify the file extension
imageUploadRequest.fields['ext'] = mimeTypeData[1];
imageUploadRequest.files.add(file);
try {
final streamedResponse = await imageUploadRequest.send();
final response = await http.Response.fromStream(streamedResponse);
if (response.statusCode != 200) {
return null;
}
final Map<String, dynamic> responseData = json.decode(response.body);
_resetState();
return responseData;
} catch (e) {
print(e);
return null;
}
}
void _startUploading() async {
final Map<String, dynamic> response = await _uploadImage(_imageFile);
print(response);
// Check if any error occured
if (response == null || response.containsKey("error")) {
Toast.show("Image Upload Failed!!!", context,
duration: Toast.LENGTH_LONG, gravity: Toast.BOTTOM);
} else {
Toast.show("Image Uploaded Successfully!!!", context,
duration: Toast.LENGTH_LONG, gravity: Toast.BOTTOM);
}
}
void _resetState() {
setState(() {
_isUploading = false;
_imageFile = null;
});
}
void _openImagePickerModal(BuildContext context) {
final flatButtonColor = Theme.of(context).primaryColor;
print('Image Picker Modal Called');
showModalBottomSheet(
context: context,
builder: (BuildContext context) {
return Container(
height: 150.0,
padding: EdgeInsets.all(10.0),
child: Column(
children: <Widget>[
Text(
'Pick an image',
style: TextStyle(fontWeight: FontWeight.bold),
),
SizedBox(
height: 10.0,
),
FlatButton(
textColor: flatButtonColor,
child: Text('Use Camera'),
onPressed: () {
_getImage(context, ImageSource.camera);
},
),
FlatButton(
textColor: flatButtonColor,
child: Text('Use Gallery'),
onPressed: () {
_getImage(context, ImageSource.gallery);
},
),
],
),
);
});
}
Widget _buildUploadBtn() {
Widget btnWidget = Container();
if (_isUploading) {
// File is being uploaded then show a progress indicator
btnWidget = Container(
margin: EdgeInsets.only(top: 10.0),
child: CircularProgressIndicator());
} else if (!_isUploading && _imageFile != null) {
// If image is picked by the user then show a upload btn
btnWidget = Container(
margin: EdgeInsets.only(top: 10.0),
child: RaisedButton(
child: Text('Upload'),
onPressed: () {
_startUploading();
},
color: Colors.pinkAccent,
textColor: Colors.white,
),
);
}
return btnWidget;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Image Upload Demo'),
),
body: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 40.0, left: 10.0, right: 10.0),
child: OutlineButton(
onPressed: () => _openImagePickerModal(context),
borderSide:
BorderSide(color: Theme.of(context).accentColor, width: 1.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.camera_alt),
SizedBox(
width: 5.0,
),
Text('Add Image'),
],
),
),
),
_imageFile == null
? Text('Please pick an image')
: Image.file(
_imageFile,
fit: BoxFit.cover,
height: 300.0,
alignment: Alignment.topCenter,
width: MediaQuery.of(context).size.width,
),
_buildUploadBtn(),
],
),
);
}
}
I used that package:
dependencies:
multi_image_picker: ^4.6.7
Ex:
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:multi_image_picker/multi_image_picker.dart';
void main() => runApp(new MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
List<Asset> images = List<Asset>();
String _error;
#override
void initState() {
super.initState();
}
Widget buildGridView() {
if (images != null)
return GridView.count(
crossAxisCount: 3,
children: List.generate(images.length, (index) {
Asset asset = images[index];
return AssetThumb(
asset: asset,
width: 300,
height: 300,
);
}),
);
else
return Container(color: Colors.white);
}
Future<void> loadAssets() async {
setState(() {
images = List<Asset>();
});
List<Asset> resultList;
String error;
try {
resultList = await MultiImagePicker.pickImages(
maxImages: 300,
);
} on Exception catch (e) {
error = e.toString();
}
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;
setState(() {
images = resultList;
if (error == null) _error = 'No Error Dectected';
});
}
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: const Text('Plugin example app'),
),
body: Column(
children: <Widget>[
Center(child: Text('Error: $_error')),
RaisedButton(
child: Text("Pick images"),
onPressed: loadAssets,
),
Expanded(
child: buildGridView(),
)
],
),
),
);
}
}
Add dependecy of image_picker:
image_picker: ^0.8.4+3
Then make a method for selectImages():
final ImagePicker imagePicker = ImagePicker();
List<XFile>? imageFileList = [];
void selectImages() async {
final List<XFile>? selectedImages = await
imagePicker.pickMultiImage();
if (selectedImages!.isNotEmpty) {
imageFileList!.addAll(selectedImages);
}
print("Image List Length:" + imageFileList!.length.toString());
setState((){});
}
Create a builder for showing selected Images:
return Scaffold(
appBar: AppBar(
title: Text('Multiple Images'),
),
body: SafeArea(
child: Column(
children: [
ElevatedButton(
onPressed: () {
selectImages();
},
child: Text('Select Images'),
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: GridView.builder(
itemCount: imageFileList!.length,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3),
itemBuilder: (BuildContext context, int index) {
return Image.file(File(imageFileList![index].path),
fit: BoxFit.cover,);
}),
),
),
],
),
));
Complete Source code available in github link...
https://github.com/NishaJain24/multi_image_picker
I am new to Flutter. I try to load network images using image.network widget. it's working fine but sometimes it takes time to load. I added tap listener to image.network during tap I need to check image is fully loaded or not based on the result I need to redirect the page. how to check image is loaded or not?
Code:
new Image.network('http://via.placeholder.com/350x150')
Any help will be appreciated, thank you in advance
You may use the loadingBuilder which is inbuilt feature from flutter for Image.Network
I did it as below:
Image.network(imageURL,fit: BoxFit.cover,
loadingBuilder:(BuildContext context, Widget child,ImageChunkEvent loadingProgress) {
if (loadingProgress == null) return child;
return Center(
child: CircularProgressIndicator(
value: loadingProgress.expectedTotalBytes != null ?
loadingProgress.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes!
: null,
),
);
},
),
for this kind of issues it's good to use the cached_network_image
so you can provide a placeholder when the image is loading and an error widget in case a resource fails to load
String url = "http://via.placeholder.com/350x150";
CachedNetworkImage(
imageUrl: url,
placeholder: (context,url) => CircularProgressIndicator(),
errorWidget: (context,url,error) => new Icon(Icons.error),
),
for ones who do not need to cache the image can use meet_network_image package,
The package basic usage :
MeetNetworkImage(
imageUrl:
"https://random.dog/3f62f2c1-e0cb-4077-8cd9-1ca76bfe98d5.jpg",
loadingBuilder: (context) => Center(
child: CircularProgressIndicator(),
),
errorBuilder: (context, e) => Center(
child: Text('Error appear!'),
),
)
In addition, you can do that by yourself with using a FutureBuilder,
We need to get data with http call that way, we need to import http before import you also need to add pubspec.yaml and run the command flutter packages get
import 'package:http/http.dart' as http;
FutureBuilder(
// Paste your image URL inside the htt.get method as a parameter
future: http.get(
"https://random.dog/3f62f2c1-e0cb-4077-8cd9-1ca76bfe98d5.jpg"),
builder: (BuildContext context, AsyncSnapshot<http.Response> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
return Text('Press button to start.');
case ConnectionState.active:
case ConnectionState.waiting:
return CircularProgressIndicator();
case ConnectionState.done:
if (snapshot.hasError)
return Text('Error: ${snapshot.error}');
// when we get the data from the http call, we give the bodyBytes to Image.memory for showing the image
return Image.memory(snapshot.data.bodyBytes);
}
return null; // unreachable
},
);
This way it will start loading, then it will show the loading of the image loading and then the image. Best option if you don't want to use external libs.
Image.network(
imgUrl,
height: 300,
fit: BoxFit.contain,
frameBuilder: (_, image, loadingBuilder, __) {
if (loadingBuilder == null) {
return const SizedBox(
height: 300,
child: Center(child: CircularProgressIndicator()),
);
}
return image;
},
loadingBuilder: (BuildContext context, Widget image, ImageChunkEvent? loadingProgress) {
if (loadingProgress == null) return image;
return SizedBox(
height: 300,
child: Center(
child: CircularProgressIndicator(
value: loadingProgress.expectedTotalBytes != null
? loadingProgress.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes!
: null,
),
),
);
},
errorBuilder: (_, __, ___) => Image.asset(
AppImages.withoutPicture,
height: 300,
fit: BoxFit.fitHeight,
),
)
thank you for your comment thats help to resolve the situation that how to know if the image is loaded or not hope that help
I use a StatefulWidget
need a editing depend on your AffichScreen
situation :
-i have an url that i enter
-if url is correct affich the image if not affich an icon
-if empty affich a Text()
-precacheImage check if the url is correct if not give an error and change _loadingimage(bool) to false to affich the icon eror
-i use a NetworkImage to check with precacheImage and before affich use a Image.network
bool _loadingimage;
ImageProvider _image;
Image _imagescreen;
#override
void initState() {
_loadingimage = true;
_imageUrlfocusNode.addListener(_updateImageUrl);
super.initState();
}
#override
void dispose() {
_imageUrlfocusNode.removeListener(_updateImageUrl);
_quantityfocusNode.dispose();
_imageUrlConroller.dispose();
_imageUrlfocusNode.dispose();
super.dispose();
}
void _updateImageUrl() {
setState(() {
_image = NetworkImage(_imageUrlConroller.text);
});
if (!_imageUrlfocusNode.hasFocus) {
if (_imageUrlConroller.text.isNotEmpty) {
setState(() {
loadimage();
});
}
}
}
void loadimage() {
_loadingimage = true;
precacheImage(_image, context, onError: (e, stackTrace) {
// log.fine('Image ${widget.url} failed to load with error $e.');
print('error $e');
setState(() {
_loadingimage = false;
print(_loadingimage);
});
});
if (_loadingimage == true) {
_imagescreen = Image.network(
_imageUrlConroller.text,
fit: BoxFit.fill,
);
}
}
Container(
width: 100,
height: 100,
margin: EdgeInsets.only(top: 13, right: 11),
decoration: BoxDecoration(
border: Border.all(
width: 1,
color: Colors.grey,
),
),
child:_imageUrlConroller.text.isEmpty
? Text('enter an url')
: !_loadingimage
? Container(
child: Icon(Icons.add_a_photo),
)
: Container(
child: _imagescreen,
),
),