I want to implement twitter share in my flutter application.
I convert my widget to image by using RepaintBoundary and stored as ByteData as below.
Future<ByteData> convertWidgetToImage(GlobalKey key) async {
final RenderRepaintBoundary boundary =
key.currentContext!.findRenderObject() as RenderRepaintBoundary;
final image = await boundary.toImage();
final byteData = await image.toByteData(format: ui.ImageByteFormat.png);
return byteData!;
}
Then, I want to open twitter app with some default text and with this image data. (I can convert this bytedata to local file path url if needed as below)
Future<String> get _localPath async {
final directory = await getApplicationDocumentsDirectory();
return directory.path;
}
Is there any way I can share this image to twitter (onTap then open twitter app with this image)?
This could be an option but I don't think I can share twitter image
https://pub.dev/packages/social_share
Related
in my flutter app, the user picture is loaded by Cached Network image command, which gets its url by stream builder from firestore.
I am trying to add the functionality to the user of changing his pic by pressing on the pic as following:
Selecting his pic with image picker.
upload it to firebase storage.
updating firestore usercollection document with new image url.
I created the below code.
The problem is getDownloadURL() is not returning actual string, but "Instance of 'Future'".
so the new link stored in firestore is not correct to be used by Cached Network Image.
how can I get the actual URl String?
My Future Function Code:
Future ChangeProfilePic() async {
String newimageurl = "";
FirebaseStorage storage = FirebaseStorage.instance;
Reference ref =
storage.ref().child("ProfileImages/$globaluserid".toString());
CollectionReference userscollectionref =
FirebaseFirestore.instance.collection('UsersCollection');
final ImagePicker _picker = ImagePicker();
final XFile? image = await _picker.pickImage(source: ImageSource.gallery);
File imagefile = File(image!.path);
UploadTask uploadTask = ref.putFile(imagefile);
uploadTask.whenComplete(() {
newimageurl = ref.getDownloadURL().toString();
print("Image Uploaded");
userscollectionref
.doc(globaluserid)
.update({'User_image_link': newimageurl});
print("Link is Updated");
}).catchError((onError) {
print("Error");
print(onError);
});
}
Like many calls in your code `` is an asynchronous call, whose result won't be available immediately, so it returns a Future that will at some point contain the value. You can use await to wait for such a Future to complete and get its value, similar to what you already do in await _picker.pickImage.
await ref.getDownloadURL().toString();
Another change to consider is that putFile returns a Task, but that is actually also a Future, which means that you can await that too.
Combining these two fact, you can simplify your code to:
final XFile? image = await _picker.pickImage(source: ImageSource.gallery);
File imagefile = File(image!.path);
await ref.putFile(imagefile);
newimageurl = (await ref.getDownloadURL()).toString();
print("Image Uploaded");
userscollectionref
.doc(globaluserid)
.update({'User_image_link': newimageurl});
print("Link is Updated");
I want to download widgets screenshots as an image file in flutter Web. Is there any to do this?
By the way for converting the widget to Uint8List, I am using the screenshot plugin.
You can use the RenderRepaintBoundary.toImage() function to convert the widget into an image. Then you convert to byteData, then to Uint8list, then do a base64encode on that Uint8List and basically make the widget an anchor element which you can then download.
I've attached some sample code from a project that I was working on that lets the user generate a QR code and download it to the downloads folder on their PC to show what I'm talking about.
Make sure you've imported html at top of dart file:
import 'dart:html' as html;
Then, the code would look something like:
final key = GlobalKey();
final qrTextController = TextEditingController();
//this code "wraps" the qr widget into an image format
RenderRepaintBoundary boundary = key.currentContext!
.findRenderObject() as RenderRepaintBoundary;
//captures qr image
var image = await boundary.toImage();
String qrName = qrTextController.text;
//running on web
if(kIsWeb){
print('registering as a web device');
ByteData? byteData = await image.toByteData(format: ImageByteFormat.png);
Uint8List pngBytes = byteData!.buffer.asUint8List();
final _base64 = base64Encode(pngBytes);
final anchor =
html.AnchorElement(href: 'data:application/octet-stream;base64,$_base64')
..download = "image.png"
..target = 'blank';
html.document.body!.append(anchor);
anchor.click();
anchor.remove();
}
There is the way to save the widget into transparent png and save it into gallery?
Thanks in advance.
Flutter draws every single pixel, so you can easily convert your widget to an image.
You need to follow these steps:
Edit -- first import path_provider link to pupspec.yaml and then follow this steps
Create a GlobalKey
final _globalKey = GlobalKey();
Create Uint8List
Uint8List pngBytes;
Wrap your widget with RepaintBoundary widget & pass in the key
RepaintBoundary(
key: _globalKey,
child: YourWidget(),
),
Create a method to convert your widget to image:
Future<void> _capturePng() async {
try {
final RenderRepaintBoundary boundary =
_globalKey.currentContext.findRenderObject();
final image = await boundary.toImage(pixelRatio: 2.0); // image quality
final byteData = await image.toByteData(format: ui.ImageByteFormat.png);
pngBytes = byteData.buffer.asUint8List();
} catch (e) {
print(e);
}
}
Convert your image to a file so that you can save it in your app
Future<File> convertImageToFile(Uint8List image) async {
final file = File(
'${(await
getTemporaryDirectory()).path}/${DateTime.now().millisecondsSinceEpoch}.png');
await file.writeAsBytes(image);
return file;
}
https://pub.dev/packages/share
Dependency:
share: ^0.6.5+2
Local file directory
Future<String> get _localPath async {
final directory = await getApplicationDocumentsDirectory();
return directory.path;
}
Share function
Future<void> _onShare(BuildContext context) async {
final RenderBox box = context.findRenderObject();
final path = await _localPath;
await Share.shareFiles(
['$path/assets/images/${widget.imgUrl}.png'],
text: text,
sharePositionOrigin: box.localToGlobal(Offset.zero) & box.size);
}
Button - on press
FlatButton(child: Text('Share'), onPressed: () => _onShare(context)),
I'm using this package to share image from application. I have no issue sharing text but when I add the function to share image, I keep getting errors for missing image.
Am I doing it correctly?
Managed to figure out the problem.
Seems like I need to save image before I can reference the image.
final ByteData bytes = await rootBundle
.load('assets/images/${widget.imgUrl}.png');
final Uint8List list = bytes.buffer.asUint8List();
final directory = (await getExternalStorageDirectory()).path;
File imgFile = File('$directory/screenshot.png');
imgFile.writeAsBytesSync(list);
Share.shareFiles(['$directory/screenshot.png'],
sharePositionOrigin: box.localToGlobal(Offset.zero) & box.size);
I'm making an app that takes a screenshot of the entire screen when clicking a button. Apparently the image goes to:
/storage/emulated/0/Android/data/com.example.program-name/files
I have tested this using the android emulator as well as my physical device. The path name changes slightly, but I still have no access to this image.
I am using the following code in order to take the screenshot and save it:
takeScreenShot() async{
RenderRepaintBoundary boundary = globalKey.currentContext.findRenderObject();
ui.Image image = await boundary.toImage();
final directory = (await getExternalStorageDirectory()).path;
print(directory);
ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
Uint8List pngBytes = byteData.buffer.asUint8List();
File imgFile = new File('$directory/screenshot.png');
print (imgFile.toString());
imgFile.writeAsBytes(pngBytes);
}
Is there anyway to:
Access this file and move it elsewhere on the computer/phone or,
Change the following directory to one that goes to any file on your computer?
final directory = (await getExternalStorageDirectory()).path;
The idea would be to save user data on a form and save an image of the page that was just filled in for future reference. i.e. submit form, save screenshot-image to PC desktop gallery, for example.
There are issues on this. #48208 #35783
On Android you can write path by yourself.
Future<void> _screenshot() async {
RenderRepaintBoundary boundary = globalKey.currentContext.findRenderObject();
ui.Image image = await boundary.toImage();
ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
Uint8List pngBytes = byteData.buffer.asUint8List();
Directory d = Directory('/storage/emulated/0');
if (d.existsSync()) {
Directory(d.path + '/MyApp').createSync();
File imgFile = new File(d.path + '/MyApp/screenshot.png');
print('saving to ${imgFile.path}');
imgFile.createSync();
imgFile.writeAsBytes(pngBytes);
}
}