My camera preview is currently stretched vertically as per the screenshot attached.
The code to the camera page is below, does anyone know how to adjust the code so that the camera preview does not appear to be stretched?
I need it to work for iOS and Android, and for every device.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:camera/camera.dart';
import 'dart:io';
import 'package:flutter/services.dart';
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();
SystemChrome.setEnabledSystemUIOverlays([]);
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: Stack(
children: <Widget>[
_cameraPreviewWidget(),
_cameraControlWidget(context)
],
),
),
);
}
Widget _cameraPreviewWidget() {
if (controller == null || !controller.value.isInitialized) {
return const Text(
'Loading',
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
fontWeight: FontWeight.w900,
),
);
}
final size = MediaQuery.of(context).size;
final deviceRatio = size.width / size.height;
return Stack(children: <Widget>[
Positioned.fill(
child: new AspectRatio(
aspectRatio: controller.value.aspectRatio,
child: new CameraPreview(controller),
),
),
]);
}
Widget _cameraControlWidget(context) {
return Container(
child: Align(
alignment: Alignment.center,
child: FloatingActionButton(
child: Icon(
Icons.center_focus_strong,
size: 39,
color: Color(0xd),
),
backgroundColor: Color(0xff33333D),
onPressed: () {
_openGallery();
Navigator.pop(context);
},
)
));
}
}
and here is the image as to how it is rendering. The button in the middle takes the photo.
I have struggled with the camera preview in Flutter as well. It is a pain to work with. This is what I am using right now. Hopefully it will help you
class CameraPreview extends StatelessWidget {
const CameraPreview({Key? key, this._cameraController}) : super(key: key);
final CameraController _cameraController;
#override
Widget build(BuildContext context) {
return ClipRect(
child: OverflowBox(
alignment: Alignment.center,
child: FittedBox(
fit: BoxFit.cover,
child: SizedBox(
height: 1,
child: AspectRatio(
aspectRatio: 1 / _cameraController.value.aspectRatio,
child: CameraPreview(_cameraCcontroller),
),
),
),
),
);
}
}
Related
I am trying to integrate speech to text into my flutter app. However, nothing I try is working. Here is my dart code:
import 'package:client/main.dart';
import 'package:flutter/material.dart';
import 'package:client/language/nlp.dart';
import 'package:speech_to_text/speech_recognition_result.dart';
import 'package:speech_to_text/speech_to_text.dart';
class Home extends StatefulWidget{
const Home({super.key});
#override
State<Home> createState() => HomeState();
}
class HomeState extends State<Home>{
#override
BuildContext context = navigatorKey.currentState!.context;
SpeechToText _speechToText = SpeechToText();
bool _speechEnabled = false;
String _lastWords = "";
Language nlp = Language();
#override
void initState(){
super.initState();
_initSpeech();
}
void _initSpeech() async {
_speechEnabled = await _speechToText.initialize();
setState(() {});
}
void _startListening() async {
await _speechToText.listen(onResult: _onSpeechResult);
setState(() {});
}
void _stopListening() async {
await _speechToText.stop();
setState(() {});
}
void _onSpeechResult(SpeechRecognitionResult result){
setState(() {
_lastWords = result.recognizedWords;
print(result.recognizedWords);
nlp.parseInput(result.recognizedWords);
});
}
#override
Widget build(BuildContext context){
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
padding: EdgeInsets.all(16),
child: const Text(
"Recognised words:",
style: TextStyle(fontSize: 20.0),
),
),
Expanded(
child: Container(
padding: EdgeInsets.all(16),
child: Text(
_speechToText.isListening
? '$_lastWords'
: _speechEnabled
? 'Tap the microphone to start listening...'
: "Speech not available", ),
),
)
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _speechToText.isNotListening ? _startListening : _stopListening,
child: Icon(_speechToText.isNotListening ? Icons.mic_off : Icons.mic),
),
);
}
}
Does anyone know of a way to make this work? No error message is being shown but the speech input is not being sent to the nlp.parseInput() function and is not being printed. I have tried googling it and can't find any solutions.
I'm currently create chat in flutter and get the last messages , I want to handle when scrolling to top to load more messages how can I create that ?
If you want to implement swipe to refresh kind of behaviour, you can use RefreshIndicator. See the example and usage in this YouTube video.
All you have to do is wrap your scrollable widget (it can be ListView or SingleChildScrollView) in a RefreshIndicator and provide onRefresh method:
class PullToRefresh extends StatelessWidget {
const PullToRefresh({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return RefreshIndicator(
onRefresh: _refreshData,
child: ListView.builder( // or SingleChildScrollView
...
),
);
}
Future<void> _refreshData() async {
// load more items
}
}
ListView reverse: true displays the List from the bottom to the top.
and this is how to implement pagination
class HomeState extends State<Home> {
ScrollController? controller;
final _all = <WordPair>[];
final _saved = Set<WordPair>();
final _biggerFont = const TextStyle(fontSize: 18.0);
GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
bool isLoading = false;
#override
void initState() {
super.initState();
_all.addAll(generateWordPairs().take(20));
controller = ScrollController()..addListener(_scrollListener);
}
#override
void dispose() {
super.dispose();
controller?.dispose();
}
void _scrollListener() {
if (controller!.position.pixels == controller!.position.maxScrollExtent) {
startLoader();
}
}
void startLoader() {
setState(() {
isLoading = !isLoading;
fetchData();
});
}
fetchData() async {
var _duration = const Duration(seconds: 2);
return Timer(_duration, onResponse);
}
void onResponse() {
setState(() {
isLoading = !isLoading;
_all.addAll(generateWordPairs().take(20));
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: scaffoldKey,
appBar: AppBar(
title: const Text(
"List load more example",
style: TextStyle(color: Colors.white),
),
),
body: Stack(
children: <Widget>[
_buildSuggestions(),
_loader(),
],
),
);
}
Widget _buildRow(WordPair pair) {
final alreadySaved = _saved.contains(pair);
return Column(
children: <Widget>[
ListTile(
title: Text(
pair.asPascalCase,
style: _biggerFont,
),
trailing: Icon(
alreadySaved ? Icons.check : Icons.check,
color: alreadySaved ? Colors.deepOrange : null,
),
onTap: () {
setState(() {
if (alreadySaved) {
_saved.remove(pair);
} else {
_saved.add(pair);
}
});
},
),
const Divider(),
],
);
}
Widget _buildSuggestions() {
return ListView.builder(
reverse: true,
padding: const EdgeInsets.all(16.0),
controller: controller,
itemCount: _all.length,
itemBuilder: (context, i) {
return _buildRow(_all[i]);
});
}
Widget _loader() {
return isLoading
? const Align(
child: SizedBox(
width: 70.0,
height: 70.0,
child: Padding(
padding: EdgeInsets.all(5.0),
child: Center(child: CircularProgressIndicator())),
),
alignment: FractionalOffset.topCenter,
)
: const SizedBox(
width: 0.0,
height: 0.0,
);
}
}
You can get full code from Github HERE
Am able to show and hide the widget i want but it keeps flickering or rebuilding its self every time.
i just want to show the the capture icon button when the compass degree reaches 190 degree
this is my main widget
late List<CameraDescription> cameras;
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
cameras = await availableCameras();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: CameraApp(),
);
}
}
class CameraApp extends StatefulWidget {
#override
_CameraAppState createState() => _CameraAppState();
}
class _CameraAppState extends State<CameraApp> {
String? imagePath;
XFile? imageFile;
late CameraController controller;
late Future<void> _initializeControllerFuture;
int? angleResult;
bool showCaptureButton = false;
String? getLocation;
bool k = false;
void getAngleFromCompass(newResult) {
WidgetsBinding.instance!.addPostFrameCallback((_) {
setState(() {
angleResult = newResult;
});
});
}
void getLocationRes(newResult) {
getLocation = newResult;
}
#override
void initState() {
super.initState();
controller = CameraController(
// Get a specific camera from the list of available cameras.
cameras[0],
// Define the resolution to use.
ResolutionPreset.high,
imageFormatGroup: ImageFormatGroup.yuv420,
);
_initializeControllerFuture = controller.initialize().then((value) {
setState(() {});
});
}
#override
void dispose() {
controller.dispose();
super.dispose();
}
void _captureImage() async {
await takePicture().then((filePath) {
if (mounted) {
setState(() {
imagePath = filePath;
});
}
});
}
Widget cameraWidget(context) {
var camera = controller.value;
final size = MediaQuery.of(context).size;
var scale = size.aspectRatio * camera.aspectRatio;
if (scale < 1) scale = 1 / scale;
return Transform.scale(
scale: scale,
child: Center(
child: CameraPreview(controller),
),
);
}
#override
Widget build(BuildContext context) {
if (!controller.value.isInitialized) {
return Container();
}
theCompassApp(getAngleFromCompass) keeps flikering here
return Scaffold(
body: FutureBuilder(
future: _initializeControllerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return Stack(
children: [
cameraWidget(context),
Align(
alignment: Alignment.topCenter,
child: LocationApp(getLocationRes),
),
Align(
child: CompassApp(getAngleFromCompass),
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
color: Color(0xAA333639),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
angleResult == 190 ? IconButton(
onPressed: () => _captureImage(),
iconSize: 40,
icon: Icon(
Icons.camera_alt,
color: Colors.white,
),
) : Text(''),
],
),
),
)
],
);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
),
);
}
Compass App Widget
class CompassApp extends StatefulWidget {
final getAngleValue;
CompassApp(this.getAngleValue);
#override
_CompassAppState createState() => _CompassAppState();
}
class _CompassAppState extends State<CompassApp> {
bool _hasPermissions = false;
#override
void initState() {
super.initState();
_fetchPermissionStatus();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
backgroundColor: Colors.transparent,
body: Builder(builder: (context) {
if (_hasPermissions) {
return Column(
children: <Widget>[
Expanded(child: _buildCompass()),
],
);
} else {
return Text('');
}
}),
),
);
}
Widget _buildCompass() {
return StreamBuilder<CompassEvent>(
stream: FlutterCompass.events,
builder: (context, snapshot) {
if (snapshot.hasError) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 30),
child: Text('Error reading heading not support'),
);
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(),
);
}
double? direction = snapshot.data!.heading;
int ang = direction!.round();
Compass angle passed to main widget here
widget.getAngleValue(ang);
if (direction.isNaN)
return Center(
child: Text("Device does not have sensors !"),
);
return Material(
color: Colors.transparent,
child: Column(
children: [
RotatedBox(
quarterTurns: 1,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 41),
child: Text(
'$ang',
style: TextStyle(
fontSize: 50,
color: Colors.white,
backgroundColor: Colors.black26),
),
),
),
],
),
);
},
);
}
void _fetchPermissionStatus() {
Permission.locationWhenInUse.status.then((status) {
if (mounted) {
setState(() => _hasPermissions = status == PermissionStatus.granted);
}
});
}
}
Have you tried Visibility or Opacity?
Visibility
Visibility(
visible: true, //false for invisible
child: Text('I am visible'),
),
Opacity
Opacity(
opacity: 1.0, //0.0 for invisible
child: Text('I am visible'),
),
When a user takes a photo, I want to send it to the photo_preview screen, which gives the user the chance to take another photo.
This page is as follows:
import 'package:flutter/material.dart';
import 'dart:io';
class photo_previewScreen extends StatelessWidget {
final String imagePath;
const photo_previewScreen({Key key, this.imagePath}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Display the Picture')),
body: Image.file(File(imagePath)),
);
}
}
On my current camera page, what's the best way for me to send the photo to the above page?
When the take picture button is pressed, this is what is currently happening:
onPressed: () {
_openGallery();
Navigator.pop(context);
},
EDIT: Full page with edits from the answer
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:camera/camera.dart';
import 'dart:io';
import 'package:stumble/pages/PhotoPreviewScreen.dart';
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;
takePicture;
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()],
),
),
)
],
),
),
),
);
}
Widget _cameraPreviewWidget() {
if (controller == null || !controller.value.isInitialized) {
return const Text(
'Loading',
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
fontWeight: FontWeight.w900,
),
);
}
final size = MediaQuery.of(context).size;
final deviceRatio = size.width / size.height;
return Stack(children: <Widget>[
Positioned.fill(
child: new AspectRatio(
aspectRatio: controller.value.aspectRatio,
child: new CameraPreview(controller),
),
),
]);
}
Widget _cameraControlWidget(context) {
return Expanded(
child: Align(
alignment: Alignment.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
FloatingActionButton(
child: Icon(
Icons.center_focus_strong,
size: 39,
color: Color(0xffffffff),
),
backgroundColor: Color(0xff33333D),
onPressed: () async {
var result = await takePicture();
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PhotoPreviewScreen(
imagePath: result,
),
),
);
})
],
),
),
);
}
}
I am getting the error that
'The method 'takePicture isn't defined for the type '_CameraScreenState'
This despite takePicture(); being defined.
You can navigate to the preview screen on clicking the take picture button, passing the image path:
void onTakePictureButtonPressed() async {
var result = await takePicture();
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PhotoPreviewScreen(
imagePath: result,
),
),
);
}
Future<String> takePicture() async {
if (!controller.value.isInitialized) {
showErrorFlushbar(context, 'Error: select a camera first.');
return null;
}
final Directory extDir = await getApplicationDocumentsDirectory();
final String dirPath = '${extDir.path}/Pictures/ompariwar';
await Directory(dirPath).create(recursive: true);
final String filePath = '$dirPath/${timestamp()}.jpg';
if (controller.value.isTakingPicture) {
// A capture is already pending, do nothing.
return null;
}
try {
await controller.takePicture(filePath);
} on CameraException catch (e) {
print(e);
return null;
}
return filePath;
}
In the preview screen, you can do this:
class PhotoPreviewScreen extends StatelessWidget {
final String imagePath;
const PhotoPreviewScreen({Key key, this.imagePath}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () => Navigator.pop(context), // Go back to the camera to take the picture again
child: Icon(Icons.camera_alt),
),
appBar: AppBar(title: Text('Display the Picture')),
body: Column(
children: [
Expanded(child: Image.file(File(imagePath))),
SomeButton(), // Add a button to send the image to server or go back to home screen here
],
),
);
}
}
Btw it's a convention to name your class/ Widget name in UpperCamelCase. Read more on this Dart style guide for clean code.
I was trying to make a class for scanning barcodes with "fast_qr_reader_view: ^0.1.5" dependencies. But when I call this class on my main.dart this error came out "NoSuchMethodError: The method[] was called on null.Receiver:null. Tried calling:"
I already tried writing on the main.dart and works, but when Im calling it from a different class doesn't work
This is my code that shows me the error main.dart
import 'package:flutter/material.dart';
import 'RegistroTrajetaOCedulaWidget.dart';
import 'package:pay_id/Screens/testScan.dart';
import 'Screens/dashboard.dart';
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,
),
debugShowCheckedModeBanner: false,
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> {
#override
Widget build(BuildContext context) {
return Scan();
}
}
testScan.dart
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:fast_qr_reader_view/fast_qr_reader_view.dart';
import 'package:lamp/lamp.dart';
List<CameraDescription> cameras;
Future<Null> main() async {
// Fetch the available cameras before initializing the app.
try {
cameras = await availableCameras();
} on QRReaderException catch (e) {
logError(e.code, e.description);
}
runApp(new Scan());
}
void logError(String code, String message) =>
print('Error: $code\nError Message: $message');
class Scan extends StatefulWidget {
#override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<Scan> with SingleTickerProviderStateMixin {
QRReaderController controller;
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
AnimationController animationController;
#override
void initState() {
super.initState();
animationController = new AnimationController(
vsync: this,
duration: new Duration(seconds: 3),
);
animationController.addListener(() {
this.setState(() {});
});
animationController.forward();
verticalPosition = Tween<double>(begin: 0.0, end: 300.0).animate(
CurvedAnimation(parent: animationController, curve: Curves.linear))
..addStatusListener((state) {
if (state == AnimationStatus.completed) {
animationController.reverse();
} else if (state == AnimationStatus.dismissed) {
animationController.forward();
}
});
// pick the first available camera
onNewCameraSelected(cameras[0]);
}
Animation<double> verticalPosition;
#override
Widget build(BuildContext context) {
return new Scaffold(
key: _scaffoldKey,
appBar: new AppBar(
title: const Text('Prueba escaner'),
),
floatingActionButton: FloatingActionButton(
child: new Icon(Icons.check),
onPressed: () {
Lamp.turnOn();
},
),
body: Stack(
children: <Widget>[
new Container(
child: new Padding(
padding: const EdgeInsets.all(0.0),
child: new Center(
child: _cameraPreviewWidget(),
),
),
),
Center(
child: Stack(
children: <Widget>[
SizedBox(
height: 300.0,
width: 300.0,
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.red, width: 2.0)),
),
),
Positioned(
top: verticalPosition.value,
child: Container(
width: 300.0,
height: 2.0,
color: Colors.red,
),
)
],
),
),
],
),
);
}
/// Display the preview from the camera (or a message if the preview is not available).
Widget _cameraPreviewWidget() {
if (controller == null || !controller.value.isInitialized) {
return const Text(
'No camera selected',
style: const TextStyle(
color: Colors.white,
fontSize: 24.0,
fontWeight: FontWeight.w900,
),
);
} else {
return new AspectRatio(
aspectRatio: controller.value.aspectRatio,
child: new QRReaderPreview(controller),
);
}
}
void onCodeRead(dynamic value) {
showInSnackBar(value.toString());
// ... do something
// wait 5 seconds then start scanning again.
new Future.delayed(const Duration(seconds: 5), controller.startScanning);
}
void onNewCameraSelected(CameraDescription cameraDescription) async {
if (controller != null) {
await controller.dispose();
}
controller = new QRReaderController(cameraDescription,
ResolutionPreset.high, [CodeFormat.qr, CodeFormat.pdf417], onCodeRead);
// If the controller is updated then update the UI.
controller.addListener(() {
if (mounted) setState(() {});
if (controller.value.hasError) {
showInSnackBar('Camera error ${controller.value.errorDescription}');
}
});
try {
await controller.initialize();
} on QRReaderException catch (e) {
logError(e.code, e.description);
showInSnackBar('Error: ${e.code}\n${e.description}');
}
if (mounted) {
setState(() {});
controller.startScanning();
}
}
void showInSnackBar(String message) {
_scaffoldKey.currentState
.showSnackBar(new SnackBar(content: new Text(message)));
}
}
cameras did not init
you can init cameras in testScan.dart directly
_asyncMethod() async {
cameras = await availableCameras();
onNewCameraSelected(cameras[0]);
print('camera ${cameras.length}');
}
#override
void initState() {
super.initState();
...
_asyncMethod();
}
demo for init cameras in testScan.dart directly
fulll test demo for testScan.dart
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:fast_qr_reader_view/fast_qr_reader_view.dart';
import 'package:lamp/lamp.dart';
List<CameraDescription> cameras;
/*Future<Null> main() async {
// Fetch the available cameras before initializing the app.
try {
cameras = await availableCameras();
} on QRReaderException catch (e) {
logError(e.code, e.description);
}
runApp(new Scan());
}*/
void logError(String code, String message) =>
print('Error: $code\nError Message: $message');
class Scan extends StatefulWidget {
#override
_ScanState createState() => new _ScanState();
}
class _ScanState extends State<Scan> with SingleTickerProviderStateMixin {
QRReaderController controller;
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
AnimationController animationController;
_asyncMethod() async {
cameras = await availableCameras();
onNewCameraSelected(cameras[0]);
print('camera ${cameras.length}');
}
#override
void initState() {
super.initState();
animationController = new AnimationController(
vsync: this,
duration: new Duration(seconds: 3),
);
animationController.addListener(() {
this.setState(() {});
});
animationController.forward();
verticalPosition = Tween<double>(begin: 0.0, end: 300.0).animate(
CurvedAnimation(parent: animationController, curve: Curves.linear))
..addStatusListener((state) {
if (state == AnimationStatus.completed) {
animationController.reverse();
} else if (state == AnimationStatus.dismissed) {
animationController.forward();
}
});
// pick the first available camera
_asyncMethod();
}
Animation<double> verticalPosition;
#override
Widget build(BuildContext context) {
return new Scaffold(
key: _scaffoldKey,
appBar: new AppBar(
title: const Text('Prueba escaner'),
),
floatingActionButton: FloatingActionButton(
child: new Icon(Icons.check),
onPressed: () {
Lamp.turnOn();
},
),
body: Stack(
children: <Widget>[
new Container(
child: new Padding(
padding: const EdgeInsets.all(0.0),
child: new Center(
child: _cameraPreviewWidget(),
),
),
),
Center(
child: Stack(
children: <Widget>[
SizedBox(
height: 300.0,
width: 300.0,
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.red, width: 2.0)),
),
),
Positioned(
top: verticalPosition.value,
child: Container(
width: 300.0,
height: 2.0,
color: Colors.red,
),
)
],
),
),
],
),
);
}
/// Display the preview from the camera (or a message if the preview is not available).
Widget _cameraPreviewWidget() {
if (controller == null || !controller.value.isInitialized) {
return const Text(
'No camera selected',
style: const TextStyle(
color: Colors.white,
fontSize: 24.0,
fontWeight: FontWeight.w900,
),
);
} else {
return new AspectRatio(
aspectRatio: controller.value.aspectRatio,
child: new QRReaderPreview(controller),
);
}
}
void onCodeRead(dynamic value) {
showInSnackBar(value.toString());
// ... do something
// wait 5 seconds then start scanning again.
new Future.delayed(const Duration(seconds: 5), controller.startScanning);
}
void onNewCameraSelected(CameraDescription cameraDescription) async {
if (controller != null) {
await controller.dispose();
}
controller = new QRReaderController(cameraDescription,
ResolutionPreset.high, [CodeFormat.qr, CodeFormat.pdf417], onCodeRead);
// If the controller is updated then update the UI.
controller.addListener(() {
if (mounted) setState(() {});
if (controller.value.hasError) {
showInSnackBar('Camera error ${controller.value.errorDescription}');
}
});
try {
await controller.initialize();
} on QRReaderException catch (e) {
logError(e.code, e.description);
showInSnackBar('Error: ${e.code}\n${e.description}');
}
if (mounted) {
setState(() {});
controller.startScanning();
}
}
void showInSnackBar(String message) {
_scaffoldKey.currentState
.showSnackBar(new SnackBar(content: new Text(message)));
}
}