Closed renehw closed 10 months ago
Hi @renehw ! Can you check that the last modifications fix your bug ? It actually can't dynamically set the orientation, but you can manage this directly from your widget which implements BarcodeScannerWidget
by setting the orientation
parameter.
Hello!
I will update and test. I'll get back to you as soon as I finish the tests, but I believe everything is ok. Thanks!
Hello @Verbruik !
I ran the tests again and the problem still persists.
I'm sorry, I hadn't paid attention to the message, so I ended up not implementing the new parameter. I'll make the adjustment and test again.
Hello @renehw ! Did you test with the new parameter ?
Hello @Verbruik , I used the parameter you mentioned "orientation", but the problem still occurs.
Ok, just to precise, the new parameter "orientation" doesn't manage the orientation dynamically, it's an initialization param which set the orientation of the camera when the view is created. I'll certainly add the possibility to track the orientation and set it dynamically later but right now i'm out of time for that :sweat_smile:
Can you ensure me that the orientation is not set when the view is created ?
I was using the following code in the initState of the screen that renders the camera:
@override
void initState() {
SystemChrome.setPreferredOrientations([
DeviceOrientation.landscapeLeft,
DeviceOrientation.landscapeRight,
]);
super.initState();
}
Any news?
Hi ! I'm currently working on the plugin and will check this asap. Sorry for the waiting :sweat_smile:
No problem, if you need more details you can ask me.
Perhaps information that was not clear in my last message, but the code snippet I sent causes the screen to be automatically rotated when starting the screen where the camera widget is called. More precisely, before the camera widget is initialized.
Hello !
I ran the example app and test with a forced orientation as you suggested and everything run fine with my two devices for testing, can you send me an example app which reproduce the bug ?
[✓] Connected device (3 available) • Mathieu's iPhone (mobile) • 0f2eb882713fb79a7a0cd535e5f62f586d7468af • ios • iOS 15.4.1 19E258
[✓] Connected device (3 available) • Mathieu’s iPhone (mobile) • 00008101-0015292922FA001E • ios • iOS 16.6.1 20G81
Hi!
This is the code I use in my app
class LeitorCodigo extends StatefulWidget {
const LeitorCodigo({super.key});
@override
State<LeitorCodigo> createState() => _LeitorCodigoState();
}
class _LeitorCodigoState extends State<LeitorCodigo> {
bool withOverlay = true;
bool toggleFlash = false;
@override
void initState() {
SystemChrome.setPreferredOrientations([
DeviceOrientation.landscapeLeft,
DeviceOrientation.landscapeRight,
]);
super.initState();
}
@override
void dispose() {
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
BarcodeScanner.stopScanner();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
extendBodyBehindAppBar: true,
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0.0,
leading: IconButton(
icon: const Icon(
Icons.close,
color: Colors.white,
),
onPressed: () {
Navigator.pop(context);
},
),
actions: [
IconButton(
icon: Icon(
toggleFlash == true ? Icons.flash_on : Icons.flash_off,
color: Colors.white,
),
tooltip: 'Flash',
onPressed: () async {
setState(() {
toggleFlash = !toggleFlash;
});
await BarcodeScanner.toggleFlashlight();
},
),
],
),
body: Builder(
builder: (context) {
return SmartlookTrackingWidget(
isSensitive: true,
child: Stack(
children: [
BarcodeScannerWidget(
orientation: CameraOrientation.landscapeLeft,
startScanning: true,
stopScanOnBarcodeDetected: true,
onBarcodeDetected: (barcode) {
log('leitura realizada');
Navigator.pop(context, barcode.value);
},
onError: (error) {
log('Erro na leitura');
},
),
Align(alignment: Alignment.center, child: Divider(color: Colors.red[400], thickness: 0.8)),
ColorFiltered(
colorFilter: ColorFilter.mode(
Colors.black.withOpacity(0.4),
BlendMode.srcOut,
),
child: Stack(
children: [
Container(
decoration: const BoxDecoration(
color: Colors.black,
backgroundBlendMode: BlendMode.dstOut,
),
),
Center(
child: AnimatedContainer(
width: MediaQuery.sizeOf(context).width * 1,
height: MediaQuery.sizeOf(context).height * 0.55,
color: Colors.white,
margin: const EdgeInsets.only(top: 10.0),
duration: const Duration(milliseconds: 150),
),
),
],
),
),
],
),
);
},
),
);
}
}
Hi ! Thanks to your code I found where is the problem and I'm happy to say that the plugin works as it should :-)
Because you set the SystemChrome.orientation value before this screen, the async call to setPreferredOrientations to landscape is not over when the BarcodeScannerPlugin is intialized and it takes the value of the screen in portrait mode, you can check that the switch is over before initialize the Scanner and it works well !
Add a startScanner variable and set it when the orientation is set, I'm not 100% sure that's the proper way to do it, but it still work anyway... 😅
class _LeitorCodigoState extends State<LeitorCodigo> {
bool withOverlay = true;
bool toggleFlash = false;
bool startScanner = false;
@override
void initState() {
SystemChrome.setPreferredOrientations([
DeviceOrientation.landscapeLeft,
DeviceOrientation.landscapeRight,
]);
super.initState();
}
@override
void dispose() {
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
BarcodeScanner.stopScanner();
super.dispose();
}
@override
Widget build(BuildContext context) {
debugPrint('################## ${MediaQuery.sizeOf(context).width}');
if (!startScanner && MediaQuery.sizeOf(context).width > MediaQuery.sizeOf(context).height) {
WidgetsBinding.instance.addPostFrameCallback((_) {
debugPrint('####################### start scanner !!!!!!');
if (context.mounted) setState(() => startScanner = true);
});
}
return Scaffold(
backgroundColor: Colors.black,
extendBodyBehindAppBar: true,
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0.0,
leading: IconButton(
icon: const Icon(
Icons.close,
color: Colors.white,
),
onPressed: () {
Navigator.pop(context);
},
),
actions: [
IconButton(
icon: Icon(
toggleFlash == true ? Icons.flash_on : Icons.flash_off,
color: Colors.white,
),
tooltip: 'Flash',
onPressed: () async {
setState(() {
toggleFlash = !toggleFlash;
});
await BarcodeScanner.toggleFlashlight();
},
),
],
),
body: Builder(
builder: (context) {
return Stack(
children: [
!startScanner ? Container() : BarcodeScannerWidget(
orientation: CameraOrientation.landscapeLeft,
startScanning: true,
stopScanOnBarcodeDetected: true,
onBarcodeDetected: (barcode) {
print('leitura realizada');
Navigator.pop(context, barcode.value);
},
onError: (error) {
print('Erro na leitura');
},
),
Align(alignment: Alignment.center, child: Divider(color: Colors.red[400], thickness: 0.8)),
ColorFiltered(
colorFilter: ColorFilter.mode(
Colors.black.withOpacity(0.4),
BlendMode.srcOut,
),
child: Stack(
children: [
Container(
decoration: const BoxDecoration(
color: Colors.black,
backgroundBlendMode: BlendMode.dstOut,
),
),
Center(
child: AnimatedContainer(
width: MediaQuery.sizeOf(context).width * 1,
height: MediaQuery.sizeOf(context).height * 0.55,
color: Colors.white,
margin: const EdgeInsets.only(top: 10.0),
duration: const Duration(milliseconds: 150),
),
),
],
),
),
],
);
},
),
);
}
}
Hello @Verbruik , thank you for your help, I suspected it could be this, but as it was working fine on Android I expected it to be something from the package, and unfortunately as I don't have a physical iOS device, I wasn't able to test whether it could be this delay situation, thanks for the clarification, I will try to provide a device to perform the adjustment.
Thanks again, and I appreciate the package, I noticed that it provides better performance than others due to the use of recent SDKs, thank you and great work!!!
Hello guys,
For a side-note, if you depend on a future to build your widget, you should consider the FutureBuilder
which will handle this specific case. :wink:
class _LeitorCodigoState extends State<LeitorCodigo> {
// Calls the future (either in the field initialization as here or in initState)
final Future<void> _orientationFuture = SystemChrome.setPreferredOrientations([
DeviceOrientation.landscapeLeft,
DeviceOrientation.landscapeRight,
]);
@override
Widget build(BuildContext context) {
return FutureBuilder<void>(
future: _orientationFuture,
builder: (BuildContext context, AsyncSnapshot<void> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
// The future has completed.
} else {
// Future not complete yet
}
},
);
}
}
A new problem has been identified, it appears that iOS now does not respect the guidance.
The following image shows the phone in portrait mode, but the camera is in landscape mode, the image being captured is also in portrait mode, and not as in the capture. Strangely what I did was remove the code orientation: CameraOrientation.landscapeLeft,
from the BarcodeScannerWidget.
Some help?
my initState and dispose are like this:
@override
void initState() {
SystemChrome.setPreferredOrientations([
DeviceOrientation.landscapeLeft,
DeviceOrientation.landscapeRight,
]);
super.initState();
}
@override
void dispose() {
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
BarcodeScanner.stopScanner();
super.dispose();
}
Hello!
Any solution?
Hello !
I think what you pointed as a new problem is the desired behavior. I'm agree that it's not the best solution, and it will be fixed later, but ATM the orientation is not set dynamically on iOS native side, so you must set the orientation for BarcodeScannerWidget if you want to change the camera orientation.
Does this answer your question ? :sweat_smile:
Hello
This BarcodeScannerWidget orientation would be orientation: CameraOrientation.landscapeLeft,
. The parameter you added some time ago?
If this is the case, I've already added it, and this causes another bug where when the camera is opened, the image is rendered upside down.
@Verbruik
Hello!
Has there been any progress on the problem?
Hi !
I'm sorry that it's taking so long but I'm quite busy for the moment :sweat:
Be sure that I don't forget you and will fix this asap !
Hi @renehw !
This BarcodeScannerWidget orientation would be orientation: CameraOrientation.landscapeLeft,. The parameter you added some time ago?
If this is the case, I've already added it, and this causes another bug where when the camera is opened, the image is rendered upside down.
I think there is a confusion between landscapeLeft and landscapeRight, if the screen is upside down it's probably because you try to set the orientation to the wrong one. The problem here is that Flutter doesn't given a proper way to get the device orientation (left or right), so there is a couple of solutions for you :
setPreferredOrientations
to the only (left or right) landscape mode you want to supportI surely implement a detection of the orientation later on the plugin but right now I don't have time for that. If you are determinate and have a little bit of time to share with us, feel free to create a new MR with the code which detect the screen orientation 😄
Thanks for the report, if you have and other issue don't hesitate to create a new issue or reopen this one if the problem still with those suggestions 😉
I found a bug when opening the code reader on iPhone, specifically iOS 16.6.1 and 17.0.3. When opening, the screen is divided into half with the camera open and the other half with a black stripe.