I'm working on an app for scanning barcode, and i want to scanning multiple barcodes and still see what i'm scanning at the same time. please there a way this can be achieved in flutter?
This would only be achievable by using an inline QR scan widget.
This is available, but uses embedded native widgets, which is an experimental feature.
Have a look at this library: https://pub.dev/packages/qr_code_scanner
The example included should be able to help you. It divides the screen in 4/5 for the camera widget and 1/5 for the rest. You can change this by changing the flex value in the example below.
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:qr_code_scanner/qr_code_scanner.dart';
void main() => runApp(MaterialApp(home: QRViewExample()));
class QRViewExample extends StatefulWidget {
const QRViewExample({
Key key,
}) : super(key: key);
#override
State<StatefulWidget> createState() => _QRViewExampleState();
}
class _QRViewExampleState extends State<QRViewExample> {
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
var qrText = "";
QRViewController controller;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Expanded(
child: QRView(
key: qrKey,
onQRViewCreated: _onQRViewCreated,
),
flex: 4,
),
Expanded(
child: Column(children:
<Widget>[
Text("This is the result of scan: $qrText"),
RaisedButton(
onPressed: (){
if(controller != null){
controller.flipCamera();
}
},
child: Text(
'Flip',
style: TextStyle(fontSize: 20)
),
)
],
),
flex: 1,
)
],
),
);
}
void _onQRViewCreated(QRViewController controller) {
final channel = controller.channel;
controller.init(qrKey);
this.controller = controller;
channel.setMethodCallHandler((MethodCall call) async {
switch (call.method) {
case "onRecognizeQR":
dynamic arguments = call.arguments;
setState(() {
qrText = arguments.toString();
});
}
});
}
}
Related
I'm trying to show the full image that has been clicked on from my drawer.
I have a liste of images that I display in my drawer and What I want is that when I click on a specific image, it closes my drawer and show the image on my screen in a kind of an image slider where I can switch images directly from the opened image.
here is my code where I extract my list of images from my asset folder :
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class GetImages extends StatefulWidget {
const GetImages({super.key});
#override
State<GetImages> createState() => _GetImagesState();
}
class _GetImagesState extends State<GetImages> {
List<String> imagePaths = [];
#override
void initState() {
_initImages();
super.initState();
}
Future _initImages() async {
final Map<String, dynamic> assets =
jsonDecode(await rootBundle.loadString('AssetManifest.json'));
setState(() {
imagePaths = assets.keys
.where((String key) => key.contains('photos/'))
.where((String key) => key.contains('.JPG'))
.toList();
});
}
#override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, constraints) {
return GridView.count(
crossAxisCount: constraints.maxWidth > 700 ? 4 : 2,
children: imagePaths
.map(
(path) => Padding(
padding: const EdgeInsets.symmetric(horizontal: 17),
child: Image.asset(path),
),
)
.toList(),
);
});
}
}
And here is my code for my drawer :
import 'package:flutter/material.dart';
import 'package:myapp/widgets/get_images.dart';
import 'package:image_viewer/image_viewer.dart';
class SideBar extends StatelessWidget {
const SideBar({super.key, required this.title});
final String title;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(title)),
body: const Center(
child: Text('My Page!'),
),
drawer: Drawer(
child: InkWell(
child: GetImages(),
onTap: () {
//ImageViewer.showImageSlider(images: ["assets/photos/IMG_4100.JPG"]);
// montre la photo et ferme la sidebar
Navigator.pop(context);
},
),
),
);
}
}
Thanks in advance for your help :)
You could try this package that i've used before https://pub.dev/packages/lightbox seems like it does exactly what you are looking for.
I'm trying to use the qr_code_scanner library in order to scan the attached QR code, which contains a logo in its center. The code in the sample, however, doesn't seem to work with such QR codes, but it does with normal ones. Google Lens can decode it normally, so I'm wondering if there's something that I'm missing. Does this library not support this case due to it being old?
Here's my code (similar to the sample one):
class QRCameraView extends StatefulWidget {
const QRCameraView({Key? key}) : super(key: key);
#override
State<QRCameraView> createState() => _QRCameraViewState();
}
class _QRCameraViewState extends State<QRCameraView> {
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
Barcode? result;
QRViewController? controller;
// 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) {
controller!.pauseCamera();
} else if (Platform.isIOS) {
controller!.resumeCamera();
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Expanded(
flex: 5,
child: QRView(
key: qrKey,
onQRViewCreated: _onQRViewCreated,
),
),
Expanded(
flex: 1,
child: Center(
child: (result != null)
? Text(
'Barcode Type: ${describeEnum(result!.format)} Data: ${result!.code}',
)
: const Text('Scan a code'),
),
)
],
),
);
}
void _onQRViewCreated(QRViewController controller) {
setState(() {
this.controller = controller;
});
controller.scannedDataStream.listen((Barcode scanData) {
HapticFeedback.vibrate();
setState(() {
result = scanData;
debugPrint(result?.code ?? 'error');
});
});
}
#override
void dispose() {
controller?.dispose();
super.dispose();
}
}
And here's the qr code in question:
I've created a .riv file with 3 state animations: start, processing, end, which are in "State machine". Rive team recently announced a new feature with dinamically changing animations, it's "State machine". Not sure, how to use it in flutter project, i.e how to dynamically change value of animation. If somebody needs some code, no problem, I could provide. Moreover, link to rive's "state machine" https://www.youtube.com/watch?v=0ihqZANziCk. I didn't find any examples related to this new feature. Please help! Thanks.
The other answer is outdated.
class SimpleStateMachine extends StatefulWidget {
const SimpleStateMachine({Key? key}) : super(key: key);
#override
_SimpleStateMachineState createState() => _SimpleStateMachineState();
}
class _SimpleStateMachineState extends State<SimpleStateMachine> {
SMITrigger? _bump;
void _onRiveInit(Artboard artboard) {
final controller = StateMachineController.fromArtboard(artboard, 'bumpy');
artboard.addController(controller!);
_bump = controller.findInput<bool>('bump') as SMITrigger;
}
void _hitBump() => _bump?.fire();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Simple Animation'),
),
body: Center(
child: GestureDetector(
child: RiveAnimation.network(
'https://cdn.rive.app/animations/vehicles.riv',
fit: BoxFit.cover,
onInit: _onRiveInit,
),
onTap: _hitBump,
),
),
);
}
}
See the RIVE guide:
https://help.rive.app/runtimes/state-machines
There are examples on rives pub package site. Here is one for state machine.
example_state_machine.dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:rive/rive.dart';
/// An example showing how to drive two boolean state machine inputs.
class ExampleStateMachine extends StatefulWidget {
const ExampleStateMachine({Key? key}) : super(key: key);
#override
_ExampleStateMachineState createState() => _ExampleStateMachineState();
}
class _ExampleStateMachineState extends State<ExampleStateMachine> {
/// Tracks if the animation is playing by whether controller is running.
bool get isPlaying => _controller?.isActive ?? false;
Artboard? _riveArtboard;
StateMachineController? _controller;
SMIInput<bool>? _hoverInput;
SMIInput<bool>? _pressInput;
#override
void initState() {
super.initState();
// Load the animation file from the bundle, note that you could also
// download this. The RiveFile just expects a list of bytes.
rootBundle.load('assets/rocket.riv').then(
(data) async {
// Load the RiveFile from the binary data.
final file = RiveFile.import(data);
// The artboard is the root of the animation and gets drawn in the
// Rive widget.
final artboard = file.mainArtboard;
var controller =
StateMachineController.fromArtboard(artboard, 'Button');
if (controller != null) {
artboard.addController(controller);
_hoverInput = controller.findInput('Hover');
_pressInput = controller.findInput('Press');
}
setState(() => _riveArtboard = artboard);
},
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey,
appBar: AppBar(
title: const Text('Button State Machine'),
),
body: Center(
child: _riveArtboard == null
? const SizedBox()
: MouseRegion(
onEnter: (_) => _hoverInput?.value = true,
onExit: (_) => _hoverInput?.value = false,
child: GestureDetector(
onTapDown: (_) => _pressInput?.value = true,
onTapCancel: () => _pressInput?.value = false,
onTapUp: (_) => _pressInput?.value = false,
child: SizedBox(
width: 250,
height: 250,
child: Rive(
artboard: _riveArtboard!,
),
),
),
),
),
);
}
}
I have a listview.builder in flutter and every item of the list has a dropdown now whenever I select one dropdown value of every dropdown changes. how can I fix this problem in flutter?
Ok, after spending a couple of hours on this and not finding a satisfactory answer (but a lot of hints) I worked it out.
I made a new StatefulWidget class that wraps the DropdownButton. It is instantiated with the List of items for the dropdown.
listview_dropdownbutton.dart
import 'package:flutter/material.dart';
class ListviewDropdownButton extends StatefulWidget {
final List<dynamic> sizes;
const ListviewDropdownButton({
Key? key,
required this.sizes,
}) : super(key: key);
#override
State<ListviewDropdownButton> createState() => _ListviewDropdownButton();
}
class _ListviewDropdownButton extends State<ListviewDropdownButton> {
List<dynamic>? _sizes;
String _currentSize = '';
#override
Widget build(BuildContext context) {
_sizes = _sizes ?? widget.sizes;
_currentSize = _currentSize != '' ? _currentSize : widget.sizes[0];
return DropdownButton<dynamic>(
value: _currentSize,
style: const TextStyle(
color: Colors.green,
),
items: _sizes!.map<DropdownMenuItem<dynamic>>((dynamic size) {
return DropdownMenuItem(
value: size,
child: Text(size),
);
}).toList(),
onChanged: (dynamic size) {
if (_currentSize != size) {
setState(() {
_currentSize = size!;
});
}
},
);
}
}
In the parent widget, just include the class and use it where you'd put the DropdownButton.
Here's a working example.
main.dart
import 'package:flutter/material.dart';
import 'listview_dropdownbutton.dart';
void main() => runApp(const DropdownButtonApp());
class DropdownButtonApp extends StatelessWidget {
const DropdownButtonApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('DropdownButton In ListView')),
body: Center(
child: DropdownButtonExample(),
),
),
);
}
}
class DropdownButtonExample extends StatelessWidget {
DropdownButtonExample({super.key});
final List<String> _items = <String>['Shirt', 'T-Shirt', 'Pants', 'Blouse', 'Coat'];
final List<String> _sizes = <String>['Small', 'Medium', 'Large', 'X-Large'];
String _currentSize = 'Small';
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: _items.length,
itemBuilder: (
BuildContext context,
int index,
) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(_items[index]),
Row(
children: [
ListviewDropdownButton(
sizes: _sizes,
),
DropdownButton<String>(
value: _currentSize,
style: const TextStyle(
color: Colors.red,
),
items: _sizes.map<DropdownMenuItem<String>>((String size) {
return DropdownMenuItem(
value: size,
child: Text(size),
);
}).toList(),
onChanged: (String? size) {
if (_currentSize != size) {
// setState(() {
_currentSize = size!;
// });
}
},
),
],
),
const Divider(
thickness: 2,
height: 2,
),
],
);
},
);
}
}
To illustrate it works, I put both the ListviewDropdownButton and a regular DropdownButton in the ListView.
I added String _currentSize = 'Small'; and the onChanged method to show the regular DropdownButton does not work. It never changes from "Small", which was my original problem.
I have a Home Screen Widget, that plays a fullscreen background video using the video_player package.
This code works fine for me:
class HomeScreen extends StatefulWidget {
HomeScreen({Key key}) : super(key: key);
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
VideoPlayerController _controller;
void initState() {
super.initState();
// Pointing the video controller to mylocal asset.
_controller = VideoPlayerController.asset("assets/waterfall.mp4");
_controller.initialize().then((_) {
// Once the video has been loaded we play the video and set looping to true.
_controller.play();
_controller.setLooping(true);
// Ensure the first frame is shown after the video is initialized.
setState(() {});
});
}
#override
void dispose() {
super.dispose();
_controller.dispose();
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Stack(
children: <Widget>[
SizedBox.expand(
child: FittedBox(
// If your background video doesn't look right, try changing the BoxFit property.
// BoxFit.fill created the look I was going for.
fit: BoxFit.fill,
child: SizedBox(
width: _controller.value.size?.width ?? 0,
height: _controller.value.size?.height ?? 0,
child: VideoPlayer(_controller),
),
),
),
Container(
child: Center(
child: Text('Hello!'),
),
),
],
),
),
);
}
}
The question is, how can I implement this using flutter Hooks? I understand that I have to use useEffect() to implement the functionality of initState() and dispose(), useFuture() and maybe useMemoized() to handle asynchronous _controller.initialize() call and what possibly else? But, I cannot glue them to get the desired result. Can anyone indicate to me the "using Hooks" implementation of the above code?
I was looking for the answer to how to convert a VideoPlayer demo from StatefulWidget to HookWidget when I came across this question. I've come up with something that works so I'll post it here since there is nothing elsewhere that I could find and some others are hitting this page looking for an answer.
I used a viewmodel. The video controller is a property of the viewmodel. This code will not compile since some of the controls are not included. But it will demonstrate the structure and incorporation of the viewmodel.
Here's the widget file:
import 'package:flutter/foundation.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:video_player/video_player.dart';
import 'intro_viewmodel.dart';
class IntroPage extends HookWidget {
Future<void> saveAndGetStarted(BuildContext context) async {
final IntroViewModel introViewModel = context.read(introViewModelProvider);
await introViewModel.completeIntro();
}
Future<void> onNext(BuildContext context) async {
final IntroViewModel introViewModel = context.read(introViewModelProvider);
await introViewModel.incrementIntro();
}
final List<SliderModel> slides = [
SliderModel(
description: 'A word with you before you get started.\n',
title: 'Why This App?',
localImageSrc: 'media/Screen1-Movingforward-pana.svg',
backgroundColor: Colors.lightGray),
SliderModel(
description: 'This information will help the app be more accurate\n',
title: 'Personal Profile',
localImageSrc: 'media/Screen2-Teaching-cuate.svg',
backgroundColor: Colors.lightGray)
];
#override
Widget build(BuildContext context) {
final IntroViewModel introViewModel = context.read(introViewModelProvider);
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Center(
child: Column(
children: [
Text(
slides[introViewModel.index].description,
style: Theme.of(context).textTheme.headline5,
textAlign: TextAlign.center,
),
Expanded(
child: FractionallySizedBox(
widthFactor: .98,
heightFactor: .5,
child: VideoPlayer(introViewModel.videoController),
)),
Align(
alignment: Alignment.bottomCenter,
child: CustomRaisedButton(
onPressed: () {
if (introViewModel.index == slides.length - 1) {
saveAndGetStarted(context);
} else {
onNext(context);
}
},
color: Theme.of(context).accentColor,
borderRadius: 15,
height: 50,
child: Text(
introViewModel.index == 0
? 'Continue'
: 'Save and Get Started',
style: Theme.of(context)
.textTheme
.headline5
.copyWith(color: Colors.white),
),
),
),
],
),
),
));
}
#override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(IterableProperty<SliderModel>('slides', slides));
}
}
And here is the viewmodel code
import 'package:flutter/foundation.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:video_player/video_player.dart';
import '../top_level_providers.dart';
final introViewModelProvider = ChangeNotifierProvider<IntroViewModel>((ref) {
//this singleton class provides global access to selected variables
final SharedPreferencesService localSharedPreferencesService =
ref.watch(sharedPreferencesService);
return IntroViewModel(localSharedPreferencesService);
});
class IntroViewModel extends ChangeNotifier {
IntroViewModel(this.localSharedPreferencesService) : super() {
state = localSharedPreferencesService?.isIntroComplete();
// Pointing the video controller to my local asset.
videoController = VideoPlayerController.asset('media/test_search.mp4');
videoController.initialize().then((_) {
// Once the video has been loaded we play the video and set looping to true.
// not autoplaying yet
// videoController.play();
// videoController.setLooping(true);
});
}
final SharedPreferencesService localSharedPreferencesService;
VideoPlayerController videoController;
bool state = false;
int index = 0;
Future<void> completeIntro() async {
await localSharedPreferencesService.setIntroComplete();
state = true;
notifyListeners();
}
Future<void> incrementIntro() async {
++index;
notifyListeners();
}
bool get isIntroComplete => state;
}