Flutter with Getx ImagePicker does not work properly - flutter

Why does the image update only when I save file?
image_picker version
image_picker: ^0.8.4+3
My Code related to ImagePicker
// image_picker_controller.dart
// controller
import 'dart:io';
import 'package:get/get.dart';
import 'package:image_picker/image_picker.dart';
class ImagePickerController extends GetxController {
File? pickedImageFile;
var seletedImagePath = ''.obs;
void _pickImage() async {
final picker = ImagePicker();
// final pickedImage = await picker.pickImage(source: ImageSource.gallery);
final pickedImage = await picker.pickImage(source: ImageSource.camera);
if (pickImage != null) {
pickedImageFile = File(pickedImage!.path);
}
update();
}
void Function() get pickImage => _pickImage;
}
view page
// user_image_picker.dart
// page screen
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_chatting_app/src/controllers/image_picker_controller.dart';
import 'package:get/get.dart';
class UserImagePicker extends GetView<ImagePickerController> {
UserImagePicker({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Column(
children: [
CircleAvatar(
radius: 40,
backgroundColor: Colors.grey,
backgroundImage: controller.pickedImageFile != null
? FileImage(controller.pickedImageFile as File)
: null,
),
TextButton.icon(
onPressed: controller.pickImage,
icon: Icon(Icons.image),
label: Text('Add Image'),
),
],
);
}
}
You can have a look at what happens in this gif link
When I add image with ImagePicker, DEBUG CONSOLE shows below, and image isn't updated.
// DEBUG CONSOLE
D/MediaScannerConnection( 7062): Scanned /data/user/0/com.example.flutter_chatting_app/cache/bc149d80-91bb-487d-b2b7-3597357c4d182105624148556557573.jpg to null
but, after I save codes, the image appear. I think the state doens't update, but I have no idea why it happens.
I've googled about this problem, but I couldn't figure it out.
Please, somebody help me.

I used the default Stateless and GetBuilder combination and it worked:
class ImagePickerController extends GetxController {
File? pickedImageFile;
void _pickImage() async {
final picker = ImagePicker();
final pickedImage = await picker.pickImage(source: ImageSource.camera);
pickedImageFile = File(pickedImage!.path);
update();
}
void Function() get pickImage => _pickImage;
}
and the view:
class UserImagePicker extends StatelessWidget {
const UserImagePicker({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return GetBuilder<ImagePickerController>(builder: (logic) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
CircleAvatar(
radius: 40,
backgroundColor: Colors.grey,
backgroundImage: logic.pickedImageFile != null
? FileImage(logic.pickedImageFile as File)
: null,
),
TextButton.icon(
onPressed: logic.pickImage,
icon: const Icon(Icons.image),
label: const Text('Add Image'),
),
],
);
});
}
}

Related

increase font on webview Flutter

Help please, I have a WebView screen on which I display the site. This site adapts to the width of the mobile phone and reduces the font. Can I somehow increase the font?
body: Container(
child: WebView(
initialUrl: url,
javascriptMode: JavascriptMode.unrestricted,
),
),
Android is smart enough to identify html code without with viewport, but IOS does not. You have to explicitly set viewport to mobile device, like you make webapp responsive to mobile devices.
It's better to wrap annotation to render correctly.
This is what you need exactly to your code:
<!DOCTYPE html><html><head><meta name="viewport" content="width=device-width, initial-scale=1.0"></head><!--rest of your html-->
You can use the flutter_inappwebview plugin (I'm the author) to set custom text size/zoom to the whole web page.
On Android, we can use InAppWebViewSettings.textZoom property.
On iOS, we need to use JavaScript and set the text-size-adjust CSS property.
Here is a code example using the current latest version 6 available (6.0.0-beta.18):
import 'dart:collection';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
const kInitialTextSize = 100;
const kTextSizePlaceholder = 'TEXT_SIZE_PLACEHOLDER';
const kTextSizeSourceJS = """
window.addEventListener('DOMContentLoaded', function(event) {
document.body.style.textSizeAdjust = '$kTextSizePlaceholder%';
document.body.style.webkitTextSizeAdjust = '$kTextSizePlaceholder%';
});
""";
final textSizeUserScript = UserScript(
source: kTextSizeSourceJS.replaceAll(kTextSizePlaceholder, '$kInitialTextSize'),
injectionTime: UserScriptInjectionTime.AT_DOCUMENT_START);
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
if (!kIsWeb &&
kDebugMode &&
defaultTargetPlatform == TargetPlatform.android) {
await InAppWebViewController.setWebContentsDebuggingEnabled(kDebugMode);
}
runApp(const MaterialApp(home: MyApp()));
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final GlobalKey webViewKey = GlobalKey();
InAppWebViewController? webViewController;
int textSize = kInitialTextSize;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Custom Text Size"),
actions: [
IconButton(
onPressed: () async {
textSize++;
await updateTextSize(textSize);
},
icon: const Icon(Icons.add)),
IconButton(
onPressed: () async {
textSize--;
await updateTextSize(textSize);
},
icon: const Icon(Icons.remove)),
TextButton(
onPressed: () async {
textSize = kInitialTextSize;
await updateTextSize(textSize);
},
child: const Text(
'Reset',
style: TextStyle(color: Colors.white),
),
),
],
),
body: Column(children: <Widget>[
Expanded(
child: InAppWebView(
key: webViewKey,
initialUrlRequest:
URLRequest(url: WebUri("https://github.com/flutter")),
initialUserScripts: UnmodifiableListView(
!kIsWeb && defaultTargetPlatform == TargetPlatform.android
? []
: [textSizeUserScript]),
initialSettings: InAppWebViewSettings(textZoom: textSize),
onWebViewCreated: (controller) async {
webViewController = controller;
},
),
),
]));
}
updateTextSize(int textSize) async {
if (!kIsWeb && defaultTargetPlatform == TargetPlatform.android) {
await webViewController?.setSettings(
settings: InAppWebViewSettings(textZoom: textSize));
} else {
// update current text size
await webViewController?.evaluateJavascript(source: """
document.body.style.textSizeAdjust = '$textSize%';
document.body.style.webkitTextSizeAdjust = '$textSize%';
""");
// update the User Script for the next page load
await webViewController?.removeUserScript(userScript: textSizeUserScript);
textSizeUserScript.source =
kTextSizeSourceJS.replaceAll(kTextSizePlaceholder, '$textSize');
await webViewController?.addUserScript(userScript: textSizeUserScript);
}
}
}
Full project code example is available at https://github.com/pichillilorenzo/flutter_inappwebview_examples/tree/main/custom_text_size

How to add widget to appear only when sharing to social

I tried share package and it works but I want to add a Widget that only appears on the shared image, not on the app. So please help me this is the code so far:
import 'dart:ui';
import 'dart:io';
import 'package:path_provider/path_provider.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:share/share.dart';
void main() {
runApp(MaterialApp(home: HomePage()));
}
class HomePage extends StatelessWidget {
final _contentKey = GlobalKey();
final bool forSharing;
HomePage({
Key key,
this.forSharing = false,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: [
IconButton(
icon: const Icon(Icons.share),
onPressed: () => onTakeScreenShotAndSharing(
'Image',
_contentKey.currentContext,
),
),
],
),
body: RepaintBoundary(
key: _contentKey,
child: Column(
children: [
if (forSharing) Text('Text appear only for Sharing'), // This is the widget that I want it appear only on the shared image
Text('Content'),
],
),
),
);
}
void onTakeScreenShotAndSharing(String fileName, BuildContext context) async {
try {
RenderRepaintBoundary boundary = context.findRenderObject();
final image = await boundary?.toImage();
final bytes = await image?.toByteData(format: ImageByteFormat.png);
if (bytes == null || bytes.buffer == null) return;
final dir = (await getApplicationDocumentsDirectory()).path;
final file = File('$dir/$fileName${DateTime.now().toString()}.png');
final newFile = await file.writeAsBytes(bytes.buffer.asUint8List());
await Share.shareFiles([newFile.path]);
} catch (error) {
print(error);
}
}
}

Flutter Image.memory() loading animation with slow large files

I am fetching an image from the gallery and displaying it in my cropper with Image.memory(). But sometimes (with large files) it takes a few seconds for the image to show. I want to show a loading animation but how do I detect when it is loading or finished? There is no loadingBuilder like for Image.network(). Any ideas?
final XFile? image = await _picker.pickImage(source: ImageSource.gallery);
Image.memory(_imageToCrop!)
Like Ankit Kumar Maurya said I studied the frameBuilder documentation and this solved my issue:
Image.memory(
_imageToCrop!,
frameBuilder:
((context, child, frame, wasSynchronouslyLoaded) {
if (wasSynchronouslyLoaded) return child;
return AnimatedSwitcher(
duration: const Duration(milliseconds: 200),
child: frame != null
? child
: SizedBox(
height: 60,
width: 60,
child: CircularProgressIndicator(
strokeWidth: 6),
),
);
}),
),
you can maintain an enum for this,
enum State {idle, loading, done ,error}
now,
State fetchState = State.idle
void fetch()async{
setState((){
fetchState = State.loading;
});
try{
final XFile? image = await _picker.pickImage(source:
ImageSource.gallery);
Image.memory(_imageToCrop!);
setState((){
fetchState = State.done;
});
}catch(e){
setState((){
fetchState = State.error;
});
}
}
Now use this states in your widget tree to show loader when state is loading.
you can use a single boolean variable as said in other answer but with this method you can catch errors at run time. You can use this method for api calls also.
You should once check this documentation provided by flutter frame_builder. You could also use frameBuilder for your requirement.
May be my code will help you:-
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
void main() {
runApp(const MaterialApp(
title: 'Temp',
home: const MyApp(),
));
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
bool loading = false;
late Uint8List image;
XFile? file = null;
ImagePicker imagePicker = ImagePicker();
Future<void> pickImage() async {
print('starting');
setState(() {
loading = true;
});
file = await imagePicker.pickImage(source: ImageSource.gallery);
print('file');
if(file != null){
print(file.toString());
image = await file!.readAsBytes();
}
setState(() {
loading = false;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Image Picker'),
),
body: loading
? Container(
child: const Center(child: CircularProgressIndicator()),
)
: file != null?Container(child: Center(child: Image.memory(image),)) : Container(
child: const Center(child: Text('Pick an Image')),
),
floatingActionButton: FloatingActionButton(
child: const Icon(
Icons.image,
),
onPressed: (){
pickImage();
}),
);
}
}
Short Description - my code will fetch an image from the system and then show … I have used a loading widget while the image is fetching and being converted to bytes.
It might be helpful if you share your logic here to figure out the main problem(if missing any thing).

Flutter Image now showing properly/blue circle instead

I have a filePick function to select an image and display it as a profile picture (code bellow):
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:image_picker/image_picker.dart';
class TestScreen extends StatefulWidget {
const TestScreen({Key? key}) : super(key: key);
#override
_TestScreenState createState() => _TestScreenState();
}
class _TestScreenState extends State<TestScreen> {
PickedFile? pickedImage;
late File imageFile;
bool _load = true;
final picker = ImagePicker();
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: InkWell(
onTap: () async {
final pickedFile =
await picker.pickImage(source: ImageSource.gallery);
setState(() {
imageFile = File(pickedFile!.path);
_load = false;
});
},
child: _load == true
? Image.asset(
"images/null_pfp.png",
)
: CircleAvatar(
radius: 500,
backgroundImage: FileImage(imageFile),
),
),
),
);
}
}
But as you can see in this gif, every time I select any image (jpg), it only displays this blue circle.
Maybe there must be bug with "image_picker" ,
Please try to use : https://pub.dev/packages/image_picker_for_web

Flutter Error: Type 'File' not found. What's going on here?

I'm trying to use firebase_ml_vision with image_picker.
Here's the code:
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:firebase_ml_vision/firebase_ml_vision.dart';
void main() => runApp(MyHomePage());
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
FirebaseVisionImage visionImage;
final BarcodeDetector barcodeDetector = FirebaseVision.instance.barcodeDetector();
final TextRecognizer textRecognizer = FirebaseVision.instance.textRecognizer();
final ImageLabeler labeler = FirebaseVision.instance.imageLabeler(
ImageLabelerOptions(confidenceThreshold: 0.75),
);
final FaceDetector faceDetector = FirebaseVision.instance.faceDetector();
void detections() async {
final VisionText visionText = await textRecognizer.processImage(visionImage);
}
File _image;
Future getImage() async {
var image = await ImagePicker.pickImage(source: ImageSource.camera);
var something = await ImagePicker.pickImage(source: ImageSource.camera);
setState(() {
this.visionImage = FirebaseVisionImage.fromFile(something);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Image Picker Example'),
),
body: Center(
child: _image == null
? Text('No image selected.')
: Image.file(_image),
),
floatingActionButton: FloatingActionButton(
onPressed: getImage,
tooltip: 'Pick Image',
child: Icon(Icons.add_a_photo),
),
);
}
}
But I am unable to use the File datatype and this is the error I get:
Error
Here's what I get when I run flutter doctor:
Doctor
And here's what I get when I run flutter --version:
Version
I'm very new to Flutter so please let me know if you need anything else.
Thank you!
File type is in dart:io, which you are missing. Add import 'dart:io'; to the top of the file.