I want to show AlertDialog on click of drawer item
I'm using below code to use navigation drawer item in my flutter app
class HomePage extends StatefulWidget {
final drawerItems = [
DrawerItem("View Your account", Icons.account_circle),
DrawerItem("Request", Icons.receipt),
DrawerItem("Order", Icons.shopping_cart),
DrawerItem("Report", Icons.report_problem),
DrawerItem("Log out", Icons.info)
];
#override
State<StatefulWidget> createState() {
return new HomePageState();
}
}
class HomePageState extends State<HomePage> {
int _selectedDrawerIndex = 0;
bool visibilityTag = false;
showAlertDialog(BuildContext context) {
// set up the button
Widget okButton = FlatButton(
child: Text("OK"),
onPressed: () {
Navigator.of(context).pop();
},
);
Widget cancelButton = FlatButton(
child: Text("Cancel"),
onPressed: () {
Navigator.of(context).pop();
},
);
// set up the AlertDialog
AlertDialog alert = AlertDialog(
elevation: 10,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20.0))),
title: Text("ORICON"),
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text("Are you sure you want to logout?"),
Padding(
padding: const EdgeInsets.only(top: 20.0),
child: Text(
"1300 898 989",
style: TextStyle(
color: Colors.blue,
fontWeight: FontWeight.bold,
fontSize: 20.0),
),
),
],
),
actions: [okButton, cancelButton],
);
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return alert;
},
);
}
_getDrawerItemWidget(int pos) {
switch (pos) {
case 0:
visibilityTag = false;
return AccountDetails();
case 1:
visibilityTag = true;
return RequestBin();
case 2:
visibilityTag = true;
return OrderBin();
case 3:
visibilityTag = true;
return Report();
case 4:
showAlertDialog(context);
visibilityTag = false;
return AccountDetails();
default:
return new Text("Error");
}
}
_onSelectItem(int index) {
if (index == 0) {
visibilityTag = false;
} else {
visibilityTag = true;
}
// setState(() => _selectedDrawerIndex = index);
_selectedDrawerIndex = index; // removed setState call
Navigator.of(context).pop(); // close the drawer
}
#override
Widget build(BuildContext context) {
List<Widget> drawerOptions = [];
for (var i = 0; i < widget.drawerItems.length; i++) {
var d = widget.drawerItems[i];
drawerOptions.add(new ListTile(
leading: Icon(d.icon),
title: Text(d.title),
selected: i == _selectedDrawerIndex,
onTap: () => _onSelectItem(i),
));
}
Future<bool> customPop() {
if (_selectedDrawerIndex == 0) {
visibilityTag = false;
return Future.value(true);
} else {
setState(() {
visibilityTag = false;
_selectedDrawerIndex = 0;
});
return Future.value(false);
}
}
void navigateToHomeScreen() {
if (_selectedDrawerIndex == 0) {
visibilityTag = false;
} else {
visibilityTag = false;
setState(() {
_selectedDrawerIndex = 0;
});
}
}
return WillPopScope(
onWillPop: customPop,
child: Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
iconTheme: IconThemeData(color: Colors.black), //add this line here
// here we display the title corresponding to the fragment
// you can instead choose to have a static title
title: Text(
widget.drawerItems[_selectedDrawerIndex].title,
style: TextStyle(color: Colors.black),
),
actions: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 10),
child: Visibility(
visible: visibilityTag,
child: Row(
children: <Widget>[
IconButton(
icon: new Icon(Icons.arrow_back_ios),
color: Colors.grey,
onPressed: navigateToHomeScreen,
),
Text(
"BACK",
style: TextStyle(color: Colors.grey),
)
],
)),
)
],
),
drawer: Drawer(
child: Column(
children: <Widget>[
UserAccountsDrawerHeader(
accountName: new Text("Nilesh Rathod"), accountEmail: null),
Column(children: drawerOptions)
],
),
),
body: _getDrawerItemWidget(_selectedDrawerIndex)),
);
}
}
But I'm getting below Exception
This Overlay widget cannot be marked as needing to build because the framework is already in the process of building widgets. A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was: Overlay-[LabeledGlobalKey<OverlayState>#7e1a8]
state: OverlayState#72b8b(entries: [OverlayEntry#cf40a(opaque: false; maintainState: false), OverlayEntry#e10aa(opaque: false; maintainState: true), OverlayEntry#e0ccc(opaque: false; maintainState: false), OverlayEntry#5fdab(opaque: false; maintainState: true)])
The widget which was currently being built when the offending call was made was: HomePage
dirty
dependencies: [_InheritedTheme, _LocalizationsScope-[GlobalKey#c84d4]]
state: HomePageState#982b0
User-created ancestor of the error-causing widget was:
MaterialApp file:///home/ctpl119/Documents/NEW_PROJECT/oricon/oricon/lib/main.dart:11:10
When the exception was thrown, this was the stack:
#0 Element.markNeedsBuild.<anonymous closure> (package:flutter/src/widgets/framework.dart:3687:11)
#1 Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:3702:6)
#2 State.setState (package:flutter/src/widgets/framework.dart:1161:14)
#3 OverlayState.insertAll (package:flutter/src/widgets/overlay.dart:346:5)
#4 OverlayRoute.install (package:flutter/src/widgets/routes.dart:43:24)
I have already checked below Stack-overflow links
Flutter - Cannot build because the frawework is already building
Flutter - Cannot build because the frawework is already building
Flutter Error: "Widget cannot build because is already in the process of building"
Assertion on Navigator.push() caused by OverlayEntry in Flutter
Adding OverlayEntry in Flutter
setState() or markNeedsBuild() called during build flutter
If need more information please do let me know. Thanks in advance. Your efforts will be appreciated.
You can copy paste run full code below
You need WidgetsBinding.instance.addPostFrameCallback
code snippet
case 4:
//showAlertDialog(context);
WidgetsBinding.instance.addPostFrameCallback((_) {
showAlertDialog(context);
});
visibilityTag = false;
return AccountDetails();
working demo
full code
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: HomePage(),
);
}
}
class DrawerItem {
String title;
IconData icon;
DrawerItem(this.title, this.icon);
}
class HomePage extends StatefulWidget {
final drawerItems = [
DrawerItem("View Your account", Icons.account_circle),
DrawerItem("Request", Icons.receipt),
DrawerItem("Order", Icons.shopping_cart),
DrawerItem("Report", Icons.report_problem),
DrawerItem("Log out", Icons.info)
];
#override
State<StatefulWidget> createState() {
return new HomePageState();
}
}
class HomePageState extends State<HomePage> {
int _selectedDrawerIndex = 0;
bool visibilityTag = false;
showAlertDialog(BuildContext context) {
// set up the button
Widget okButton = FlatButton(
child: Text("OK"),
onPressed: () {
Navigator.of(context).pop();
},
);
Widget cancelButton = FlatButton(
child: Text("Cancel"),
onPressed: () {
Navigator.of(context).pop();
},
);
// set up the AlertDialog
AlertDialog alert = AlertDialog(
elevation: 10,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20.0))),
title: Text("ORICON"),
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text("Are you sure you want to logout?"),
Padding(
padding: const EdgeInsets.only(top: 20.0),
child: Text(
"1300 898 989",
style: TextStyle(
color: Colors.blue,
fontWeight: FontWeight.bold,
fontSize: 20.0),
),
),
],
),
actions: [okButton, cancelButton],
);
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return alert;
},
);
}
_getDrawerItemWidget(int pos) {
switch (pos) {
case 0:
visibilityTag = false;
return AccountDetails();
case 1:
visibilityTag = true;
return RequestBin();
case 2:
visibilityTag = true;
return OrderBin();
case 3:
visibilityTag = true;
return Report();
case 4:
//showAlertDialog(context);
WidgetsBinding.instance.addPostFrameCallback((_) {
showAlertDialog(context);
});
visibilityTag = false;
return AccountDetails();
default:
return new Text("Error");
}
}
_onSelectItem(int index) {
if (index == 0) {
visibilityTag = false;
} else {
visibilityTag = true;
}
setState(() => _selectedDrawerIndex = index);
//_selectedDrawerIndex = index; // removed setState call
Navigator.of(context).pop(); // close the drawer
}
#override
Widget build(BuildContext context) {
List<Widget> drawerOptions = [];
for (var i = 0; i < widget.drawerItems.length; i++) {
var d = widget.drawerItems[i];
drawerOptions.add(new ListTile(
leading: Icon(d.icon),
title: Text(d.title),
selected: i == _selectedDrawerIndex,
onTap: () => _onSelectItem(i),
));
}
Future<bool> customPop() {
if (_selectedDrawerIndex == 0) {
visibilityTag = false;
return Future.value(true);
} else {
setState(() {
visibilityTag = false;
_selectedDrawerIndex = 0;
});
return Future.value(false);
}
}
void navigateToHomeScreen() {
if (_selectedDrawerIndex == 0) {
visibilityTag = false;
} else {
visibilityTag = false;
setState(() {
_selectedDrawerIndex = 0;
});
}
}
return WillPopScope(
onWillPop: customPop,
child: Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
iconTheme: IconThemeData(color: Colors.black), //add this line here
// here we display the title corresponding to the fragment
// you can instead choose to have a static title
title: Text(
widget.drawerItems[_selectedDrawerIndex].title,
style: TextStyle(color: Colors.black),
),
actions: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 10),
child: Visibility(
visible: visibilityTag,
child: Row(
children: <Widget>[
IconButton(
icon: new Icon(Icons.arrow_back_ios),
color: Colors.grey,
onPressed: navigateToHomeScreen,
),
Text(
"BACK",
style: TextStyle(color: Colors.grey),
)
],
)),
)
],
),
drawer: Drawer(
child: Column(
children: <Widget>[
UserAccountsDrawerHeader(
accountName: new Text("Nilesh Rathod"), accountEmail: null),
Column(children: drawerOptions)
],
),
),
body: _getDrawerItemWidget(_selectedDrawerIndex)),
);
}
}
class AccountDetails extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Text("AccountDetails");
}
}
class RequestBin extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Text("RequestBin");
}
}
class OrderBin extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Text("OrderBin");
}
}
class Report extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Text("Report");
}
}
You should make _selectedDrawerIndex a global variable (aka put it above the classes). You don't need to use setState to change the value of the variable. When you pop a route, it causes the widget to rebuild.
_onSelectItem(int index) {
if (index == 0) {
visibilityTag = false;
} else {
visibilityTag = true;
}
_selectedDrawerIndex = index; // removed setState call
Navigator.of(context).pop();
}
Also, functions like showAlertDialog(context); should not be in a setState call.
So, in summary:
Remove setState calls that change the value of _selectedDrawerIndex and showAlertDialog.
showAlertDialog has a builder so there's no reason to call setState if it's going to rebuild anyways.
_getDrawerItemWidget(int pos) {
switch (pos) {
case 0:
visibilityTag = false;
return AccountDetails();
case 1:
visibilityTag = true;
return RequestBin();
case 2:
visibilityTag = true;
return OrderBin();
case 3:
visibilityTag = true;
return Report();
case 4:
setState(() {
visibilityTag = false;
});
showAlertDialog(context);
return AccountDetails();
default:
return new Text("Error");
}
}
Related
I am using qr_code_scanner to scan a qr code in flutter . The point here is that it shows a black screen instead of showing a scanner . I cant seem to start the qr reader . but suppose i exit the app like put the app in the background and then come to the app again the camera suddenly started . Cant seem to find why the camera dosent start on the app start .
class Home extends StatefulWidget {
const Home({Key? key}) : super(key: key);
#override
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: QrScan(),
);
}
}
class QrScan extends StatefulWidget {
const QrScan({Key? key}) : super(key: key);
#override
State<QrScan> createState() => _QrScanState();
}
class _QrScanState extends State<QrScan> {
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
Barcode? result;
QRViewController? controller;
#override
void initState() {
super.initState();
controller?.resumeCamera();
}
// 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,
overlay: QrScannerOverlayShape(
borderRadius: 10, borderWidth: 5, borderColor: Colors.white),
),
),
Expanded(
flex: 1,
child: Center(
child: (result != null)
? Text(
'Barcode Type: ${describeEnum(result!.format)} Data: ${result?.code}')
: Text('Scan a code'),
),
)
],
),
);
}
void _onQRViewCreated(QRViewController controller) {
this.controller = controller;
controller.scannedDataStream.listen((scanData) {
setState(() {
result = scanData;
});
});
}
#override
void dispose() {
controller?.dispose();
super.dispose();
}
}
Try to pause and resume the camera inside your _onQRViewCreated:
void _onQRViewCreated(QRViewController controller) {
this.controller = controller;
controller.scannedDataStream.listen((scanData) {
setState(() {
result = scanData;
});
});
controller.pauseCamera();
controller.resumeCamera();
}
Try this it will surely solve the problem!
#override
Widget build(BuildContext context) {
if (controller != null && mounted) {
controller!.pauseCamera();
controller!.resumeCamera();
}
Use the below code if you are using the flashlight feature!
class QRScanner extends StatefulWidget {
const QRScanner({Key? key}) : super(key: key);
#override
State<StatefulWidget> createState() => _QRScannerState();
}
class _QRScannerState extends State<QRScanner> {
Barcode? result;
QRViewController? controller;
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
bool isflash = false;
// 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();
controller!.resumeCamera();
}
controller!.resumeCamera();
}
#override
Widget build(BuildContext context) {
if (controller != null && mounted && !isflash) {
controller!.pauseCamera();
controller!.resumeCamera();
}
return Scaffold(
appBar:
appBar(context, backbutton: true, icon: true, notifications: true),
body: Stack(
children: <Widget>[
_buildQrView(context),
Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
// if (result != null)
// Text(
// 'Barcode Type: ${describeEnum(result!.format)} Data: ${result!.code}',
// style: const TextStyle(color: Colors.white),
// )
// else
// const Text('Scan a code'),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
GestureDetector(
onTap: () async {
isflash = !isflash;
await controller?.toggleFlash();
setState(() {});
},
child: Container(
margin: const EdgeInsets.all(8),
child: FutureBuilder(
future: controller?.getFlashStatus(),
builder: (context, snapshot) {
return snapshot.data == false
? const Icon(
Icons.flash_off,
color: Colors.white,
)
: const Icon(Icons.flash_on, color: Colors.white);
},
),
),
),
GestureDetector(
onTap: () async {
await controller?.flipCamera();
setState(() {});
},
child: Container(
margin: const EdgeInsets.all(8),
child: FutureBuilder(
future: controller?.getCameraInfo(),
builder: (context, snapshot) {
if (snapshot.data != null) {
return const Icon(Icons.cameraswitch_rounded,
color: Colors.white);
} else {
return const SizedBox();
}
},
),
),
)
],
),
],
)
],
),
);
}
Widget _buildQrView(BuildContext context) {
var scanArea = (Get.width < 400 || Get.height < 400) ? 230.0 : 330.0;
return QRView(
key: qrKey,
onQRViewCreated: _onQRViewCreated,
overlay: QrScannerOverlayShape(
borderColor: buttonColor,
borderRadius: 2,
borderLength: 35,
borderWidth: 6,
cutOutSize: scanArea),
onPermissionSet: (ctrl, p) => _onPermissionSet(context, ctrl, p),
);
}
void _onQRViewCreated(QRViewController controller) {
setState(() {
this.controller = controller;
});
controller.scannedDataStream.listen((scanData) {
if (scanData != null) {
setState(() {
result = scanData;
});
Get.find<QRService>().updateResult(scanData.code);
// Get.defaultDialog(
// content: Text("${scanData.code}"),
// );
Get.back();
// Get.offAll(() => const QRmainScreen());
}
});
}
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() {
controller?.dispose();
super.dispose();
}
}
Remove resume camera from init state
#override
void initState() {
super.initState();
//controller?.resumeCamera();
}
I'm creating a quiz app using Flutter & Firebase. I've fetched questions & options which don't contain images using Firebase, but I'm not able to fetch questions that contain an image in them.
This is a screenshot of the question, which doesn't have an image, I've fetched in the app:
Question with image is like shown below in excel format:
All these data except images are fetched from JSON file imported in Realtime Database in Firebase.
Below is the code where questions are fetched from Realtime database in Firebase:
import 'package:http/http.dart' as http;
import './question_model.dart';
import 'dart:convert';
import '../test.dart';
class DBconnect {
final url = Uri.parse(
'https://rto1-798fc-default-rtdb.firebaseio.com/questions.json');
Future<List<Question>> fetchQuestions() async {
return http.get(url).then((response) {
var data = json.decode(response.body) as Map<String, dynamic>;
List<Question> newQuestions = [];
data.forEach((key, value) {
var newQuestion = Question(
id: key,
title: value['title'],
options: Map.castFrom(value['options']),
);
newQuestions.add(newQuestion);
newQuestions.shuffle();
});
return newQuestions;
});
}
}
Below is the question model:
class Question {
final String id;
final String title;
final Map<String, bool> options;
Question({
required this.id,
required this.title,
required this.options,
});
#override
String toString() {
return 'Question(id: $id, title: $title, options: $options)';
}
}
Below is the question widget:
import 'package:flutter/material.dart';
import '../constants.dart';
class QuestionWidget extends StatelessWidget {
const QuestionWidget(
{Key? key,
required this.question,
required this.indexAction,
required this.totalQuestions})
: super(key: key);
final String question;
final int indexAction;
final int totalQuestions;
#override
Widget build(BuildContext context) {
return Container(
alignment: Alignment.centerLeft,
child: Text(
'Question ${indexAction + 1}/20: $question',
style: const TextStyle(
fontSize: 24.0,
color: neutral,
),
),
);
}
}
And this is the main page:
import 'package:flutter/material.dart';
import '../constants.dart';
import '../models/question_model.dart';
import '../widgets/question_widget.dart';
import '../widgets/next_button.dart';
import '../widgets/option_card.dart';
import '../widgets/result_box.dart';
import '../models/db_connect.dart';
class TestScreen extends StatefulWidget {
const TestScreen({Key? key}) : super(key: key);
#override
State<TestScreen> createState() => _TestScreenState();
}
class _TestScreenState extends State<TestScreen> {
var db = DBconnect();
late Future _questions;
Future<List<Question>> getData() async {
return db.fetchQuestions();
}
#override
void initState() {
_questions = getData();
super.initState();
}
int index = 0;
int score = 0;
bool isPressed = false;
bool isAlreadySelected = false;
void nextQuestion(int questionLength) {
if (index == 19 || score == 12) {
showDialog(
context: context,
barrierDismissible: false,
builder: (ctx) => ResultBox(
result: score,
questionLength: questionLength,
));
} else {
if (isPressed) {
setState(() {
index++;
isPressed = false;
isAlreadySelected = false;
});
} else {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: const Text('Please select any option'),
behavior: SnackBarBehavior.floating,
margin: EdgeInsets.symmetric(vertical: 20.0),
));
}
}
}
void checkAnswerAndUpdate(bool value) {
if (isAlreadySelected) {
return;
} else {
if (value == true) {
score++;
setState(() {
isPressed = true;
isAlreadySelected = false;
});
} else if (value == false) {
setState(() {
isPressed = true;
isAlreadySelected = false;
});
}
}
}
void startOver() {
setState(() {
Text('You have already attempted the LL Test');
});
}
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: _questions as Future<List<Question>>,
builder: (ctx, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasError) {
return Center(
child: Text('${snapshot.error}'),
);
} else if (snapshot.hasData) {
var extractedData = snapshot.data as List<Question>;
return Scaffold(
backgroundColor: background,
appBar: AppBar(
title: const Text('LL Test'),
backgroundColor: background,
shadowColor: Colors.transparent,
actions: [
Padding(
padding: const EdgeInsets.all(18.0),
child: Text(
'Score: $score',
style: TextStyle(fontSize: 18.0),
),
)
],
),
body: Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Column(
children: [
QuestionWidget(
question: extractedData[index].title,
indexAction: index,
totalQuestions: extractedData.length,
),
const Divider(
color: neutral,
),
const SizedBox(height: 25.0),
for (int i = 0;
i < extractedData[index].options.length;
i++)
GestureDetector(
onTap: () => checkAnswerAndUpdate(
extractedData[index].options.values.toList()[i]),
child: OptionCard(
option: extractedData[index].options.keys.toList()[i],
color: isPressed
? extractedData[index]
.options
.values
.toList()[i] ==
true
? correct
: incorrect
: neutral,
),
),
],
),
),
floatingActionButton: GestureDetector(
onTap: () => nextQuestion(extractedData.length),
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 10.0),
child: NextButton(),
),
),
floatingActionButtonLocation:
FloatingActionButtonLocation.centerFloat,
);
}
} else {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircularProgressIndicator(),
SizedBox(height: 20.0),
Text(
'Please Wait While Questions Are Loading..',
style: TextStyle(
backgroundColor: Color.fromARGB(255, 4, 82, 6),
color: neutral),
),
],
),
);
}
return const Center(
child: Text('NoData'),
);
},
);
}
}
Hello I have a problem when I want to use the List variable that stores the IDs of a database in Firebase. I would like to use it in the "Row" widget where I create a DropDownButton, it only allows me to do it if the instance is out of scope. How can i use this variable inside Row?
Main.dart
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
Firebase.initializeApp();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Material App',
// home: const CardScreen(),
initialRoute: AppRoutes.initialRoute,
routes: AppRoutes.routes,
onGenerateRoute: AppRoutes.onGenerateRoute);
}
}
Form1_screen.dart
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class FormularioScreen extends StatefulWidget {
const FormularioScreen({Key? key}) : super(key: key);
#override
State<FormularioScreen> createState() => _FormularioScreenState();
}
class _FormularioScreenState extends State<FormularioScreen> {
_FormularioScreenState();
// ignore: prefer_typing_uninitialized_variables
var selecCurrency;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text(
'PET-SOS PERRO',
style: TextStyle(color: Colors.black54),
),
iconTheme: const IconThemeData(
color: Colors.black, //change your color here
),
backgroundColor: Colors.white,
),
body: Column(
children: [
StreamBuilder(
stream: FirebaseFirestore.instance.collection('Razas').snapshots(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return const Text('Loading');
} else {
List<DropdownMenuItem> currencyItems = [];
for (int i = 0; i < snapshot.data.docs.length; i++) {
DocumentSnapshot snap = snapshot.data.docs[i];
currencyItems.add(
DropdownMenuItem(
child: Text(
snap.id,
),
value: snap.id,
),
);
}
}
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
DropdownButton<dynamic>(
items: currencyItems,
onChanged: (currencyValue) {
var snackBar = SnackBar(
content: Text('Se seleccionó $currencyValue'));
// ignore: deprecated_member_use
Scaffold.of(context).showSnackBar(snackBar);
setState(() {
selecCurrency = currencyValue;
});
},
value: selecCurrency,
hint: const Text('Seleccione una raza.')),
],
);
},
),
StreamBuilder(
stream: FirebaseFirestore.instance.collection('Peso').snapshots(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return const Text('Loading');
} else {
List<DropdownMenuItem> currencyItems = [];
for (int i = 0; i < snapshot.data.docs.length; i++) {
DocumentSnapshot snap = snapshot.data.docs[i];
currencyItems.add(
DropdownMenuItem(
child: Text(
snap.id,
),
value: snap.id,
),
);
}
}
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
DropdownButton<dynamic>(
items: currencyItems,
onChanged: (currencyValue) {
var snackBar = SnackBar(
content: Text('Se seleccionó $currencyValue'));
// ignore: deprecated_member_use
Scaffold.of(context).showSnackBar(snackBar);
setState(() {
selecCurrency = currencyValue;
});
},
value: selecCurrency,
hint: const Text('Seleccione un peso.')),
],
);
},
),
StreamBuilder(
stream: FirebaseFirestore.instance.collection('Edad').snapshots(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return const Text('Loading');
} else {
List<DropdownMenuItem> currencyItems = [];
for (int i = 0; i < snapshot.data.docs.length; i++) {
DocumentSnapshot snap = snapshot.data.docs[i];
currencyItems.add(
DropdownMenuItem(
child: Text(
snap.id,
),
value: snap.id,
),
);
}
}
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
DropdownButton<dynamic>(
items: currencyItems,
onChanged: (currencyValue) {
var snackBar = SnackBar(
content: Text('Se seleccionó $currencyValue'));
// ignore: deprecated_member_use
Scaffold.of(context).showSnackBar(snackBar);
setState(() {
selecCurrency = currencyValue;
});
},
value: selecCurrency,
hint: const Text('Seleccione una edad.')),
],
);
},
),
],
),
);
}
}
Basically the variable isn't define because it's outsite of the ambit.
move the list definition before the scaffold
class _FormularioScreenState extends State<FormularioScreen> {
_FormularioScreenState();
// ignore: prefer_typing_uninitialized_variables
var selecCurrency;
#override
Widget build(BuildContext context) {
List<DropdownMenuItem> currencyItems = []; // <= ADD
return Scaffold(
appBar: AppBar(
title: const Text(
'PET-SOS PERRO',
style: TextStyle(color: Colors.black54),
),
iconTheme: const IconThemeData(
color: Colors.black, //change your color here
),
backgroundColor: Colors.white,
),
body: Column(
children: [
StreamBuilder(
stream:
FirebaseFirestore.instance.collection('Razas').snapshots(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return const Text('Loading');
} else {
List<DropdownMenuItem> currencyItems = []; // <= REMOVE
for (int i = 0; i < snapshot.data.docs.length; i++) {
I want to pass the values like name and link in the below code's final variables dynamically i.e when onPressed is executed. Any help would be appreciated... I have separated the section using ----- below.
In the example below all files have their names and links hardcoded which is less efficient and I want to pass these values dynamically and only when a user clicks on the required button
import 'dart:isolate';
import 'dart:ui';
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'package:flutter_downloader/flutter_downloader.dart';
import 'package:permission_handler/permission_handler.dart';
const debug = true;
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await FlutterDownloader.initialize(debug: debug);
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
final platform = Theme.of(context).platform;
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(
title: 'Downloader',
platform: platform,
),
);
}
}
class MyHomePage extends StatefulWidget with WidgetsBindingObserver {
final TargetPlatform platform;
MyHomePage({Key key, this.title, this.platform}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
---------------------------------------------------------------------------------------
final _documents = [
{
'name': 'Learning Android Studio',
'link':
'http://barbra-coco.dyndns.org/student/learning_android_studio.pdf'
},
{
'name': 'Android Programming Cookbook',
'link':
'http://enos.itcollege.ee/~jpoial/allalaadimised/reading/Android-Programming-Cookbook.pdf'
},
{
'name': 'iOS Programming Guide',
'link':
'http://darwinlogic.com/uploads/education/iOS_Programming_Guide.pdf'
},
{
'name': 'Objective-C Programming (Pre-Course Workbook',
'link':
'https://www.bignerdranch.com/documents/objective-c-prereading-assignment.pdf'
},
];
final _images = [
{
'name': 'Arches National Park',
'link':
'https://upload.wikimedia.org/wikipedia/commons/6/60/The_Organ_at_Arches_National_Park_Utah_Corrected.jpg'
},
{
'name': 'Canyonlands National Park',
'link':
'https://upload.wikimedia.org/wikipedia/commons/7/78/Canyonlands_National_Park%E2%80%A6Needles_area_%286294480744%29.jpg'
},
{
'name': 'Death Valley National Park',
'link':
'https://upload.wikimedia.org/wikipedia/commons/b/b2/Sand_Dunes_in_Death_Valley_National_Park.jpg'
},
{
'name': 'Gates of the Arctic National Park and Preserve',
'link':
'https://upload.wikimedia.org/wikipedia/commons/e/e4/GatesofArctic.jpg'
}
];
final _videos = [
{
'name': 'Big Buck Bunny',
'link':
'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4'
},
{
'name': 'Elephant Dream',
'link':
'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4'
}
];
-------------------------------------------------------------------------------------------
List<_TaskInfo> _tasks;
List<_ItemHolder> _items;
bool _isLoading;
bool _permissionReady;
String _localPath;
ReceivePort _port = ReceivePort();
#override
void initState() {
super.initState();
_bindBackgroundIsolate();
FlutterDownloader.registerCallback(downloadCallback);
_isLoading = true;
_permissionReady = false;
_prepare();
}
#override
void dispose() {
_unbindBackgroundIsolate();
super.dispose();
}
void _bindBackgroundIsolate() {
bool isSuccess = IsolateNameServer.registerPortWithName(
_port.sendPort, 'downloader_send_port');
if (!isSuccess) {
_unbindBackgroundIsolate();
_bindBackgroundIsolate();
return;
}
_port.listen((dynamic data) {
if (debug) {
print('UI Isolate Callback: $data');
}
String id = data[0];
DownloadTaskStatus status = data[1];
int progress = data[2];
final task = _tasks?.firstWhere((task) => task.taskId == id);
if (task != null) {
setState(() {
task.status = status;
task.progress = progress;
});
}
});
}
void _unbindBackgroundIsolate() {
IsolateNameServer.removePortNameMapping('downloader_send_port');
}
static void downloadCallback(
String id, DownloadTaskStatus status, int progress) {
if (debug) {
print(
'Background Isolate Callback: task ($id) is in status ($status) and process ($progress)');
}
final SendPort send =
IsolateNameServer.lookupPortByName('downloader_send_port');
send.send([id, status, progress]);
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: Builder(
builder: (context) => _isLoading
? new Center(
child: new CircularProgressIndicator(),
)
: _permissionReady
? _buildDownloadList()
: _buildNoPermissionWarning()),
);
}
Widget _buildDownloadList() => Container(
child: ListView(
padding: const EdgeInsets.symmetric(vertical: 16.0),
children: _items
.map((item) => item.task == null
? _buildListSection(item.name)
: DownloadItem(
data: item,
onItemClick: (task) {
_openDownloadedFile(task).then((success) {
if (!success) {
Scaffold.of(context).showSnackBar(SnackBar(
content: Text('Cannot open this file')));
}
});
},
onAtionClick: (task) {
if (task.status == DownloadTaskStatus.undefined) {
_requestDownload(task);
} else if (task.status == DownloadTaskStatus.running) {
_pauseDownload(task);
} else if (task.status == DownloadTaskStatus.paused) {
_resumeDownload(task);
} else if (task.status == DownloadTaskStatus.complete) {
_delete(task);
} else if (task.status == DownloadTaskStatus.failed) {
_retryDownload(task);
}
},
))
.toList(),
),
);
Widget _buildListSection(String title) => Container(
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
child: Text(
title,
style: TextStyle(
fontWeight: FontWeight.bold, color: Colors.blue, fontSize: 18.0),
),
);
Widget _buildNoPermissionWarning() => Container(
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24.0),
child: Text(
'Please grant accessing storage permission to continue -_-',
textAlign: TextAlign.center,
style: TextStyle(color: Colors.blueGrey, fontSize: 18.0),
),
),
SizedBox(
height: 32.0,
),
FlatButton(
onPressed: () {
_checkPermission().then((hasGranted) {
setState(() {
_permissionReady = hasGranted;
});
});
},
child: Text(
'Retry',
style: TextStyle(
color: Colors.blue,
fontWeight: FontWeight.bold,
fontSize: 20.0),
))
],
),
),
);
void _requestDownload(_TaskInfo task) async {
task.taskId = await FlutterDownloader.enqueue(
url: task.link,
headers: {"auth": "test_for_sql_encoding"},
savedDir: _localPath,
showNotification: true,
openFileFromNotification: true);
}
void _cancelDownload(_TaskInfo task) async {
await FlutterDownloader.cancel(taskId: task.taskId);
}
void _pauseDownload(_TaskInfo task) async {
await FlutterDownloader.pause(taskId: task.taskId);
}
void _resumeDownload(_TaskInfo task) async {
String newTaskId = await FlutterDownloader.resume(taskId: task.taskId);
task.taskId = newTaskId;
}
void _retryDownload(_TaskInfo task) async {
String newTaskId = await FlutterDownloader.retry(taskId: task.taskId);
task.taskId = newTaskId;
}
Future<bool> _openDownloadedFile(_TaskInfo task) {
return FlutterDownloader.open(taskId: task.taskId);
}
void _delete(_TaskInfo task) async {
await FlutterDownloader.remove(
taskId: task.taskId, shouldDeleteContent: true);
await _prepare();
setState(() {});
}
Future<bool> _checkPermission() async {
if (widget.platform == TargetPlatform.android) {
final status = await Permission.storage.status;
if (status != PermissionStatus.granted) {
final result = await Permission.storage.request();
if (result == PermissionStatus.granted) {
return true;
}
} else {
return true;
}
} else {
return true;
}
return false;
}
Future<Null> _prepare() async {
final tasks = await FlutterDownloader.loadTasks();
int count = 0;
_tasks = [];
_items = [];
_tasks.addAll(_documents.map((document) =>
_TaskInfo(name: document['name'], link: document['link'])));
_items.add(_ItemHolder(name: 'Documents'));
for (int i = count; i < _tasks.length; i++) {
_items.add(_ItemHolder(name: _tasks[i].name, task: _tasks[i]));
count++;
}
_tasks.addAll(_images
.map((image) => _TaskInfo(name: image['name'], link: image['link'])));
_items.add(_ItemHolder(name: 'Images'));
for (int i = count; i < _tasks.length; i++) {
_items.add(_ItemHolder(name: _tasks[i].name, task: _tasks[i]));
count++;
}
_tasks.addAll(_videos
.map((video) => _TaskInfo(name: video['name'], link: video['link'])));
_items.add(_ItemHolder(name: 'Videos'));
for (int i = count; i < _tasks.length; i++) {
_items.add(_ItemHolder(name: _tasks[i].name, task: _tasks[i]));
count++;
}
tasks?.forEach((task) {
for (_TaskInfo info in _tasks) {
if (info.link == task.url) {
info.taskId = task.taskId;
info.status = task.status;
info.progress = task.progress;
}
}
});
_permissionReady = await _checkPermission();
_localPath = (await _findLocalPath()) + Platform.pathSeparator + 'Download';
final savedDir = Directory(_localPath);
bool hasExisted = await savedDir.exists();
if (!hasExisted) {
savedDir.create();
}
setState(() {
_isLoading = false;
});
}
Future<String> _findLocalPath() async {
final directory = widget.platform == TargetPlatform.android
? await getExternalStorageDirectory()
: await getApplicationDocumentsDirectory();
return directory.path;
}
}
class DownloadItem extends StatelessWidget {
final _ItemHolder data;
final Function(_TaskInfo) onItemClick;
final Function(_TaskInfo) onAtionClick;
DownloadItem({this.data, this.onItemClick, this.onAtionClick});
#override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.only(left: 16.0, right: 8.0),
child: InkWell(
onTap: data.task.status == DownloadTaskStatus.complete
? () {
onItemClick(data.task);
}
: null,
child: Stack(
children: <Widget>[
Container(
width: double.infinity,
height: 64.0,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: Text(
data.name,
maxLines: 1,
softWrap: true,
overflow: TextOverflow.ellipsis,
),
),
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: _buildActionForTask(data.task),
),
],
),
),
data.task.status == DownloadTaskStatus.running ||
data.task.status == DownloadTaskStatus.paused
? Positioned(
left: 0.0,
right: 0.0,
bottom: 0.0,
child: LinearProgressIndicator(
value: data.task.progress / 100,
),
)
: Container()
].where((child) => child != null).toList(),
),
),
);
}
Widget _buildActionForTask(_TaskInfo task) {
if (task.status == DownloadTaskStatus.undefined) {
return RawMaterialButton(
onPressed: () {
onAtionClick(task);
},
child: Icon(Icons.file_download),
shape: CircleBorder(),
constraints: BoxConstraints(minHeight: 32.0, minWidth: 32.0),
);
} else if (task.status == DownloadTaskStatus.running) {
return RawMaterialButton(
onPressed: () {
onAtionClick(task);
},
child: Icon(
Icons.pause,
color: Colors.red,
),
shape: CircleBorder(),
constraints: BoxConstraints(minHeight: 32.0, minWidth: 32.0),
);
} else if (task.status == DownloadTaskStatus.paused) {
return RawMaterialButton(
onPressed: () {
onAtionClick(task);
},
child: Icon(
Icons.play_arrow,
color: Colors.green,
),
shape: CircleBorder(),
constraints: BoxConstraints(minHeight: 32.0, minWidth: 32.0),
);
} else if (task.status == DownloadTaskStatus.complete) {
return Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(
'Ready',
style: TextStyle(color: Colors.green),
),
RawMaterialButton(
onPressed: () {
onAtionClick(task);
},
child: Icon(
Icons.delete_forever,
color: Colors.red,
),
shape: CircleBorder(),
constraints: BoxConstraints(minHeight: 32.0, minWidth: 32.0),
)
],
);
} else if (task.status == DownloadTaskStatus.canceled) {
return Text('Canceled', style: TextStyle(color: Colors.red));
} else if (task.status == DownloadTaskStatus.failed) {
return Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text('Failed', style: TextStyle(color: Colors.red)),
RawMaterialButton(
onPressed: () {
onAtionClick(task);
},
child: Icon(
Icons.refresh,
color: Colors.green,
),
shape: CircleBorder(),
constraints: BoxConstraints(minHeight: 32.0, minWidth: 32.0),
)
],
);
} else {
return null;
}
}
}
class _TaskInfo {
final String name;
final String link;
String taskId;
int progress = 0;
DownloadTaskStatus status = DownloadTaskStatus.undefined;
_TaskInfo({this.name, this.link});
}
class _ItemHolder {
final String name;
final _TaskInfo task;
_ItemHolder({this.name, this.task});
}
From this link I took the player code This is my piece of code:
class ChewieDemo extends StatefulWidget {
Datum imageData;
SubContentsDatum subContentsData;
List<Datum>imageUrls;
List<SubCategoryData> categoryData;
SubCategoryData catdata;
SharedPreferences preferences;
ChewieDemo({this.title = 'Player',Key key, this.imageData,this.categoryData}): super(key:key);
ChewieDemo.fromChewieDemo({this.title = 'Player',Key key,this.subContentsData}):super(key:key);
// ChewieDemo.fromChewieDemo({ChewieDemo demo,this.title = 'Player',Key key,#required demo.categoryData}):super(key:key);
String title;
#override
State<StatefulWidget> createState() {
return _ChewieDemoState();
}
}
class _ChewieDemoState extends State<ChewieDemo> {
TargetPlatform _platform;
VideoPlayerController _videoPlayerController1;
VideoPlayerController _videoPlayerController2;
ChewieController _chewieController;
List<Tab>categoryNames = [];
List<String>subCategories = [];
Tab tab;
List<SubContentsDatum>images = [];
String dataUrl;
SharedPreferences preferences;
void initPreferences() async {
preferences = await SharedPreferences.getInstance();
/* dataUrl = preferences.getString("dataurl");
print('dataurl:$dataUrl');
*/
}
#override
void initState() {
super.initState();
//initPreferences();
if (widget.categoryData != null) {
print('data: $categoryNames');
categoryNames.clear();
for (int i = 0; i < widget.categoryData.length; i++) {
tab = Tab(text: widget.categoryData[i].name);
categoryNames.add(tab);
}
// print('data: $categoryNames');
} else {
}
// 'https://www.sample-videos.com/video123/mp4/480/big_buck_bunny_480p_20mb.mp4'
initPlayer();
}
#override
void dispose() {
_videoPlayerController1.dispose();
// _videoPlayerController2.dispose();
_chewieController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: widget.title,
theme: ThemeData.light().copyWith(
platform: _platform ?? Theme
.of(context)
.platform,
),
home: DefaultTabController(
length: categoryNames.length,
child: Scaffold(
appBar: AppBar(
title: Text(widget.title),
leading: IconButton(icon:
Icon(Icons.arrow_back),
onPressed: (){
Navigator.of(context).pushNamed('/screen1');
}),
),
body: SafeArea(
child: Column(
children: <Widget>[
Chewie(
controller: _chewieController,
),
TabBar(
labelColor: Colors.black,
tabs: categoryNames,
),
Expanded(
child: TabBarView(
children: List<Widget>.generate(
categoryNames.length, (int index) {
print('catid:${widget.categoryData[index].id}');
int categoryId = widget.categoryData[index].id;
return ImageList(categoryId: categoryId);
}),
),
)
],
)
),
),
),
);
}
void initPlayer() async {
// initPreferences();
preferences = await SharedPreferences.getInstance();
dataUrl = preferences.getString("dataurl");
// dataUrl = 'http://159.65.156.204/p/102/sp/10200/playManifest/entryId/0_314t2peg/format/url/protocol/http';
print('dataurl:$dataUrl');
//widget.imageData.dataUrl = "http://159.65.156.204/p/102/sp/10200/playManifest/entryId/0_314t2peg/format/url/protocol/http";
//print('url player :${widget.imageData.dataUrl}');
_videoPlayerController1 = VideoPlayerController.network('$dataUrl');
_chewieController = ChewieController(
videoPlayerController: _videoPlayerController1,
aspectRatio: 3 / 2,
autoPlay: true,
looping: true,
);
}
}
Hi ,
I am trying to fetch a string from preference and passing into the player. But I am getting error like "Failed assertion"
error: Failed assertion: 'controller!=null' You must provide a chewie
controller.
I am not getting whether it is problem with async I have given for initPlayer() or something else. Please check my code and let me know.