I got recaptcha v2 working on flutter web but the issue is that I have to specify the initial height of the SizedBox that holds the HtmlElementView as follows
import 'package:flutter/material.dart';
import 'dart:ui' as ui;
import 'dart:html' as html;
class GoogleCaptchaView {
static registerViewFactory(String viewId, dynamic cb) {
// ignore:undefined_prefixed_name
ui.platformViewRegistry.registerViewFactory(viewId, cb);
}
}
class GCaptchaPlugin extends StatefulWidget {
const GCaptchaPlugin({Key? key}) : super(key: key);
#override
_GCaptchaPluginState createState() => _GCaptchaPluginState();
}
class _GCaptchaPluginState extends State<GCaptchaPlugin> {
String createdViewId = 'column';
#override
void initState() {
// ignore: undefined_prefixed_name
ui.platformViewRegistry.registerViewFactory(
createdViewId,
(int viewId) => html.IFrameElement()
..style.height = double.maxFinite.toString()
..style.width = double.maxFinite.toString()
..src = "/assets/html/recaptcha.html"
..style.border = 'none');
super.initState();
}
#override
Widget build(BuildContext context) {
return Row(
children: <Widget>[
Expanded(
child: SizedBox(
height: 120.0,
child: HtmlElementView (
viewType: createdViewId,
),
),
),
],
mainAxisAlignment: MainAxisAlignment.spaceBetween,
);
}
}
the issue is I cannot find any documentation on how to resize the SizedBox to match the new size when the image picker shows up in reCaptcha V2 so I am stuck with something looking like this
reCaptcha not Resizing
Related
I want to animate my list back and forth with scroll animation this FoodFragment call at the persistent bottom navigation
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:ikwte/AppConstant/StaticData.dart';
import 'package:ikwte/AppConstant/ThemeColors.dart';
import 'package:ikwte/AppUtils/AppUtils.dart';
import 'package:ikwte/ProviderControllers/FoodController.dart';
import 'package:ikwte/Widgets/FragmentWidgets/FoodHelper.dart';
import 'package:ikwte/main.dart';
import 'package:provider/provider.dart';
class FoodFragment extends StatefulWidget {
const FoodFragment({Key? key}) : super(key: key);
#override
State<FoodFragment> createState() => _FoodFragmentState();
}
class _FoodFragmentState extends State<FoodFragment> {
ScrollController _scrollController = ScrollController();
var themeColor = ThemeColors();
var utils = AppUtils();
var static = Statics();
#override
void initState() {
// TODO: implement initState
super.initState();
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
double minScrollExtent1 = _scrollController.position.minScrollExtent;
double maxScrollExtent1 = _scrollController.position.maxScrollExtent;
animateToMaxMin(maxScrollExtent1, minScrollExtent1, maxScrollExtent1, 1,
_scrollController);
print("Function Triggered");
});
print("InitState Triggered");
}
animateToMaxMin(double max, double min, double direction, int seconds,
ScrollController scrollController) {
scrollController
.animateTo(direction,
duration: Duration(seconds: seconds), curve: Curves.linear)
.then((value) {
direction = direction == max ? min : max;
animateToMaxMin(max, min, direction, seconds, scrollController);
});
}
#override
Widget build(BuildContext context) {
FoodHelper helper = FoodHelper(context, _scrollController);
return RefreshIndicator(
backgroundColor: themeColor.yellowColor,
color: themeColor.blueColor,
onRefresh: () async {
await apisCall();
},
child: Scaffold(
backgroundColor: themeColor.blueColor,
body: Column(
children: [
utils.statusBar(context, color: themeColor.blueColor),
Expanded(
child: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
color: themeColor.blueColor,
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
helper.appBar(),
helper.searchFieldText(),
helper.topListHeading(),
helper.topList(),
helper.whatAreYouLookingForHeading(),
helper.whatAreYouLookingForList(),
helper.collaborationsHeading(),
helper.collaborationList(),
helper.newInTownHeading(),
helper.newInTownList(),
helper.allRestaurantsHeading(),
helper.allRestaurantsList()
],
),
)),
),
utils.bottomBar(context, color: themeColor.blueColor),
],
),
),
);
}
apisCall() {
navigatorkey.currentContext!
.read<FoodController>()
.getAllRestaurantsListApi();
navigatorkey.currentContext!.read<FoodController>().getCategoryListApi();
navigatorkey.currentContext!
.read<FoodController>()
.getTopRestaurantsListApi();
navigatorkey.currentContext!
.read<FoodController>()
.getNewInTownRestaurantApi();
navigatorkey.currentContext!.read<FoodController>().getSecretMenuApi();
}
}
But the issue i am facing right now is AddpostFrameCallback Function is not calling on the persistent bottom navigation so my animation is not getting trigged i tried multiple Solutions but it didn't work for me .How can i reslove this issue
My Project was working totally fine a month ago, and now after several flutter updates, my iFrame widget is false centered in its desired renderbox. First picture is the wrong behavior, second is the old working version. I'm using a plugin which prevents the analyzer from prompting errors when using platformViewRegistry. Below is my code for the iframe-widget.
Does someone know how to fix this? I don't want to downgrade to older flutter versions.
Thanks for any help!
PS: Simple Center() did not work
My IFrame Widget
// ignore: avoid_web_libraries_in_flutter
import 'dart:html';
// ignore: undefined_prefixed_name
import 'package:universal_ui/universal_ui.dart';
import 'package:flutter/material.dart';
class Iframe extends StatefulWidget {
final String source;
final Size size;
Iframe(this.source, {this.size});
#override
_IframeState createState() => _IframeState();
}
class _IframeState extends State<Iframe> {
Widget _iframeWidget;
String source;
#override
void initState() {
newFrame();
super.initState();
}
void newFrame() async {
print(widget.size);
final String id = widget.source.hashCode.toString();
final IFrameElement _iframeElement = IFrameElement();
_iframeElement.height = widget.size?.height?.toString() ?? '500';
_iframeElement.width = widget.size?.width?.toString() ?? '500';
source = widget.source;
_iframeElement.src = widget.source;
_iframeElement.style.border = 'none';
ui.platformViewRegistry
.registerViewFactory(id, (int viewID) => _iframeElement);
_iframeWidget = HtmlElementView(
key: UniqueKey(),
viewType: id,
);
}
#override
Widget build(BuildContext context) {
if (source != widget.source) newFrame();
return _iframeWidget;
}
}
Using IFrame Widget
class ChatClientAnon extends StatelessWidget {
#override
Widget build(BuildContext context) {
return StreamCacheBuilder<Package>(
stream: Database().streamPackage(),
builder: (data) => Container(
child: Row(
children: [
Expanded(child: SmartphoneClient('Anonym', isAnon: true), flex: 2),
Expanded(
child: LayoutBuilder(
builder: (_, c) =>
Iframe(data.source, size: c.biggest)),
flex: 8),
],
),
),
);
}
}
Update: issue got fixed with next flutter update
Using flutter 1.20.4
I'm trying to implement a custom digit keyboard (a simple container at the bottom), which should appear into view when tapping on one of the rows in the List.
Here a small snippet of how I do it:
Widget build(BuildContext context) {
BudgetPageState budgetPageState = Provider.of<BudgetPageState>(context, listen: true);
ButtonDial buttonDial =
budgetPageState.showButtonDial ? ButtonDial() : null;
return Scaffold(
appBar: AppBar(
title: Text("Budget Page"),
),
body: Column(children: <Widget>[
Expanded(child: CustomList()),
if (buttonDial != null) buttonDial
]));
}
}
However, when the keyboard appears, the bottom rows get obscured by the container.
I tried using Scrollable.ensureVisible, that works for the middle rows, but the last ones are still obscured. It seems like the ScrollView still has it's old size (full height) when Scrollable.ensureVisible() kicks in (I notice this by looking at the ScrollBar).
Code snippet:
Scrollable.ensureVisible(context, duration: Duration(milliseconds: 200), alignment: 0.5);
See video below.
Keyboard obscures last rows when tapped (here clicking on row 14)
However, once the keyboard is up, the SingleChildScrollView has shrunk to the new size and the Scrollable now works.
When keyboard is up, Scrollable.ensureVisible() does its job(here clicking on row 6 and 12)
I know this is similar to this question, but
I tried multiple things of this issue.
I use a "custom keyboard"
The flutter github issue here below fixed this (I think)
Read through this popular Flutter Github issue, this made me use SingleChildScrollView instead of ListView.
Tried this, this fixes the keyboard obscuring the bottom Rows by shifting them up, however now when clicking on the first Rows, they get moved out of view.
Tried KeyboardAvoider, but as this is not an onscreen Keyboard, I doesn't work.
You'll find a full minimal reproducible example here below.
main.dart
(Main + ChangeNotifierProvider for the state)
import 'package:flutter/material.dart';
import 'package:scrollTest/budgetPage.dart';
import 'package:scrollTest/budgetPageState.dart';
import 'package:provider/provider.dart';
void main() {
runApp(HomeScreen());
}
class HomeScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: ChangeNotifierProvider(
create: (_) => BudgetPageState(), child: BudgetPage()),
),
);
}
}
budgetPage.dart
(Main Page with the CustomList() and the buttonDial (custom keyboard, here just a simple container)
import 'package:flutter/material.dart';
import 'package:scrollTest/budgetPageState.dart';
import 'package:scrollTest/customList.dart';
import 'package:provider/provider.dart';
class BudgetPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
BudgetPageState budgetPageState = Provider.of<BudgetPageState>(context, listen: true);
ButtonDial buttonDial =
budgetPageState.showButtonDial ? ButtonDial() : null;
return Scaffold(
appBar: AppBar(
title: Text("Budget Page"),
),
body: Column(children: <Widget>[
Expanded(child: CustomList()),
if (buttonDial != null) buttonDial
]));
}
}
class ButtonDial extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
height: MediaQuery.of(context).size.height * 0.3,
child: Container(
color: Colors.blue,
),
);
}
}
customList.dart
(Simple List view SingleChildScrollView and a ScrollController)
import 'package:flutter/material.dart';
import 'package:scrollTest/CustomRow.dart';
class CustomList extends StatefulWidget {
#override
_CustomListState createState() => _CustomListState();
}
class _CustomListState extends State<CustomList> {
ScrollController _scrollController;
#override
void initState() {
super.initState();
_scrollController = ScrollController();
}
#override
void dispose() {
_scrollController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scrollbar(
isAlwaysShown: true,
controller: _scrollController,
child: SingleChildScrollView(
controller: _scrollController,
child: Column(
children: _buildList(),
),
),
);
}
}
List<Widget> _buildList() {
List<Widget> widgetList = [];
for (int i = 0; i < 15; i++) {
widgetList.add(CustomRow(rowID: i));
}
return widgetList;
}
customRow.dart
(This is where I scroll to the selected row in handleOnTap)
import 'package:flutter/material.dart';
import 'package:scrollTest/budgetPageState.dart';
import 'package:provider/provider.dart';
class CustomRow extends StatefulWidget {
final int rowID;
CustomRow({Key key, #required this.rowID}) : super(key: key);
#override
_CustomRowState createState() => _CustomRowState();
}
class _CustomRowState extends State<CustomRow> {
BudgetPageState budgetPageState;
void handleOnTap(BuildContext context) {
if (!budgetPageState.isSelected(widget.rowID)) {
Scrollable.ensureVisible(context, duration: Duration(milliseconds: 200), alignment: 0.5);
}
budgetPageState.toggleButtonDial(widget.rowID);
budgetPageState.updateIsSelected(widget.rowID);
}
#override
void initState() {
super.initState();
budgetPageState = Provider.of<BudgetPageState>(context, listen: false);
budgetPageState.insertRowInHashMap(widget.rowID);
}
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap:() => handleOnTap(context),
child: Container(
height: 60,
width: double.infinity,
color: budgetPageState.isSelected(widget.rowID)
? Colors.grey[200]
: Colors.white,
child: Center(
child: Text(
"Test ${widget.rowID}",
),
),
),
);
}
}
budgetPageState.dart
(The state managed using ChangeNotifier. Mainly contains logic for selecting/deselecting a row as well as logic for when to show the keyboard (using bool showButtonDial and notifyListeners())
import 'dart:collection';
import 'package:flutter/material.dart';
class BudgetPageState extends ChangeNotifier {
bool showButtonDial = false;
Map<int, bool> _isSelectedMap = HashMap();
int selectedId = -1;
bool isSelected(int rowId) {
return this._isSelectedMap[rowId];
}
Map<int, bool> get isSelectedMap => _isSelectedMap;
void updateIsSelected(int rowId) async {
///Select the row [rowId] if we tapped on a different one than the one
///that is currently highlighted ([selectedId])
///The same row was tapped, we remove the highlight i.e. we don't
///put it back to [true]
//Unselect all
_isSelectedMap.forEach((k, v) => _isSelectedMap[k] = false);
if (selectedId != rowId) {
this._isSelectedMap[rowId] = true;
selectedId = rowId;
} else {
selectedId = -1;
}
notifyListeners();
}
void toggleButtonDial(int rowId) {
if (!showButtonDial) {
showButtonDial = true;
} else if (rowId == selectedId) {
showButtonDial = false;
}
}
void insertRowInHashMap(int subcatId) {
this._isSelectedMap[subcatId] = false;
}
}
In my code below, I am struggling with LifeCyrles in Flutter where I can update my State in Provider, APPARENTLY, only in didChangeDependencies hook or in a template widget (via events hung up on buttons or so).
Alright, I don't mind that only didChangeDependencies hook works for me BUT when my logic in earlier mentioned hook depends on some class properties I am having problems with the accuracy of the class data.
I get data one step behind (since it's called before build hook I guess).
I cannot run this logic in the build hook because it includes a request to change the state in Provider. If I try to change the state there I've got either this error:
setState() or markNeedsBuild() called during build.
or this one
The setter 'lastPage=' was called on null.
Receiver: null
Tried calling: lastPage=true
What I want to do: I've got a wrapper widget which holds three other widgets: footer, header and pageViewer.
When I reach the last page I need to notify my wrapper widget about that so it reacts accordingly and hides header and footer.
I would appreciate any help here!
The focused code:
Here is the problem and must be solution
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:ui_flutter/screens/welcome/welcome_bloc.dart';
import 'package:flutter/scheduler.dart';
class _FooterState extends State<Footer> {
#override
void initState() {
super.initState();
}
#override
void didChangeDependencies() {
super.didChangeDependencies();
final WelcomeBloc _welcome = Provider.of<WelcomeBloc>(context);
_welcomeBloc = _welcome;
// this._detectLastPage();
}
#override
Widget build(BuildContext context) {
return Container(
alignment: Alignment.bottomCenter,
padding: EdgeInsets.symmetric(vertical: 30.0, horizontal: 30.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
this.stepper,
this.nextArrow,
],
),
);
}
_detectLastPage() {
// Here I've got inaccurate data
print(this.widget.currentStep);
}
}
I have already tried some other hooks like Scheduler but maybe I did something wrong there.
SchedulerBinding.instance
.addPostFrameCallback((_) => this._detectLastPage());
It's called only once at the first build-up round and that's it.
I lack an Angular hook here AfterViewInit. It would be handy here.
or Mounted in VueJS
That's the rest of my code if you'd like to see the whole picture.
If you have any suggestions on the architecture, structure or something else you are welcome. It's highly appreciated since I'm new to Flutter.
main.dart
import 'package:flutter/material.dart';
import 'package:ui_flutter/routing.dart';
import 'package:provider/provider.dart';
import 'screens/welcome/welcome_bloc.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => WelcomeBloc()),
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
initialRoute: '/welcome',
onGenerateRoute: RouteGenerator.generateRoute,
),
);
}
}
welcome.dart (my wrapper)
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:provider/provider.dart';
import 'package:ui_flutter/screens/welcome/welcome_bloc.dart';
import './footer.dart';
import './viewWrapper.dart';
import './header.dart';
// import 'package:ui_flutter/routing.dart';
class Welcome extends StatefulWidget {
#override
_WelcomeState createState() => _WelcomeState();
}
class _WelcomeState extends State<Welcome> {
WelcomeBloc _welcomeBloc;
#override
Widget build(BuildContext context) {
final WelcomeBloc _welcome = Provider.of<WelcomeBloc>(context);
this._welcomeBloc = _welcome;
print('Welcome: _welcome.currentPage - ${this._welcomeBloc.lastPage}');
return Scaffold(
body: SafeArea(
child: Stack(
children: <Widget>[
ViewerWrapper(),
Footer(
currentStep: _welcomeBloc.currentPage,
totalSteps: 3,
activeColor: Colors.grey[800],
inactiveColor: Colors.grey[100],
),
WelcomeHeader,
],
),
),
);
}
}
welcomeBloc.dart (my state via Provider)
import 'package:flutter/material.dart';
class WelcomeBloc extends ChangeNotifier {
PageController _controller = PageController();
int _currentPage;
bool _lastPage = false;
bool get lastPage => _lastPage;
set lastPage(bool value) {
_lastPage = value;
notifyListeners();
}
int get currentPage => _currentPage;
set currentPage(int value) {
_currentPage = value;
notifyListeners();
}
get controller => _controller;
nextPage(Duration duration, Curves curve) {
controller.nextPage(duration: duration, curve: curve);
}
}
footer.dart (that's where I've problems with data at the very bottom of the code - _detectLastPage method)
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:ui_flutter/screens/welcome/welcome_bloc.dart';
import 'package:flutter/scheduler.dart';
class Footer extends StatefulWidget {
final int currentStep;
final int totalSteps;
final Color activeColor;
final Color inactiveColor;
final Duration duration;
final Function onFinal;
final Function onStart;
Footer({
this.activeColor,
this.inactiveColor,
this.currentStep,
this.totalSteps,
this.duration,
this.onFinal,
this.onStart,
}) {}
#override
_FooterState createState() => _FooterState();
}
class _FooterState extends State<Footer> {
final double radius = 10.0;
final double distance = 4.0;
Container stepper;
Container nextArrow;
bool lastPage;
WelcomeBloc _welcomeBloc;
#override
void didChangeDependencies() {
super.didChangeDependencies();
final WelcomeBloc _welcome = Provider.of<WelcomeBloc>(context);
_welcomeBloc = _welcome;
this._detectLastPage();
}
#override
Widget build(BuildContext context) {
this._makeStepper();
this._makeNextArrow();
return Container(
alignment: Alignment.bottomCenter,
padding: EdgeInsets.symmetric(vertical: 30.0, horizontal: 30.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
this.stepper,
this.nextArrow,
],
),
);
}
_makeCirle(activeColor, inactiveColor, position, currentStep) {
currentStep = currentStep == null ? 0 : currentStep - 1;
Color color = (position == currentStep) ? activeColor : inactiveColor;
return Container(
height: this.radius,
width: this.radius,
margin: EdgeInsets.only(left: this.distance, right: this.distance),
decoration: BoxDecoration(
color: color,
border: Border.all(color: activeColor, width: 2.0),
borderRadius: BorderRadius.circular(50.0)),
);
}
_makeStepper() {
List<Container> circles = List();
for (var i = 0; i < widget.totalSteps; i++) {
circles.add(
_makeCirle(this.widget.activeColor, this.widget.inactiveColor, i,
this.widget.currentStep),
);
}
this.stepper = Container(
child: Row(
children: circles,
),
);
}
_makeNextArrow() {
this.nextArrow = Container(
child: Padding(
padding: const EdgeInsets.only(right: 8.0),
child: GestureDetector(
onTap: () {
_welcomeBloc.controller.nextPage(
duration: this.widget.duration ?? Duration(milliseconds: 500),
curve: Curves.easeInOut,
);
},
child: Icon(
Icons.arrow_forward,
)),
),
);
}
_onLastPage() {
if (this.widget.onFinal != null) {
this.widget.onFinal();
}
}
_onFirstPage() {
if (this.widget.onStart != null) {
this.widget.onStart();
}
}
_detectLastPage() {
// Here I've got inaccurate data
int currentPage =
this.widget.currentStep == null ? 1 : this.widget.currentStep;
if (currentPage == 1 && this.widget.currentStep == null) {
this._onFirstPage();
} else if (currentPage == this.widget.totalSteps) {
print('lastPage detected');
setState(() {
this.lastPage = true;
});
_welcomeBloc.lastPage = true;
this._onLastPage();
} else {
setState(() {
this.lastPage = false;
});
_welcomeBloc.lastPage = false;
}
}
}
Thanks in advance!
I am new to flutter as well, But I have learned about a few architecture patterns that have helped me build some apps.
Here is how I do it:
Create a Provider which holds the data for you in runtime. (It can be a Bloc in your case). Stick to one architecture, don't try to put providers and blocs in the same project. Both are used for state management and only using one would be a great practice.
Second, Register the providers using ChangeNotificationProvider or any other widgets which does a similar job of rebuilding the child widget when a data gets changed.
Third, Get the provider in the build method of the widget that is supposed to change when the value of the variable provider changes. This way only the concerned widget is redrawn.
For your case,
If you want to hide the header and footer once you reach the last page, you can declare a variable, let's say isLastPage set to false by default in your provider.
Next, wrap the widget, i.e. header and footer with ChangeNotificationListner
Now, let that widget decide what it has to do based on the value of isLastPage, either hide itself or show.
I hope this helps!
At the long run, I seem to have found Mounted lifecycle hook in Flutter which is implemented with the help of Future.microtask. Unlike .addPostFrameCallback:
SchedulerBinding.instance
.addPostFrameCallback((_) => this._detectLastPage());
Which is triggered only once like InitState (but only at the end of the build execution), Future.microtask can be placed inside build block and be invoked after every change and state update.
It doesn't solve the problem with the inaccurate state in didChangeDependencies hook but provides another way to perform post-build executions.
Credits for the current solution to #Abion47
example
Future.microtask(() => this._detectLastPage());
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();
});
}
});
}
}