Reputation: 1338
I have been trying to add text on top of an image and then allow the user to share the image. I'm having two issues that I can't seem to figure out.
The text is overflowing off the screen and not wrapping in the TextPainter when adding to Canvas.
I have been trying to share the image using a FloatingActionButton. The issue I am having is sharing an actual image and not image string. I have been using the esys_flutter_share package to try and achieve it but I get an error. I really just want to share the Image that I wrote the text on top of.
Unhandled Exception: type 'Image' is not a subtype of type 'String'
.
Any help is greatly appreciated.
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:esys_flutter_share/esys_flutter_share.dart';
import 'package:flutter/services.dart' show rootBundle;
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
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 _MyHomePageState extends State<MyHomePage> {
var _imageUrl = 'https://imageurl.png';
var _img;
var nimg;
@override
void initState() {
_showImg();
super.initState();
}
@override
Widget build(BuildContext context) {
var widget =
_img != null ? Image.memory(_img) : Text('pleace click button');
return Scaffold(
appBar: AppBar(),
body: Center(child: widget),
floatingActionButton: FloatingActionButton(
onPressed: () async {
final ByteData bytes = await rootBundle.load(nimg);
await Share.file('esys image', '$nimg', bytes.buffer.asUint8List(), 'image/png');
},
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
_showImg() async{
var uri = Uri.parse(_imageUrl);
var httpClient = HttpClient();
var request = await httpClient.getUrl(uri);
var response = await request.close();
var imageData = <int>[];
await response.forEach((data) async {
imageData.addAll(data);
});
ui.Image image =
await decodeImageFromList(Uint8List.fromList(imageData));
var pictureRecorder = ui.PictureRecorder();
var canvas = Canvas(pictureRecorder);
var paint = Paint();
paint.isAntiAlias = true;
var src = Rect.fromLTWH(
0.0, 0.0, image.width.toDouble(), image.height.toDouble());
var dst = Rect.fromLTWH(
0.0, 0.0, image.width.toDouble(), image.height.toDouble());
canvas.drawRect(Rect.fromLTWH(0.0, 0.0, 200.0, 200.0), paint);
canvas.drawImageRect(image, src, dst, paint);
//Add text on image
TextSpan span = new TextSpan(
style: new TextStyle(color: Colors.white, fontSize: 150.0,
fontFamily: 'Roboto'), text: "Here is some great text to put on top");
TextPainter tp = new TextPainter(
text: span, textDirection: TextDirection.ltr, textAlign: TextAlign.center);
tp.layout();
tp.paint(canvas, new Offset(image.width/2 - image.width/2 /2, image.height/2 - image.height/2 /3));
var pic = pictureRecorder.endRecording();
ui.Image img = await pic.toImage(image.width, image.height);
var byteData = await img.toByteData(format: ui.ImageByteFormat.png);
var buffer = byteData.buffer.asUint8List();
//Assign image to be shared
nimg = img;
//Set the image as the child in the body
setState(() {
_img = buffer;
});
}
}
Upvotes: 4
Views: 2157
Reputation: 7601
The easiest way to share image with text:
Create a Stack and put Image in it, positioned the Text widget anywhere you want on the image.
Wrap Stack with RepaintBoundary
Screenshot with
RenderRepaintBoundary boundary = _globalKey.currentContext.findRenderObject();
Image image = await boundary.toImage();
PS. Of course you can also use image packages to add text to image.
Upvotes: 4
Reputation: 2154
esys_flutter_share
is not having capability of sharing both data type at a same time. I have faced this issue and fixed by taking this package in my code and editing it's methods that allows us to share both data type. Here is the edited package files.
How to take packages in local code?
Checkout this answer
The updated code url is this, download it and follow above answer.
Upvotes: 1