Should i put CameraController to getxController? - flutter

I saw in the getx documents that GetxController is business logic class. When i try to seperate business logic in widget, i have an issue about some controllers such as CameraController, QRViewController,MediaPlayer,... Should i put all things in GetxController or keep this in widget?
qr_code.dart
import 'dart:developer';
import 'dart:io';
import 'package:clean_architecture_getx/controller/qr_code/qr_code_controller.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:qr_code_scanner/qr_code_scanner.dart';
class QrCodeScreen extends StatefulWidget {
const QrCodeScreen({Key? key}) : super(key: key);
#override
State<StatefulWidget> createState() => _QrCodeScreenState();
}
class _QrCodeScreenState extends State<QrCodeScreen> {
final scanQrController = Get.put(ScanQrController());
QRViewController? qrViewController;
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
// In order to get hot reload to work we need to pause the camera if the platform
// is android, or resume the camera if the platform is iOS.
#override
void reassemble() {
super.reassemble();
if (Platform.isAndroid) {
qrViewController!.pauseCamera();
}
qrViewController!.resumeCamera();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Expanded(flex: 4, child: _buildQrView(context)),
Expanded(
flex: 1,
child: FittedBox(
fit: BoxFit.contain,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Obx(() {
if (scanQrController.result.value.code != null) {
return Text(
'Barcode Type: ${describeEnum(scanQrController.result
.value.format)} Data: ${scanQrController.result
.value.code}');
} else {
return const Text('Scan a code');
}
}),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
margin: const EdgeInsets.all(8),
child: ElevatedButton(
onPressed: () async {
await qrViewController?.toggleFlash();
setState(() {});
},
child: FutureBuilder(
future: qrViewController?.getFlashStatus(),
builder: (context, snapshot) {
return Text('Flash: ${snapshot.data}');
},
)),
),
Container(
margin: const EdgeInsets.all(8),
child: ElevatedButton(
onPressed: () async {
await qrViewController?.flipCamera();
setState(() {});
},
child: FutureBuilder(
future: qrViewController?.getCameraInfo(),
builder: (context, snapshot) {
if (snapshot.data != null) {
return Text(
'Camera facing ${describeEnum(
snapshot.data!)}');
} else {
return const Text('loading');
}
},
)),
)
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
margin: const EdgeInsets.all(8),
child: ElevatedButton(
onPressed: () async {
await qrViewController?.pauseCamera();
},
child: const Text('pause',
style: TextStyle(fontSize: 20)),
),
),
Container(
margin: const EdgeInsets.all(8),
child: ElevatedButton(
onPressed: () async {
await qrViewController?.resumeCamera();
},
child: const Text('resume',
style: TextStyle(fontSize: 20)),
),
)
],
),
],
),
),
)
],
),
);
}
Widget _buildQrView(BuildContext context) {
// For this example we check how width or tall the device is and change the scanArea and overlay accordingly.
var scanArea = (MediaQuery
.of(context)
.size
.width < 400 ||
MediaQuery
.of(context)
.size
.height < 400)
? 150.0
: 300.0;
// To ensure the Scanner view is properly sizes after rotation
// we need to listen for Flutter SizeChanged notification and update controller
return QRView(
key: qrKey,
onQRViewCreated: _onQRViewCreated,
overlay: QrScannerOverlayShape(
borderColor: Colors.red,
borderRadius: 10,
borderLength: 30,
borderWidth: 10,
cutOutSize: scanArea),
onPermissionSet: (ctrl, p) => _onPermissionSet(context, ctrl, p),
);
}
void _onQRViewCreated(QRViewController controller) {
setState(() {
this.qrViewController = controller;
});
controller.scannedDataStream.listen((scanData) {
debugPrint('barcode: ${scanData.code}');
scanQrController.updateBarCode(scanData);
});
}
void _onPermissionSet(BuildContext context, QRViewController ctrl, bool p) {
log('${DateTime.now().toIso8601String()}_onPermissionSet $p');
if (!p) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('no Permission')),
);
}
}
#override
void dispose() {
qrViewController?.dispose();
super.dispose();
}
}
qr_code_controller.dart
import 'package:get/get.dart';
import 'package:qr_code_scanner/qr_code_scanner.dart';
class ScanQrController extends GetxController {
final result = Barcode(null, BarcodeFormat.unknown, null).obs;
void onQrViewCreated(QRViewController controller) {}
void updateBarCode(Barcode barcode) {
result.value = barcode;
}
}
Should i put QRViewController to ScanQrController (GetxController) or keep it in widget?

Put the UI in a view, and put the business logic inside a controller. Have a GetX Controller per feature. It would be more helpful if you could provide an example of your code.

Related

Implement qrview for TargetPlatform.linux to Scan QR Code in Flutter

I wish to scan a QR Code in Flutter and I'm running on Linux and Chrome (web) without any mobile device. When I run my code, I get the following error:
Unsupported operation: Trying to use the default qrview implementation for
TargetPlatform.linux but there isn't a default one
Here is a snippet of the code to scan the QR code
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:qr_code_scanner/qr_code_scanner.dart';
import 'package:url_launcher/url_launcher.dart';
class Scanner extends StatefulWidget {
const Scanner({super.key});
#override
_ScannerState createState() => _ScannerState();
}
class _ScannerState extends State<Scanner> {
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
late QRViewController controller;
#override
void dispose() {
controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Center(child: Text("Scan the Building QR Code"),),
),
body: Stack(
children: [
Column(
children: <Widget>[
Expanded(
flex: 4,
child: Stack(
children: [
QRView(
key: qrKey,
onQRViewCreated: _onQRViewCreated,
),
Center(
child: Container(
width: 300,
height: 300,
decoration: BoxDecoration(
border: Border.all(
color: Colors.black,
width: 4,
),
borderRadius: BorderRadius.circular(12),
),
),
)
],
),
),
],
),
],
),
);
}
void _onQRViewCreated(QRViewController controller) {
this.controller = controller;
controller.scannedDataStream.listen((scanData) async {
controller.pauseCamera();
// ignore: deprecated_member_use
if (await canLaunch(scanData.code)) {
// ignore: deprecated_member_use
await launch(scanData.code);
controller.resumeCamera();
} else {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Could not find viable URL'),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
Text('Barcode Type: ${describeEnum(scanData.format)}'),
Text('Data: ${scanData.code}'),
],
),
),
actions: <Widget>[
TextButton(
child: const Text('OK'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
).then((value) => controller.resumeCamera());
}
});
}
}
And this is the screen that I get:
The package does only support the Android & iOS platform s you can see on https://pub.dev/packages/qr_code_scanner

splash screen before webview loads in flutter

I am trying to build an app that uses webview but before loading it I need an splashscreen that checks if there is internet connection and if there isn't it shows an Snackbar in splashscreen. Do you know how to achieve this?
Use this plugin
https://pub.dev/packages/connectivity_plus
Future<bool> checkInternet() async {
var connectivityResult = await (Connectivity().checkConnectivity());
if (connectivityResult == ConnectivityResult.mobile) {
return true;
} else if (connectivityResult == ConnectivityResult.wifi) {
return true;
}
return false;
}
Use it like this
if (!(await checkInternet())) {
///show your snackBar here
}
This would help. I achieved this in my personal project.
As you can see am using internet_connection_checker and whenever the internet is down I do a retry which was achieved by calling a restart widget in the main method to safely perform a restart whenever the internet is restored
Splash Page
import 'dart:async';
import 'package:airduka/main.dart';
import 'package:airduka/models/user_model.dart';
import 'package:airduka/widgets/color.dart';
import 'package:airduka/widgets/custom_navigations.dart';
import 'package:airduka/widgets/small_text.dart';
import 'package:flutter/material.dart';
import 'package:internet_connection_checker/internet_connection_checker.dart';
import 'package:page_transition/page_transition.dart';
class SplashPage extends StatefulWidget {
final String title, description, time;
final UserModel? user;
final List<dynamic>? listMsg;
const SplashPage({Key? key, this.listMsg, required this.title, required this.description, required this.time, this.user}) : super(key: key);
#override
_SplashPageState createState() => _SplashPageState();
}
class _SplashPageState extends State<SplashPage> {
Timer? timer;
Future<InternetConnectionStatus> dataConnection() async{
InternetConnectionStatus statusMain = InternetConnectionStatus.disconnected;
final StreamSubscription<InternetConnectionStatus> listener =
InternetConnectionChecker().onStatusChange.listen(
(InternetConnectionStatus status) {
switch (status) {
case InternetConnectionStatus.connected:
statusMain = InternetConnectionStatus.connected;
break;
case InternetConnectionStatus.disconnected:
statusMain = InternetConnectionStatus.disconnected;
break;
}
},
);
// close listener after 30 seconds, so the program doesn't run forever
await Future<void>.delayed(const Duration(seconds: 1));
await listener.cancel();
return statusMain;
}
#override
void initState() {
timer = Timer(
const Duration(seconds: 5),() => Navigator.pushReplacement(
context,
PageTransition(
child: FutureBuilder<InternetConnectionStatus>(
future: dataConnection(),
builder: (context, AsyncSnapshot snapshot) {
switch(snapshot.connectionState){
case ConnectionState.none:
case ConnectionState.waiting:
return Scaffold(
extendBodyBehindAppBar: true,
backgroundColor: const Color(0xFF00639E),
body: Center(
child: Image.asset(
"assets/animations/jety.gif",
height: 200,
),
),
);
default:
if(snapshot.hasError)
return Scaffold(
extendBodyBehindAppBar: true,
backgroundColor: const Color(0xFF00639E),
body: Center(
child: Image.asset(
"assets/animations/jety.gif",
height: 200,
),
),
);
else if(snapshot.data == InternetConnectionStatus.disconnected)
return Scaffold(
extendBodyBehindAppBar: true,
backgroundColor: const Color(0xFF00639E),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Center(
child: Image.asset(
"assets/animations/jety.gif",
height: 200,
),
),
const SmallTextWidget(text: "You seem to be offline", color: AppColors.whiteThemeColor,),
const SizedBox(height: 8.0,),
InkWell(
onTap: (){
RestartWidget.restartApp(context);
},
child: Container(
height: 45,
width: 100,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
color: AppColors.whiteThemeColor
),
child: const Center(child: Text("Retry", style: TextStyle(color: AppColors.blackThemeColor, fontSize: 14.0, fontWeight: FontWeight.bold),)),
),
),
],
),
);
else Scaffold(
extendBodyBehindAppBar: true,
backgroundColor: const Color(0xFF00639E),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Center(
child: Image.asset(
"assets/animations/jety.gif",
height: 200,
),
),
const SmallTextWidget(text: "Something wrong happened!", color: AppColors.whiteThemeColor,),
const SizedBox(height: 8.0,),
InkWell(
onTap: (){
RestartWidget.restartApp(context); //call restart here
},
child: Container(
height: 45,
width: 100,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
color: AppColors.whiteThemeColor
),
child: const Center(child: Text("Retry", style: TextStyle(color: AppColors.blackThemeColor, fontSize: 14.0, fontWeight: FontWeight.bold),)),
),
),
],
),
);
return CustomNavigation(msgList: widget.listMsg, user: widget.user,);
}
}),
type: PageTransitionType.fade))
);
super.initState();
}
#override
void dispose() {
timer?.cancel();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: true,
backgroundColor: const Color(0xFF00639E),
body: Center(
child: Image.asset(
"assets/animations/jety.gif",
height: 200,
),
),
);
}
}
Restart Widget in the main method
class RestartWidget extends StatefulWidget {
const RestartWidget({required this.child});
final Widget child;
static void restartApp(BuildContext context) {
context.findAncestorStateOfType<_RestartWidgetState>()!.restartApp();
}
#override
_RestartWidgetState createState() => _RestartWidgetState();
}
class _RestartWidgetState extends State<RestartWidget> {
Key key = UniqueKey();
void restartApp() {
setState(() {
key = UniqueKey();
});
}
#override
Widget build(BuildContext context) {
return KeyedSubtree(
key: key,
child: widget.child,
);
}
}
You can use internet_connection_checker for internet check
bool result = await InternetConnectionChecker().hasConnection;
if(result == true) {
print('YAY! Free cute dog pics!');
} else {
print('No internet :( Reason:');
}
call this code in init method in SplashScreen

How to play multiple videos with (player_video) package

I have created this video player for my application which can play video from assets. Since, It is made from (video_player) package I guess I can play only one video with it But I want 3-4 videos to be played. How can I do that? It is possible or not...Help me! Furthermore, I also want to make the video the option of 10 seconds backward and forward while pressing it's sides. Thanks for your help!
import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
void main() {
runApp(VideoPlay());
}
class VideoPlay extends StatefulWidget {
String? pathh;
#override
_VideoPlayState createState() => _VideoPlayState();
VideoPlay({
this.pathh = "assets/video.mp4", // Video from assets folder
});
}
class _VideoPlayState extends State<VideoPlay> {
late VideoPlayerController controller;
late Future<void> futureController;
#override
void initState() {
//url to load network
controller = VideoPlayerController.asset(widget.pathh!);
futureController = controller.initialize();
controller.setLooping(true);
controller.setVolume(25.0);
super.initState();
}
#override
void dispose() {
controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: FutureBuilder(
future: futureController,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return AspectRatio(
aspectRatio: controller.value.aspectRatio,
child: VideoPlayer(controller));
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
),
),
),
Padding(
padding: const EdgeInsets.all(6.0),
child: RaisedButton(
color: Color(0xff9142db),
child: Icon(
controller.value.isPlaying ? Icons.pause : Icons.play_arrow,
color: Colors.white,
),
onPressed: () {
setState(() {
if (controller.value.isPlaying) {
controller.pause();
} else {
controller.play();
}
});
},
),
)
],
));
}
}
App Image Is Here
I like your idea and wanted to deal with it, this is the result.
I hope you can do better.
import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
void main(List<String> args) {
runApp(Example());
}
class Example extends StatelessWidget {
const Example({
Key? key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return const MaterialApp(
color: Colors.white,
debugShowCheckedModeBanner: false,
home: VideoPlayersList(),
);
}
}
class VideoPlayersList extends StatelessWidget {
const VideoPlayersList({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
List<String> paths = [
"assets/images/testvideo.mp4",
"assets/images/testvideo.mp4",
"assets/images/testvideo.mp4",
"assets/images/testvideo.mp4",
"assets/images/testvideo.mp4",
];
return Scaffold(
body: SingleChildScrollView(
child: Column(children: [
ListView.builder(
shrinkWrap: true,
physics: const BouncingScrollPhysics(),
itemCount: paths.length,
itemBuilder: (BuildContext context, int index) {
return VideoPlay(
pathh: paths[index],
);
},
),
]),
),
);
}
}
class VideoPlay extends StatefulWidget {
String? pathh;
#override
_VideoPlayState createState() => _VideoPlayState();
VideoPlay({
Key? key,
this.pathh, // Video from assets folder
}) : super(key: key);
}
class _VideoPlayState extends State<VideoPlay> {
ValueNotifier<VideoPlayerValue?> currentPosition = ValueNotifier(null);
VideoPlayerController? controller;
late Future<void> futureController;
initVideo() {
controller = VideoPlayerController.asset(widget.pathh!);
futureController = controller!.initialize();
}
#override
void initState() {
initVideo();
controller!.addListener(() {
if (controller!.value.isInitialized) {
currentPosition.value = controller!.value;
}
});
super.initState();
}
#override
void dispose() {
controller!.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: futureController,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const CircularProgressIndicator.adaptive();
} else {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
child: SizedBox(
height: controller!.value.size.height,
width: double.infinity,
child: AspectRatio(
aspectRatio: controller!.value.aspectRatio,
child: Stack(children: [
Positioned.fill(
child: Container(
foregroundDecoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Colors.black.withOpacity(.7),
Colors.transparent
],
stops: [
0,
.3
],
begin: Alignment.bottomCenter,
end: Alignment.topCenter),
),
child: VideoPlayer(controller!))),
Positioned.fill(
child: Column(
children: [
Expanded(
flex: 8,
child: Row(
children: [
Expanded(
flex: 3,
child: GestureDetector(
onDoubleTap: () async {
Duration? position =
await controller!.position;
setState(() {
controller!.seekTo(Duration(
seconds: position!.inSeconds - 10));
});
},
child: const Icon(
Icons.fast_rewind_rounded,
color: Colors.black,
size: 40,
),
),
),
Expanded(
flex: 4,
child: IconButton(
icon: Icon(
controller!.value.isPlaying
? Icons.pause
: Icons.play_arrow,
color: Colors.black,
size: 40,
),
onPressed: () {
setState(() {
if (controller!.value.isPlaying) {
controller!.pause();
} else {
controller!.play();
}
});
},
)),
Expanded(
flex: 3,
child: GestureDetector(
onDoubleTap: () async {
Duration? position =
await controller!.position;
setState(() {
controller!.seekTo(Duration(
seconds: position!.inSeconds + 10));
});
},
child: const Icon(
Icons.fast_forward_rounded,
color: Colors.black,
size: 40,
),
),
),
],
),
),
Expanded(
flex: 2,
child: Align(
alignment: Alignment.bottomCenter,
child: ValueListenableBuilder(
valueListenable: currentPosition,
builder: (context,
VideoPlayerValue? videoPlayerValue, w) {
return Padding(
padding: const EdgeInsets.symmetric(
horizontal: 20, vertical: 10),
child: Row(
children: [
Text(
videoPlayerValue!.position
.toString()
.substring(
videoPlayerValue.position
.toString()
.indexOf(':') +
1,
videoPlayerValue.position
.toString()
.indexOf('.')),
style: const TextStyle(
color: Colors.white,
fontSize: 22),
),
const Spacer(),
Text(
videoPlayerValue.duration
.toString()
.substring(
videoPlayerValue.duration
.toString()
.indexOf(':') +
1,
videoPlayerValue.duration
.toString()
.indexOf('.')),
style: const TextStyle(
color: Colors.white,
fontSize: 22),
),
],
),
);
}),
))
],
),
),
])),
),
);
}
},
);
}
}

Making camera preview full-screen

I would like the camera preview screen to be full-screen, instead of the camera condensed down into a rectangle.
In other words, I would like the camera preview to cover the entire screen, and me build the elements on top of this. Not for the elements to reduce the camera preview.
Is there a specific element of code I need to add?
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:camera/camera.dart';
import 'dart:io';
class Camera extends StatefulWidget {
Function setData;
Camera({Key key, this.setData}) : super(key: key);
#override
_CameraScreenState createState() => _CameraScreenState();
}
class _CameraScreenState extends State<Camera> {
CameraController controller;
List cameras;
int selectedCameraIndex;
String imgPath;
var image;
Future _openGallery() async {
image = await controller.takePicture();
if (widget.setData != null) {
widget.setData(File(image.path));
}
}
#override
void initState() {
super.initState();
availableCameras().then((availableCameras) {
cameras = availableCameras;
if (cameras.length > 0) {
setState(() {
selectedCameraIndex = 0;
});
_initCameraController(cameras[selectedCameraIndex]).then((void v) {});
} else {
print('No camera available');
}
}).catchError((err) {
print('Error :${err.code}Error message : ${err.message}');
});
}
Future _initCameraController(CameraDescription cameraDescription) async {
if (controller != null) {
await controller.dispose();
}
controller = CameraController(cameraDescription, ResolutionPreset.high);
controller.addListener(() {
if (mounted) {
setState(() {});
}
if (controller.value.hasError) {
print('Camera error ${controller.value.errorDescription}');
}
});
try {
await controller.initialize();
} on CameraException catch (e) {}
if (mounted) {
setState(() {});
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expanded(
flex: 1,
child: _cameraPreviewWidget(),
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
height: 120,
width: double.infinity,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[_cameraControlWidget(context), Spacer()],
),
),
)
],
),
),
),
);
}
/// Display Camera preview.
Widget _cameraPreviewWidget() {
if (controller == null || !controller.value.isInitialized) {
return const Text(
'Loading',
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
fontWeight: FontWeight.w900,
),
);
}
return AspectRatio(
aspectRatio: controller.value.aspectRatio,
child: CameraPreview(controller),
);
}
/// Display the control bar with buttons to take pictures
Widget _cameraControlWidget(context) {
return Expanded(
child: Align(
alignment: Alignment.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
FloatingActionButton(
child: Icon(
Icons.camera,
color: Colors.black,
),
backgroundColor: Colors.white,
onPressed: () {
// getImage();
_openGallery();
Navigator.pop(context);
},
)
],
),
),
);
}
}
The Column widget puts widgets on top of each other vertically. Instead, you should use the Stack widget:
Something like this:
return Scaffold(
body: Container(
child: SafeArea(
child: Stack(
children: [
Expanded(
flex: 1,
child: _cameraPreviewWidget(),
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
height: 120,
width: double.infinity,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[_cameraControlWidget(context), Spacer()],
),
),
)
],
),
),
),
);

Showing selected image in alert dialog in flutter

How can i show the selected image in my alert dialog ?
In my app, i added an alert dialog which has the camera button. When user clicks the camera button, another alert dialog asks to select file from gallery. After the user selects image file from gallery, i want to show the image in the alert dialog with the camera button, but the image shows only after reopening the alert dialog.
I have posted my code below. I am new to flutter. Please can someone help me? Thanks in advance.
class Test extends StatefulWidget {
#override
_State createState() => new _State();
}
Future<File> imageFile;
class _State extends State<Test> {
Future<void> _openDailog() async {
return showDialog<void>(
context: context,
barrierDismissible: true,
builder: (BuildContext context) {
return AlertDialog(
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text('Click Photo'),
Ink(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(24.0),
color: Colors.blue),
child: IconButton(
color: Colors.white,
icon: Icon(Icons.camera_alt),
onPressed: () {
_cameraOptions();
print("test");
},
),
)
],
),
content: SingleChildScrollView(
child: Container(
width: 300.0,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
showImage(),
InkWell(
child: Container(
margin: EdgeInsets.only(top: 8.0),
child: RaisedButton(
color: Colors.blue,
child: new Text(
"Send",
style: TextStyle(color: Colors.white),
),
onPressed: () {
Navigator.of(context).pop();
print("test");
},
),
)),
],
),
),
),
);
},
);
}
#override
Widget build(BuildContext context) {
// TODO: implement build
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FloatingActionButton(
heroTag: null,
child: Icon(Icons.insert_drive_file),
onPressed: () {
_openDailog();
},
)
],
);
}
Future<void> _cameraOptions() {
return showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
content: new SingleChildScrollView(
child: new ListBody(
children: <Widget>[
FlatButton(
onPressed: () {
pickImageFromGallery(ImageSource.gallery);
Navigator.of(context).pop();
},
color: Colors.transparent,
child: new Text(
'Select From Gallery',
textAlign: TextAlign.start,
style: new TextStyle(
decoration: TextDecoration.underline,
),
),
),
],
),
),
);
});
}
pickImageFromGallery(ImageSource source) {
setState(() {
imageFile = ImagePicker.pickImage(source: source);
});
}
Widget showImage() {
return FutureBuilder<File>(
future: imageFile,
builder: (BuildContext context, AsyncSnapshot<File> snapshot) {
if (snapshot.connectionState == ConnectionState.done &&
snapshot.data != null) {
return Image.file(
snapshot.data,
width: MediaQuery.of(context).size.width,
height: 100,
);
} else if (snapshot.error != null) {
return const Text(
'Error Picking Image',
textAlign: TextAlign.center,
);
} else {
return const Text(
'No Image Selected',
textAlign: TextAlign.center,
);
}
},
);
}
}
That is because you would need to setState() however you can't do that in an alert dialogue as it doesn't have its own state, the workaround for that would be to have the dialogue be its own stateful widget. Please check out this article as it shows how to do that. If you faced problems let me know!
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path_provider/path_provider.dart';
void main() {
runApp(new MaterialApp(
home: new MyHomePage(),
));
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _selectedIndex = 0;
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text("StackoverFlow"),
),
body: Container(),
floatingActionButton: FloatingActionButton(
onPressed: () async {
await _dialogCall(context);
},
),
);
}
Future<void> _dialogCall(BuildContext context) {
return showDialog(
context: context,
builder: (BuildContext context) {
return MyDialog();
});
}
}
class MyDialog extends StatefulWidget {
#override
_MyDialogState createState() => new _MyDialogState();
}
class _MyDialogState extends State<MyDialog> {
String imagePath;
Image image;
#override
Widget build(BuildContext context) {
return AlertDialog(
content: new SingleChildScrollView(
child: new ListBody(
children: <Widget>[
Container(child: image!= null? image:null),
GestureDetector(
child: Row(
children: <Widget>[
Icon(Icons.camera),
SizedBox(width: 5),
Text('Take a picture '),
],
),
onTap: () async {
await getImageFromCamera();
setState(() {
});
}),
Padding(
padding: EdgeInsets.all(8.0),
),
],
),
),
);
}
Future getImageFromCamera() async {
var x = await ImagePicker.pickImage(source: ImageSource.camera);
imagePath = x.path;
image = Image(image: FileImage(x));
}
}
Try this solution with GestureDetector() .it works
onTap:()async{
var image = await ImagePicker.pickImage(
source: ImageSource.gallery).whenComplete((){
setState(() {
});
}
);
setState(() {
_image = image;
});
},