Convert a Stack Widget's content to an image [closed] - android

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I can overlay images using the Stack Widget in Flutter, but how to convert that overlayed widgets to a real image in png or jpeg format that users can save on their phone?
Context: I want to make a logo maker app, I have image assets in my project, the user may combine these assets to make a logo.

You can use RepaintBoundary for that.
Check this link,
regarding saving image to disk, you need to process the bytes taken, you can use the image package (made mostly for dart, but 100% compatible with flutter).
As you see, the code is very simple once you convert the bytes between Flutter Image and image:image
new File('thumbnail.png').writeAsBytesSync(encodePng(convertedBytes));
You can check this prototype code I made yesterday for a similar question regarding reading image pixels in Flutter.
Once you've got the Image bytes, you can stream it to a file in disk (using path_provider or similar to find the File's path in each OS), or upload it somewhere, like the first article.
Good luck with the implementation!

Try the following code it takes the screenshot of the screen and save the file in the internal storage.
pubspec.yaml
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^0.1.2
# package for saving the screenshot
image_picker_saver: ^0.1.0
main.dart
import 'dart:io';
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:image_picker_saver/image_picker_saver.dart';
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
debugShowCheckedModeBanner: false,
);
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
static GlobalKey screenshotKey = new GlobalKey(); // key
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: RepaintBoundary(
key: screenshotKey,
child: Container(
width: double.infinity,
color: Colors.white,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
RaisedButton(
child: Text("Take a screenshot"),
onPressed: _takeScreenShot,
)
],
),
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
void _takeScreenShot() async {
RenderRepaintBoundary boundary =
screenshotKey.currentContext.findRenderObject();
ui.Image image = await boundary.toImage();
ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
Uint8List pngBytes = byteData.buffer.asUint8List();
print(pngBytes);
var filePath = await ImagePickerSaver.saveFile(fileData: pngBytes);
print(filePath);
}
}

Related

flutter Problem in vs code (Unable to Load asset)

I'm having a problem in flutter on vs code
I imported the audioplayers
here's my pubspec.yaml
here's my homepage where I call the audio players
import 'package:flutter/material.dart';
import 'package:audioplayers/audioplayers.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
#override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.brown,
title: Text('anghami'),
),
body: Container(
color: Colors.brown[200],
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Card(
child: ListTile(
title: Text(
"benab",
style: TextStyle(color: Colors.red),
),
//tileColor: Colors.red,
leading: Icon(Icons.music_note),
iconColor: Colors.red,
onTap: () async {
final player = AudioPlayer();
await player
.setSource(AssetSource('assets/music/music1.mp3'));
},
),
),
],
),
),
),
);
}
}
whenever i try to play the music from the phone I get this error
P.S: the vs code has no problem in loading images or using other type of assets .
i've tried using Audiocache it doesn't work especially they deleted it in the last version ^1.1.1 ,
[enter image description here][https://i.stack.imgur.com/u9kKR.png]
It seems you trying to load an asset in /assets/assets/music/ folder.
My guess is that you want to load an asset in /assets/music/ folder and it's a simple mistake.
To fix that:
// Replace the relative path of your asset below:
// assets/music/music1.mp3 -> music/music1.mp3
await player.setSource(AssetSource('music/music1.mp3'));
Just remove assets from your audio source like this:
await player.setSource(AssetSource('music/music1.mp3'));
Firstly, create a assets directory on the root of your project , then create music folder.
Try to play with
await player.setSource(AssetSource('music/music1.mp3'));
Hello guys the solutions here are useful , so the main problem that I had was in the path so after correction it loaded the asset in a normal way,
but instead of just loading the asset you want it to play obviously and that's guaranteed by using :
**final player = AudioPlayer();**
**await player.play(AssetSource('music/music1.mp3'));**

flutter web : When I image upload to storage, I can't control the quality of the image picker

The sdk that I use is as follows.
sdk: ">=2.7.0 <3.0.0"
image_picker: ^0.6.7
image_picker_for_web: ^0.1.0
firebase_storage: ^3.1.6
cloud_firestore: ^0.13.7
When uploading an image to storage, I try to reduce the size of the image file.
And this is the code for image upload.
import 'package:image_picker/image_picker.dart';
import 'package:firebase/firebase.dart' as fb;
import 'package:omd_test/widget/custom_loading.dart';
class TestScreen extends StatefulWidget {
#override
State<TestScreen> createState() => _TestScreenState();
}
class _TestScreenState extends State<TestScreen> {
PickedFile _image;
String imageUrl;
#override
Widget build(BuildContext context) {
return SafeArea(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Scaffold(
appBar: AppBar(
title: Text("TEST"),
),
body: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
children: [
Container(
width: 200,
height: 200,
child: _image == null
? Container()
: Image.network(
_image.path,
)),
TextButton(
onPressed: () {
_getImagesPicker();
},
child: Text(
"Pick",
style: TextStyle(color: Colors.black),
)),
SizedBox(
height: 20,
),
TextButton(
onPressed: () async {
if (_image != null) {
await imageUpload(_image);
setState(() {
_image = null;
});
} else
print("No Image");
},
child: Text(
"Upload"
)),
],
),
),
),
),
);
}
Future<void> _getImagesPicker() async {
try {
final _imagePath = await ImagePicker().getImage(
source: ImageSource.gallery,
imageQuality: 10,
maxHeight: 50,
maxWidth: 50
);
setState(() {
_image = _imagePath;
});
} catch (err) {
print(err);
}
}
Future<String> imageUpload(PickedFile image) async {
var bytes = await image.readAsBytes();
fb.StorageReference _storage =
fb.storage().ref('testScreen/${image.path}.jpg');
fb.UploadTaskSnapshot uploadTaskSnapshot = await _storage
.put(bytes, fb.UploadMetadata(contentType: 'image/png'))
.future;
var imageUri = await uploadTaskSnapshot.ref.getDownloadURL();
imageUrl = imageUri.toString();
return imageUrl;
}
}
I tested by changing the value of 'imageQuality' of ImagePicker, but when uploaded to storage, all image files were the same size.
enter image description here
Can I know what the problem is?
Is it a problem to upload to storage?
Thank you.
From the image_picker repository, there's some inconsistency in what adjustments can be made to what type of images.
Here's an overview that might give some important lead.
Can I know what the problem is?
The comments in the actual implementation of the package has some lines[here]:
//Note that the `maxWidth`, `maxHeight` and `imageQuality` arguments are not supported on the web. If any of these arguments is supplied, it'll be silently ignored by the web version of the plugin.
However, there's still an implementation of the resizing of a selected image though.
Is it a problem to upload to storage?
Seemingly no.
Here's what you may wish to try going forward; run your app on other platforms and try to establish if the image is resized, this will help you single out if it's only on the web that the quality is not being adjusted.
If you establish this to be so, you may wish to have your own implementation of quality/size adjustment of the picked media, you can utilise kIsWeb boolean property to determine if it's web, then apply your own implementation.
if(kIsWeb){
//Adjust quality/size
}else{
//use the already adjusted media
}
Note this comment as well:
//Compression is only supported for certain image types such as JPEG and on Android PNG and WebP, too. If compression is not supported for the image that is picked, a warning message will be logged.

(Flutter) ListView has unnecessary spaces between items containing only images

My app requires a list view of images retrieved from a remote source to be displayed in a list. The images found below originate from the site randomuser.me and is free to use (testing, etc)
Problem:
The images are retrieved correctly and are displaying (these images are 128x128, but naturally sizes can change), however there are extremely large gaps between the images (height/width dimensions have been used nor fit options - I have previously used this to attempt to address the issue with no success).
Suggestions are to use ListTile and various solutions around this by setting dense: true or removing ListView padding and a few others, however non of these have worked.
I played around with large images - these fill up the entire screen, and I can scale them down, BUT when scaling these images, there are still large empty spaces left inbetween (expected) - these same gaps are seen in my case with NO scaling done.
MVCE
import 'package:flutter/material.dart';
void main() async {
runApp(MaterialApp(home: MyApp()));
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
List<String> imgSrc = [
"https://randomuser.me/api/portraits/women/84.jpg",
"https://randomuser.me/api/portraits/men/82.jpg",
"https://randomuser.me/api/portraits/women/11.jpg",
"https://randomuser.me/api/portraits/women/61.jpg",
"https://randomuser.me/api/portraits/men/1.jpg",
];
Widget listview() {
List<Widget> imgList = imgSrc.map((e) => Image.network(e)).map((e) => Image(image: e.image,)).toList();
return ListView(
children: imgList,
);
}
return Scaffold(
body: Container(
width: double.infinity,
child: listview()),
);
}
}
Want to create something like this:
I am not sure what is causing these spaces inbetween - advice would be appreciated!
Update
After playing around with it a little more, the only way I can get it to work as shown in the desired result it to add atleast 1 hardcoded dimension and use BoxFit.scaleDown which will scale based on the given dimension.
Example:
List<Widget> imgList = imgSrc
.map((e) => Image.network(e))
.map((e) => Image(
image: e.image,
fit: BoxFit.scaleDown,
height: 64,
))
.toList();
Yes, you need the fit parameter and try different options from (https://api.flutter.dev/flutter/painting/BoxFit-class.html) and see what would work for you. I've cleaned the code a bit while trying answer the questions and posting here.
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.purple,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
List a = [
"https://randomuser.me/api/portraits/women/84.jpg",
"https://randomuser.me/api/portraits/men/82.jpg",
"https://randomuser.me/api/portraits/women/11.jpg",
"https://randomuser.me/api/portraits/women/61.jpg",
"https://randomuser.me/api/portraits/men/1.jpg",
];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Displaying Images"),
),
body: ListView.builder(
itemBuilder: (BuildContext ctx, int index) {
return Container(
child: Image(
image: NetworkImage(a[index]),
fit: BoxFit.fill,
),
);
},
itemCount: a.length,
),
);
}
}

How to implement in-app screenshot in flutter? [duplicate]

This question already has answers here:
How to take a screenshot of the current widget - Flutter
(4 answers)
Closed 2 years ago.
How can I implement the in-app screenshot functionality in flutter android?
I need this function to take a screenshot of the app screen and share the picture.
are there any plugins?
I have shared an example of code where I have used Screenshot plugin available on pub.dev along with permission handler and path provider plugin. Basically this plugin wraps your widgets inside RenderRepaintBoundary and creates an screenshot of your widget.
main.dart
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_gallery_saver/image_gallery_saver.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:screenshot/screenshot.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Screenshot 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> {
int _counter = 0;
File _imageFile;
//Create an instance of ScreenshotController
ScreenshotController screenshotController = ScreenshotController();
#override
void initState() {
// TODO: implement initState
super.initState();
_requestPermission();
}
_requestPermission() async {
Map<Permission, PermissionStatus> statuses = await [
Permission.storage,
].request();
final info = statuses[Permission.storage].toString();
print(info);
}
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: Container(
child: new Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Screenshot(
controller: screenshotController,
child: Column(
children: <Widget>[
Text(
'You have pushed the button this many times:' +
_counter.toString(),
),
FlutterLogo(),
],
),
),
_imageFile != null ? Image.file(_imageFile) : Container(),
],
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () async {
_incrementCounter();
_imageFile = null;
screenshotController
.capture(delay: Duration(milliseconds: 10))
.then((File image) async {
//print("Capture Done");
setState(() {
_imageFile = image;
});
final result =
await ImageGallerySaver.saveImage(image.readAsBytesSync());
print("File Saved to Gallery $result");
}).catchError((onError) {
print("Error: $onError");
});
},
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
_saved(File image) async {
final result = await ImageGallerySaver.saveImage(image.readAsBytesSync());
print("File Saved to Gallery");
}
}
Packages used:
screenshot:
image_gallery_saver: ^1.1.0
permission_handler:
path_provider: ^1.6.24
You will need to specify storage permissions in AndroidManifest file as below:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
To take screenshots within flutter app of the current use this screenshot package it also has example and documentation for saving the image to a folder and as well as to gallery which can also be google photos using 2 other plugins which you can find there only. I have used this plugin and it works really well if you havep any queries then you can comment below. Hope this helps you out!

Open Flutter Application Using Dynamic Links [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I'm building a flutter application, and am having some trouble actually opening the app using the firebase_dynamic_links package. I basically took the example code found at https://pub.dev/packages/firebase_dynamic_links#-example-tab- in order to get started, but changed the information in their example to match my own firebase project (which has been setup in both android and iOS, but this testing has all been done with iOS).
I will include code and more useful information below, but I was really just hoping to get a simplified example of how this process should work. I have searched online quite a bit, following different tutorials, but none of them have done the trick for me. It could just be that I'm quite new to flutter, and am missing basic things. In my final application, I will be using dynamic links to allow users to invite other users to join the app (as well as groups within the app) via text, just to give context as to why it is needed.
Here is the code for what I have so far, but as I mentioned it is largely based off of the example from the link above.
main.dart
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'dart:io' show Platform;
import 'package:flutter/material.dart';
import 'package:firebase_dynamic_links/firebase_dynamic_links.dart';
import 'package:flutter/services.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:shopsync/helloworld.dart';
void main() async {
//Setup firebase connection
WidgetsFlutterBinding.ensureInitialized();
final FirebaseApp app = await FirebaseApp.configure(
name: 'shop-sync-d97d8',
options: Platform.isIOS
? const FirebaseOptions(
googleAppID: 'my_googleAppID',
gcmSenderID: 'my_senderID',
databaseURL: 'https://shop-sync-d97d8.firebaseio.com',
apiKey: 'AIzaSyC1TdwTs_KRXMGG2oIAGMX8v48HWqS62dc',
)
: const FirebaseOptions(
googleAppID: 'my_googleAppID',
apiKey: 'myApiKey',
databaseURL: 'my_url',
),
);
runApp(MaterialApp(
title: 'Dynamic Links Example',
routes: <String, WidgetBuilder>{
'/': (BuildContext context) => _MainScreen(),
'/helloworld': (BuildContext context) => HelloWorldScreen(),
},
));
}
class _MainScreen extends StatefulWidget {
#override
State<StatefulWidget> createState() => _MainScreenState();
}
class _MainScreenState extends State<_MainScreen> {
String _linkMessage;
bool _isCreatingLink = false;
String _testString =
"To test: long press link and then copy and click from a non-browser "
"app. Make sure this isn't being tested on iOS simulator and iOS xcode "
"is properly setup. Look at firebase_dynamic_links/README.md for more "
"details.";
#override
void initState() {
super.initState();
initDynamicLinks();
}
void initDynamicLinks() async {
final PendingDynamicLinkData data =
await FirebaseDynamicLinks.instance.getInitialLink();
final Uri deepLink = data?.link;
if (deepLink != null) {
Navigator.pushNamed(context, deepLink.path);
}
FirebaseDynamicLinks.instance.onLink(
onSuccess: (PendingDynamicLinkData dynamicLink) async {
final Uri deepLink = dynamicLink?.link;
if (deepLink != null) {
Navigator.pushNamed(context, deepLink.path);
}
}, onError: (OnLinkErrorException e) async {
print('onLinkError');
print(e.message);
});
}
Future<void> _createDynamicLink(bool short) async {
setState(() {
_isCreatingLink = true;
});
final DynamicLinkParameters parameters = DynamicLinkParameters(
uriPrefix: "https://shopsync.page.link",
link: Uri.parse("https://shopsync.page.link/helloworld"),
androidParameters: AndroidParameters(
packageName: 'com.chrismcdonnell.shopsync',
minimumVersion: 0,
),
dynamicLinkParametersOptions: DynamicLinkParametersOptions(
shortDynamicLinkPathLength: ShortDynamicLinkPathLength.short,
),
iosParameters: IosParameters(
bundleId: 'com.chrismcdonnell.shopsync',
minimumVersion: '0',
),
);
Uri url;
if (short) {
final ShortDynamicLink shortLink = await parameters.buildShortLink();
url = shortLink.shortUrl;
} else {
url = await parameters.buildUrl();
}
setState(() {
_linkMessage = url.toString();
_isCreatingLink = false;
});
}
#override
Widget build(BuildContext context) {
return Material(
child: Scaffold(
appBar: AppBar(
title: const Text('Dynamic Links Example'),
),
body: Builder(builder: (BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ButtonBar(
alignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
onPressed: !_isCreatingLink
? () => _createDynamicLink(false)
: null,
child: const Text('Get Long Link'),
),
RaisedButton(
onPressed: !_isCreatingLink
? () => _createDynamicLink(true)
: null,
child: const Text('Get Short Link'),
),
],
),
InkWell(
child: Text(
_linkMessage ?? '',
style: const TextStyle(color: Colors.blue),
),
onTap: () async {
if (_linkMessage != null) {
await launch(_linkMessage);
}
},
onLongPress: () {
Clipboard.setData(ClipboardData(text: _linkMessage));
Scaffold.of(context).showSnackBar(
const SnackBar(content: Text('Copied Link!')),
);
},
),
Text(_linkMessage == null ? '' : _testString)
],
),
);
}),
),
);
}
}
class _DynamicLinkScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Material(
child: Scaffold(
appBar: AppBar(
title: const Text('Hello World DeepLink'),
),
body: const Center(
child: Text('Hello, World!'),
),
),
);
}
}
helloworld.dart
//IMPORT NEEDED PACKAGES
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
//CREATE STATEFUL WIDGET
class HelloWorldScreen extends StatefulWidget {
#override
_HelloWorldScreen createState() => _HelloWorldScreen();
}
//CREATE STATE WIDGET
class _HelloWorldScreen extends State<HelloWorldScreen> {
#override
Widget build(BuildContext context) {
//Since this class represents an entire screen, return a scaffold with elements inside it
return Scaffold(
backgroundColor: Colors.white,
//Create AppBar w/ title "My Account"
appBar: AppBar(
title: Text('Hello World'),
automaticallyImplyLeading: false,
),
//Most of the content of the screen will go here
body: SafeArea(
child: Text('Testing'),
),
);
}
}
And lastly, here is the dynamic link I created within the console for testing. Although the final version of the application will create them programatically.
If anything else is needed please let me know. Any help would be greatly appreciated.

Categories

Resources