Dart : A non-null String must be provided to a Text widget - android

So I am going to create a quiz app but while I run it, I get the following error
'pakage:flutter/src/wigets/text.dart': Field assertion : line 298 pos
10 :'data !=null': A non-null String must be provided to a Text widget
it is a flutter based code, what are the possible thing i missed ? Can you help me please ! i shall be obliged for this :)
Here Is image of Error
import 'dart:async';
import 'dart:convert';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:crazyquiz/resultpage.dart';
class getjson extends StatelessWidget {
String langname;
getjson(this.langname);
String assettoload;
setasset() {
if (langname == "Funny") {
assettoload = "assets/funny.json";
} else if (langname == "General Knowledge") {
assettoload = "assets/gk.json";
} else if (langname == "Javascript") {
assettoload = "assets/js.json";
} else if (langname == "C++") {
assettoload = "assets/cpp.json";
} else {
assettoload = "assets/linux.json";
}
}
#override
Widget build(BuildContext context) {
setasset();
return FutureBuilder(
future:
DefaultAssetBundle.of(context).loadString(assettoload, cache: true),
builder: (context, snapshot) {
List mydata = json.decode(snapshot.data.toString());
if (mydata == null) {
return Scaffold(
body: Center(
child: Text(
"Loading",
),
),
);
} else {
return quizpage(mydata: mydata);
}
},
);
}
}
class quizpage extends StatefulWidget {
var mydata;
quizpage({Key key, this.mydata = ""}) : super(key: key);
#override
_quizpageState createState() => _quizpageState(mydata);
}
class _quizpageState extends State<quizpage> {
var mydata;
_quizpageState(this.mydata);
Color colortoshow = Colors.indigoAccent;
Color right = Colors.green;
Color wrong = Colors.red;
int marks = 0;
int i = 1;
int j = 1;
int timer = 30;
String showtimer = "30";
var random_array;
Map<String, Color> btncolor = {
"a": Colors.purple,
"b": Colors.lightBlueAccent,
"c": Colors.blueGrey,
"d": Colors.blueAccent,
};
bool canceltimer = false;
genrandomarray() {
var distinctIds = [];
var rand = new Random();
for (int i = 0;;) {
distinctIds.add(rand.nextInt(10));
random_array = distinctIds.toSet().toList();
if (random_array.length < 10) {
continue;
} else {
break;
}
}
print(random_array);
}
#override
void initState() {
starttimer();
genrandomarray();
super.initState();
}
#override
void setState(fn) {
if (mounted) {
super.setState(fn);
}
}
void starttimer() async {
const onesec = Duration(seconds: 1);
Timer.periodic(onesec, (Timer t) {
setState(() {
if (timer < 1) {
t.cancel();
nextquestion();
} else if (canceltimer == true) {
t.cancel();
} else {
timer = timer - 1;
}
showtimer = timer.toString();
});
});
}
void nextquestion() {
timer = 30;
setState(() {
if (j < 10) {
i = random_array[j];
j++;
} else {
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (context) => resultpage(marks: marks),
));
}
btncolor["a"] = Colors.purple;
btncolor["b"] = Colors.lightBlueAccent;
btncolor["c"] = Colors.blueGrey;
btncolor["d"] = Colors.blueAccent;
});
starttimer();
}
void checkanswer(String k) {
if (mydata[2][i.toString()] == mydata[1][i.toString()][k]) {
[i.toString()][k]);
marks = marks + 5;
colortoshow = right;
} else {
}
setState(() {
btncolor[k] = colortoshow;
canceltimer = true;
});
Timer(Duration(seconds: 1), nextquestion);
}
Widget choicebutton(String k) {
return Padding(
padding: EdgeInsets.symmetric(
vertical: 10.0,
horizontal: 20.0,
),
child: MaterialButton(
onPressed: () => checkanswer(k),
child: Text(
mydata[1][i.toString()][k],
style: TextStyle(
color: Colors.white,
fontFamily: "Alike",
fontSize: 16.0,
),
maxLines: 1,
),
color: btncolor[k],
splashColor: Colors.indigo[700],
highlightColor: Colors.indigo[700],
minWidth: 200.0,
height: 45.0,
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)),
),
);
}
#override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations(
[DeviceOrientation.portraitDown, DeviceOrientation.portraitUp]);
return WillPopScope(
onWillPop: () {
return showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text(
"Quizstar",
),
content: Text("You Can't Go Back At This Stage."),
actions: <Widget>[
FlatButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text(
'Ok',
),
)
],
));
},
child: Scaffold(
body: Column(
children: <Widget>[
Expanded(
flex: 3,
child: Container(
padding: EdgeInsets.all(15.0),
alignment: Alignment.bottomLeft,
child: Text(
mydata[0][i.toString()],
style: TextStyle(
fontSize: 16.0,
fontFamily: "Quando",
),
),
),
),
Expanded(
flex: 6,
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
choicebutton('a'),
choicebutton('b'),
choicebutton('c'),
choicebutton('d'),
],
),
),
),
Expanded(
flex: 1,
child: Container(
alignment: Alignment.topCenter,
child: Center(
child: Text(
showtimer.toString(),
style: TextStyle(
fontSize: 35.0,
fontWeight: FontWeight.w700,
fontFamily: 'Times New Roman',
),
),
),
),
),
],
),
),
);
}
}`

I think Yalin is perfectly right, but I would add:
Dart has some very useful operators to prevent that kind of errors, which can be catastrofic on real world usage. You can check them here. In particular you could use
mydata[0][i.toString()] ?? "Default text"
to prevent this kind of problem when an object is null

Not a flutter guy. But I'll try to help you.
If you look into flutter source and search your error message you'll get a clue what to do.
So at text.dart we can find that dart check that you fill data field with a String when you call a constructor.
So my bet is that you misplace toString here mydata[0][i.toString()]

Text widget needs a string to be initialized. As vsenik mentioned, you are probably giving a null instead of string to a text widget. The problem is in one of the below lines.
mydata[1][i.toString()][k]
mydata[0][i.toString()]
You could use debug or insert a print statement before these lines.

Related

Can't click on wrong options in my quiz app

I'm creating a quiz app using Flutter & Firebase. When the quiz starts, I can click the correct answer and it will show the correct and incorrect answers, but I can't click on incorrect options. When I try to press the incorrect options, nothing happens.
Is there anything wrong in this code that is making it happen?
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 == questionLength - 1 || 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;
});
}
}
}
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..'),
],
),
);
}
return const Center(
child: Text('NoData'),
);
},
);
}
}
You never set isPressed to true when you select the wrong (false) answer.
Your checkAnswerAndUpdate should probably always call the setState method, even if the answer was wrong.

How to generate 20 random questions from Firebase in my Flutter Quiz App?

I'm creating a quiz app using Flutter & Firebase. I've added 150 questions in Firebase Realtime Database and have fetched all the questions in the Quiz App. But the app shows all the added questions in the same order. I want to generate 20 random questions every time from the questions I've added in Firebase Realtime Database.
How can I make it happen?
Code:
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 == questionLength - 1 || 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..'),
],
),
);
}
return const Center(
child: Text('NoData'),
);
},
);
}
}
Try use Shuffle for sort random item in list
List<String> newList = [];
List<String> countries = ["USA", "United Kingdom","China", "Russia", "Brazil"];
countries.shuffle();
for(var i == 0; i <= 20; i++){
newList.add(countries[i])
}
print(newList);
// [United Kingdom, Brazil, Russia, China, USA]
//the output will be in different order every time this code is executed.

Flutter : Disposed CameraController, buildPreview() was called on a disposed CameraController

How to initialized and dispose camera controller properly. I am using camera: ^0.9.4+5
Along with many
other errors
I am getting this error on switch camera button click:
======== Exception caught by widgets library =======================================================
The following CameraException was thrown building ValueListenableBuilder<CameraValue>(dirty, state: _ValueListenableBuilderState<CameraValue>#47f17):
CameraException(Disposed CameraController, buildPreview() was called on a disposed CameraController.)
Here is the complete code:
class VideoRecorderScreen extends StatefulWidget {
#override
_VideoRecorderScreenState createState() {
return _VideoRecorderScreenState();
}
//final ApplicantData applicantData;
final String videorec;
VideoRecorderScreen(this.applicationId, this.name, this.description,
this.descriptionHindi, this.videorec,
{this.isOpenSubsDashboard = false});
}
class _VideoRecorderScreenState extends State<VideoRecorderScreen> {
CameraController controller;
XFile videoPath;
List<CameraDescription> cameras;
int selectedCameraIdx = 1;
int videoElapseTime = 25;
int videoMinElapseTime = 20;
bool visibilityStop = false;
bool visibilityButtons = false;
String timer = "00:00";
CountdownTimer cd;
bool startRecording = false;
void _reset() {
videoPath = null;
_changed(false);
_changedTimer("00:00");
_changedButtonVisibility(false);
}
void _changed(bool visibility) {
if (mounted) setState(() {
visibilityStop = visibility;
});
}
void _changedTimer(String time) {
if (mounted) setState(() {
timer = time;
});
}
void _changedButtonVisibility(bool visibility) {
if (mounted) setState(() {
visibilityButtons = visibility;
});
}
void _navigateAndDisplaySelection(BuildContext context) async {
final result = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => VideoPlayerScreen(
videoPath: videoPath.path,
applicationId: widget.applicationId,
name: widget.name,
dateTime: selectedDate,
isOpenSubsDashboard: widget.isOpenSubsDashboard)),
);
if (result) {
_reset();
}
}
#override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) =>
showSnackBar('User Validated Successfully! Welcome ' + widget.name));
availableCameras().then((availableCameras) {
cameras = availableCameras;
if (cameras.length > 0) {
for (int i = 0; i < cameras.length; i++) {
if (cameras[i].lensDirection == CameraLensDirection.front) {
if (mounted) setState(() {
selectedCameraIdx = i;
});
}
}
_onCameraSwitched(cameras[selectedCameraIdx]).then((void v) {});
}
}).catchError((err) {
print('Error: $err.code\nError Message: $err.message');
});
}
#override
Widget build(BuildContext context) {
var size = MediaQuery.of(context).size.width * (2 / 3);
return WillPopScope(
onWillPop: _onBackPressed,
child: Scaffold(
key: _scaffoldKey,
appBar: AppBarWidget(
title: 'Record Your Video',
actions: [
IconButton(
icon: Icon(
Icons.call,
),
onPressed: () {
ConstantMethods.callToSupport();
}),
AppBarLogo(),
],
),
body: Builder(builder: (BuildContext buildContext) {
scaffold = Scaffold.of(buildContext);
return Container(
child: ListView(
children: <Widget>[
Center(
child: Container(
width: size / 1.5,
height: size / 1.5,
Container(
padding: EdgeInsets.all(5.0),
color: Colors.grey[850],
child: Text(
selectedDate != null ? selectedDate : "",
textAlign: TextAlign.start,
),
],
),
))
: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
VerticalSpacing(20.0),
Padding(
padding:
const EdgeInsets.only(left: 8.0, right: 8.0),
child: Text(
'Click on video icon to start the recording',
textAlign: TextAlign.justify,
FlatButton(
child: Text(' Proceed for Recording '),
onPressed: () {
if (mounted) setState(() {
startRecording = true;
});
},
),
VerticalSpacing(10.0),
FlatButton(
textColor: ThemeColors.colorPrimary,
VerticalSpacing(20.0),
],
),
startRecording
? Padding(
padding: const EdgeInsets.all(5.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
_cameraTogglesRowWidget(),
_captureControlRowWidget(),
Expanded(
child: Text("$timer",
textAlign: TextAlign.end,
style: TextStyle(
fontSize: Consts.fontSizeMedium)),
),
],
),
)
: new Container(),
!visibilityButtons
? Column(
children: [
Row(mainAxisAlignment: MainAxisAlignment.spaceBetween,
//alignment: Alignment.bottomRight,
children: [
IconButton(
icon: const Icon(Icons.info_outline,
size: 25.0),
color: ThemeColors.colorPrimary,
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) =>
MessageDialog(
title: "ImportantTips",
message: Languages.of(context)
.videoPreInstruction,
),
);
},
),
ToggleButtons(
borderColor: ThemeColors.colorAccent,
fillColor: Colors.lightBlue[100],
borderWidth: 1,
selectedBorderColor: ThemeColors.colorAccent,
selectedColor: Colors.blue[900],
color: ThemeColors.colorPrimary,
borderRadius: BorderRadius.circular(10),
children: <Widget>[
Padding(
padding: const EdgeInsets.only(
left: 12.0, right: 8.0),
child: Text(
'In English',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: Consts.fontSizeSmall),
),
),
Padding(
padding: const EdgeInsets.only(
left: 8.0, right: 8.0),
child: Text(
'हिंदी में ',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: Consts.fontSizeSmall),
),
),
],
onPressed: (int index) {
if(this.mounted) setState(() {
for (int i = 0;
i < isSelectedLanguage.length;
i++) {
if (i == index) {
isSelectedLanguage[i] = true;
} else {
isSelectedLanguage[i] = false;
}
}
if (isSelectedLanguage[0]) {
changeLanguage(context, 'en');
} else if (isSelectedLanguage[1]) {
changeLanguage(context, 'hi');
}
});
},
isSelected: isSelectedLanguage,
)
]),
VerticalSpacing(10.0),
Padding(
padding:
const EdgeInsets.only(left: 8.0, right: 8.0),
child
: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
OutlineButton(
padding: EdgeInsets.all(5.0),
splashColor: Colors.blue[300],
borderSide:
BorderSide(color: ThemeColors.colorPrimary),
child: Text(' Retake Video ',
style: TextStyle(
color: Colors.blue,
fontSize: Consts.fontSizeMedium)),
onPressed: () {
_reset();
},
),
HorizontalSpacing(10.0),
FlatButton(
padding: EdgeInsets.all(5.0),
color: ThemeColors.colorPrimary,
// splashColor: Colors.greenAccent,
textColor: ThemeColors.white,
child: Text(' Play Recording ',
style:
TextStyle(fontSize: Consts.fontSizeMedium)),
onPressed: () {
if(videoPath!=null) {
_navigateAndDisplaySelection(context);
} else{
//ConstantMethods.showToast("Technical exception with camera.");
ConstantMethods.showToast("There is some issue in recording video right now, please try again later.");
_onBackPressed();
}
},
),
],
),
VerticalSpacing(10.0),
],
));
})),
);
}
IconData _getCameraLensIcon(CameraLensDirection direction) {
switch (direction) {
case CameraLensDirection.back:
return Icons.camera_rear;
case CameraLensDirection.front:
return Icons.camera_front;
case CameraLensDirection.external:
return Icons.camera;
default:
return Icons.device_unknown;
}
}
// Display 'Loading' text when the camera is still loading.
Widget _cameraPreviewWidget(var size) {
if (controller == null || !controller.value.isInitialized) {
return const Text(
'Loading',
style: TextStyle(
color: ThemeColors.white,
fontSize: 20.0,
fontWeight: FontWeight.w900,
),
);
}
return Container(
width: size,
height: size,
child: ClipRect(
child: OverflowBox(
alignment: Alignment.center,
child: FittedBox(
fit: BoxFit.fitWidth,
child: Container(
width: size,
height: size / controller.value.aspectRatio,
// height: size / controller.value.aspectRatio,
child: CameraPreview(controller),
// this is my CameraPreview
),
),
),
),
);
}
/// Display a row of toggle to select the camera (or a message if no camera is available).
Widget _cameraTogglesRowWidget() {
if (cameras == null) {
return Row();
}
CameraDescription selectedCamera =
cameras[selectedCameraIdx];
CameraLensDirection lensDirection =
selectedCamera.lensDirection;
//CameraLensDirection lensDirection = CameraLensDirection.front;
return Expanded(
child: Align(
alignment: Alignment.centerLeft,
child: FlatButton.icon(
onPressed: controller != null && controller.value.isRecordingVideo
? null
: _onSwitchCamera,
icon: Icon(_getCameraLensIcon(lensDirection)),
label: Text(
"${lensDirection.toString().substring(lensDirection.toString().indexOf('.') + 1)}")),
),
);
}
/// Display the control bar with buttons to record videos.
Widget _captureControlRowWidget() {
return Expanded(
child: Align(
alignment: Alignment.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
IconButton(
icon: const Icon(Icons.videocam, size: 40.0),
color: ThemeColors.colorPrimary,
onPressed: controller != null &&
controller.value.isInitialized &&
!controller.value.isRecordingVideo &&
videoPath == null
? _onRecordButtonPressed
: null,
),
IconButton(
icon: const Icon(Icons.stop, size: 40.0),
color: ThemeColors.red,
onPressed: controller != null &&
controller.value.isInitialized &&
controller.value.isRecordingVideo &&
visibilityStop
? _onStopButtonPressed
: null,
),
// : new Container(),
],
),
),
);
}
String timestamp() => DateTime.now().millisecondsSinceEpoch.toString();
Future<void> _onCameraSwitched(CameraDescription description) async {
if (description == null) {
return;
}
if(!(controller != null && controller.value.isRecordingVideo)){
onNewCameraSelected(description);
}
}
void onNewCameraSelected(CameraDescription cameraDescription) async {
if (controller != null) {
await controller.dispose();
}
controller = CameraController(
cameraDescription, ResolutionPreset.low
);
//controller = cameraController;
// If the controller is updated then update the UI.
controller.addListener(() {
if (mounted) setState(() {});
if (controller.value.hasError) {
Fluttertoast.showToast(
msg: 'Camera error ${controller.value.errorDescription}',
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: ThemeColors.red,
textColor: ThemeColors.white);
}
});
try {
await controller.initialize();
} on CameraException catch (e) {
_showCameraException(e);
}
if (mounted) {
setState(() {});
}
}
void _onSwitchCamera() {
selectedCameraIdx =
selectedCameraIdx < cameras.length - 1 ? selectedCameraIdx + 1 : 0;
CameraDescription selectedCamera = cameras[selectedCameraIdx];
_onCameraSwitched(selectedCamera);
if (mounted) setState(() {
selectedCameraIdx = selectedCameraIdx;
});
}
void _onRecordButtonPressed() {
_startVideoRecording().then((_) {
/*if (mounted) setState(() {});*/
//if (filePath != null) {
final df = new DateFormat('dd-MM-yyyy hh:mm a');
String date = df.format(new DateTime.now());
if (mounted) setState(() {
// selectedDate = date1.replaceAll("/", "-");
selectedDate = date;
});
Fluttertoast.showToast(
msg: 'Recording video started',
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: ThemeColors.grey,
textColor: ThemeColors.white);
// }
});
}
void _onStopButtonPressed() {
if (cd.isRunning) {
cd.cancel();
}
_stopVideoRecording().then((file) {
if (mounted) setState(() {});
if (file != null) {
showInSnackBar('Video recorded to ${file.path}');
videoPath = file;
}
});
}
Future<void> _startVideoRecording() async {
//final CameraController? cameraController = controller;
if (controller == null || !controller.value.isInitialized) {
//showInSnackBar('Error: select a camera first.');
Fluttertoast.showToast(
msg: 'Please wait',
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: ThemeColors.grey,
textColor: ThemeColors.white);
return;
}
if (controller.value.isRecordingVideo) {
// A recording is already started, do nothing.
return;
}
try {
cd = CountdownTimer(
new Duration(seconds: videoElapseTime), new Duration(seconds: 1));
// var sub = cd.listen(null);
var sub = cd.listen(null);
sub.onData((duration) {
// setState(() { _current = _start - duration.elapsed.inSeconds; });
if (duration.elapsed.inSeconds == videoMinElapseTime) {
// ((videoElapseTime - 5) < 20 ? 20 : (videoElapseTime - 5))) {
_changed(true);
}
timer = duration.elapsed.inMinutes.toString().padLeft(2, '0') +
":" +
duration.elapsed.inSeconds.toString().padLeft(2, '0');
_changedTimer(timer + "/00:" + videoElapseTime.toString());
print(timer);
});
sub.onDone(() {
print("Done");
_onStopButtonPressed();
sub.cancel();
});
await controller.startVideoRecording();
} on CameraException catch (e) {
_showCameraException(e);
return;
}
}
Future<XFile> _stopVideoRecording() async {
if (controller == null || !controller.value.isRecordingVideo) {
return null;
}
try {
_changedButtonVisibility(true);
XFile video = await controller.stopVideoRecording();
await GallerySaver.saveVideo(video.path); //for testing
return video;
} on CameraException catch (e) {
_showCameraException(e);
return null;
}
}
void _showCameraException(CameraException e) {
String errorText = 'Error: ${e.code}\nError Message: ${e.description}';
print(errorText);
}
Future<bool> _onBackPressed() {
if (widget.isOpenSubsDashboard && (role == null || role.isEmpty)) {
//subscriber
return Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => SubscriberDashboard()),
(route) => false,
) ??
false;
} else {
//Navigator.of(context).pop();
return Future.value(Navigator.of(context).canPop());
}
}
One way of resolving this issue is by using a WidgetsBindingObserver - this helps manages the app's lifecycle. Inherit the WidgetsBidingObserver in your _VideoRecorderScreenState class to dispose the camera properly. A similar approach is demonstrated on this GitHub issue thread.

How to access one button at a time?

I resolved my current issue regarding locking and unlocking buttons. I am basing my levels on the marks the user got. If they got a score of 25 and above, they will proceed to the next level.
Now the problem here is since my quiz is sharing one code with a different JSON file, when the user perfects the score on the first stage, the whole level will unlock which is a no-no. The idea is even they scored perfect, the next stage will be unlocked not the whole level. I tried thinking of ways on how to do it but nothing comes to my mind.
Here is my Quiz Page:
import 'dart:async';
import 'dart:convert';
import 'dart:developer';
import 'package:baybay_app/Quiz/NextLevel class.dart';
import 'package:baybay_app/Quiz/QuizHome.dart';
import 'package:baybay_app/Quiz/ResultPage.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class Quizjson extends StatelessWidget {
String roundName;
bool isComplete = false;
Quizjson(this.roundName, mark);
String assettoload;
int question;
// a function
// sets the asset to a particular JSON file
// and opens the JSON
setasset() {
if (roundName == 'Easy Round') {
assettoload ='assets/Sample.json';
} else if (roundName == 'Average Round') {
assettoload = 'assets/Medium.json';
} else if (roundName == 'Hard Round') {
assettoload = 'assets/Hard.json';
}else {
assettoload = 'assets/Intermediate.json';
}
}
#override
Widget build(BuildContext context) {
setasset();
return FutureBuilder(
future: DefaultAssetBundle.of(context).loadString(assettoload, cache: false),
builder: (context, snapshot){
List mydata = json.decode(snapshot.data.toString());
if(mydata == null){
return Scaffold(
body: Center(
child: Text(
"Loading",
),
),
);
}else{
return quizpage(mydata: mydata);
}
}
);
}
}
class quizpage extends StatefulWidget {
String langname;
var mydata;
quizpage({Key key, #required this.mydata}): super(key: key);
#override
_quizpageState createState() => _quizpageState(mydata);
}
class _quizpageState extends State<quizpage> {
var mydata;
_quizpageState(this.mydata);
#override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitDown, DeviceOrientation.portraitUp]);
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
flex: 3,
child: Container(
padding: EdgeInsets.all(20.0),
alignment: Alignment.bottomLeft,
child: Text(mydata[0][question.toString()])
),
),
Expanded(
flex: 6,
child: Container(
child: Column(
children: [
Row(
children:[
ChoiceButton("a"),
ChoiceButton("b")
]
),
Row(
children: [
ChoiceButton("c"),
ChoiceButton("d"),
]
)
]
),
),
),
Expanded(
flex: 1,
child: Container(
alignment: Alignment.topCenter,
child: Center(
child: Text(
showtimer,
style: TextStyle(
fontSize: 20.0
),
),
),
),
),
],
)
);
}
Widget ChoiceButton(String k) {
return Padding(
padding: EdgeInsets.symmetric(
vertical: 10.0,
horizontal: 10.0),
child: MaterialButton(
onPressed: ()=>CheckAnswer(k),
child: Text(
mydata[1][question.toString()][k],
style: TextStyle(
color: Colors.white
)),
color: btncolor[k],
),
);
}
Color colorsToShow = Colors.brown[700];
Color right = Colors.greenAccent[700];
Color wrong = Colors.redAccent[700];
int mark = 0;
int question = 1;
int timer = 30;
String showtimer = "30";
bool canceltimer = false;
bool isComplete = false;
Map<String,Color> btncolor = {
"a" : Colors.brown[700],
"b" : Colors.brown[700],
"c" : Colors.brown[700],
"d" : Colors.brown[700],
};
#override
void initState(){
starttimer();
super.initState();
}
#override
void setState(fn){
if(mounted){
super.setState(fn);
}
}
void starttimer() async {
const onesec = Duration(seconds: 1);
Timer.periodic(onesec, (Timer t){
setState(() {
if(timer < 1){
t.cancel();
NextQuestion();
}
else if(canceltimer==true){
t.cancel();
}
else{
timer = timer - 1;
}
showtimer = timer.toString();
});
});
}
void NextQuestion(){
canceltimer = false;
timer = 30;
setState(() {
if(question< 10){
question++;
}
else{
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (context) => ResultPage(mark: mark),
));}
btncolor["a"] = Colors.brown[700];
btncolor["b"] = Colors.brown[700];
btncolor["c"] = Colors.brown[700];
btncolor["d"] = Colors.brown[700];
isComplete = true;
});
starttimer();
}
void CheckAnswer(String k) {
if(mydata[2][question.toString()] == mydata[1][question.toString()][k]){
mark = mark+5;
colorsToShow = right;
}
else{
colorsToShow = wrong;
}
setState(() {
btncolor[k] = colorsToShow;
});
Timer(Duration(seconds: 2), NextQuestion);
}
}
Here is my Quiz Home:
import 'package:baybay_app/Quiz/QuizTracingSound.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:baybay_app/Quiz/QuizTracingSound.dart';
class QuizHome extends StatefulWidget {
int mark = 0;
QuizHome({ #required this.mark });
#override
_QuizHomeState createState() => _QuizHomeState(mark);
}
class _QuizHomeState extends State<QuizHome> {
createAlertDialouge(BuildContext context){
return showDialog(context: context, builder: (context){
return AlertDialog(
title: Text('Not Complete'),
content: Text('Please score 25 above mark'),
actions: [
Center(
child: RaisedButton(
onPressed: (){Navigator.of(context).pop();},
color: Colors.grey[100],
),
),
],
shape: RoundedRectangleBorder(side: BorderSide(width: 16.0, color: Colors.red.shade100)),
backgroundColor: Colors.lightBlue.shade100,
);
});
}
createAlertDialougeOne(BuildContext context){
return showDialog(context: context, builder: (context){
return AlertDialog(
title: Text('Not Complete'),
content: Text('Please score 35 and above mark'),
actions: [
Center(
child: RaisedButton(
onPressed: (){Navigator.of(context).pop();},
color: Colors.grey[100],
),
),
],
shape: RoundedRectangleBorder(side: BorderSide(width: 16.0, color: Colors.red.shade100)),
backgroundColor: Colors.lightBlue.shade100,
);
});
}
createAlertDialougeTwo(BuildContext context){
return showDialog(context: context, builder: (context){
return AlertDialog(
title: Text('Not Complete'),
content: Text('Please score 35 and above mark'),
actions: [
Center(
child: RaisedButton(
onPressed: (){Navigator.of(context).pop();},
color: Colors.grey[100],
),
),
],
shape: RoundedRectangleBorder(side: BorderSide(width: 16.0, color: Colors.red.shade100)),
backgroundColor: Colors.lightBlue.shade100,
);
});
}
int mark = 0 ;
_QuizHomeState(this.mark);
String langname;
bool isComplete = false;
#override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitDown, DeviceOrientation.portraitUp]);
List <String> images = [
'assets/Ba.gif',
'assets/GA.PNG',
'assets/HA.PNG',
'assets/SA.PNG'
];
return Scaffold(
appBar: AppBar(
title: Text('Quiz Home '),
),
body:ListView(
children: <Widget>[
FlatButton(
child: CustomCard('Easy Round', images[0], des[1], isComplete, Colors.green, mark),
onPressed: () {
{ Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context)=> Quizjson("Easy Round", mark = 5),
));}
}
),
SizedBox(
height: 20.0,
),
FlatButton(
child: CustomCard('Average Round', images[1], des[1], isComplete, lockOrNot, mark),
onPressed: _onPressedOne,
),
SizedBox(
height: 20.0,
),
FlatButton(
onPressed: _onPressedTwo,
child: CustomCard('Hard Round', images[2],des[2], isComplete, btncolor, mark)
),
SizedBox(
height: 20.0,
),
FlatButton(
onPressed: _onPressedThree,
child: CustomCard('Intermediate Round', images[3],des[3], isComplete, btncolor, mark )
),
],
)
);
}
List <String> des = [
"The easy round lets you test your knowledge in determining letters. Are you up for the challenge? Click here!!!",
"Do you want to step up your baybayin game? Let's see if you can distinguish words! Click here!!!",
"Do you know how to construct sentences with the use of Baybayin? Click here!!!",
"Masters of baybayin can only enter this quiz! Are you one of them? Click Here!!!",
];
Color btncolor;
Widget CustomCard(String roundName,images,String des, bool isComplete, Color btncolor, int mark ) {
return Material(
color: btncolor,
elevation: 10.0,
borderRadius: BorderRadius.circular(20.0),
child: Container(
child: Column(
children: <Widget>[
Text(
'$mark'
),
Padding(
padding: EdgeInsets.symmetric(
vertical: 10.0,
),
child: Material(
elevation: 5.0,
borderRadius: BorderRadius.circular(100.0),
child: Container(
height: 200.0,
width: 200.0,
child:ClipOval(
child: Image(
image: AssetImage(images),
),
)
),
),
),
Center(
child: Text( roundName,
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
letterSpacing: 10.0,
fontFamily: 'S'
),),
),
Container(
padding:EdgeInsets.all(8.0),
child: Text(
des,
style: TextStyle(
color: Colors.white,
letterSpacing: 1.0
),
),
),
],
),
),
);
}
Color unlockColor = Colors.green;
Color lockColor = Colors.grey;
Color lockOrNot = Colors.grey;
void _onPressedOne() {
int marks1 = 24;
if(marks1< mark){
Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context)=> Quizjson( "Average Round", 7 ),
));
}
else{
createAlertDialouge(context);
}
}
void _onPressedTwo() {
int marks2 = 34;
int marc = mark;
if( marks2 < marc ){
Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context)=> Quizjson("Hard Round", 7 ),
));
}
else{
createAlertDialougeOne(context);
}
}
void _onPressedThree() {
int marks3 = 49;
int marc = mark;
if( marks3 < marc ){
Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context)=> Quizjson("Average Round", 8),
));
}
else{
createAlertDialougeTwo(context);
}
}
}
If you need the Result page:
import 'package:baybay_app/Quiz/QuizHome.dart';
import 'package:flutter/material.dart';
class ResultPage extends StatefulWidget {
int mark;
ResultPage({Key key, #required this.mark}) : super(key: key);
#override
_ResultPageState createState() => _ResultPageState(mark);
}
class _ResultPageState extends State<ResultPage> {
List<String> images = [
'assets/excellent.jpg',
'assets/good.png',
'assets/Sorry.png'
];
String message;
String image;
#override
void initState(){
if(mark<5){
image = images[2];
message = 'Try Again..\n' + 'You scored $mark';
}
else if(mark==5){
image = images[1];
message = 'Good.. \n' + 'You scored $mark';
}
else{
image = images[0];
message = 'Excellent!!!...\n' + 'You scored $mark';
}
}
int mark;
_ResultPageState(this.mark);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
"Result"
)
),
body: Column(
children:[
Expanded(
flex: 6,
child: Material(
elevation: 5.0,
child: Container(
child:Column(
children: [
Material(
child: Container(
width: 300.0,
height: 300.0,
child: ClipRect(
child: Image(
image: AssetImage(
image,
)
)
),
),
),
Center(
child: Text(
message,
style: TextStyle(
fontSize: 20.0,
fontFamily: 'Staatliches'
),
),
)
],
),
),
),
),
Expanded(
flex:4,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children:<Widget>[
OutlineButton(
onPressed: () {
Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context)=> QuizHome(mark:mark)));
},
child: Text(
'Continue',
style: TextStyle(
fontSize: 20.0,
fontFamily: 'Staatliches'
)
),
padding: EdgeInsets.symmetric(vertical: 10.0,horizontal: 15.0),
borderSide: BorderSide(width: 3.0,color: Colors.brown[700])
)
],
)
)
]
)
);
}
}
What can I try next?

how set data of virtual keyboard in textfield flutter

How i get focus of virtual keyboard rather than normal keyboard on textfiled .
heres the code
import 'dart:async';
import 'package:android/GlobalVariables.dart' as globals;
import 'package:flutter/material.dart';
import 'package:localstorage/localstorage.dart';
import 'Confirm.dart';
import 'package:virtual_keyboard/virtual_keyboard.dart';
import 'package:keyboard_actions/keyboard_actions.dart';
import 'package:connectivity/connectivity.dart';
import 'package:flutter/services.dart';
import 'HomeScreen.dart';
void bh(context) async {
var connectivityResult = await (Connectivity().checkConnectivity());
if (connectivityResult == ConnectivityResult.mobile) {
print("Connected to Mobile Network");
} else if (connectivityResult == ConnectivityResult.wifi) {
print("Connected to WiFi");
} else {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Center(
child: Text(
"Connectivity ",
style: TextStyle(fontSize: 15),
),
),
actions: <Widget>[
Center(
child: Text(
"Please Check your Internet Connection",
style: TextStyle(fontSize: 15),
)),
FlatButton(
child: Text(
'ok',
style: TextStyle(fontSize: 15),
),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
});
}
}
class DashboardScreen extends StatefulWidget {
#override
_DashboardScreenState createState() => new _DashboardScreenState();
}
class _DashboardScreenState extends State<DashboardScreen> {
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
LocalStorage userKey = new LocalStorage('userKey');
TextEditingController pinNumber = new TextEditingController();
bool hasKey;
var userKeyValue;
void showInSnackBar(String message) {
scaffoldKey.currentState.showSnackBar(SnackBar(content: Text(message)));
}
#override
void initState() {
super.initState();
bh(context);
}
void checkKey() async {
userKeyValue = await userKey.getItem('userKey');
print(userKeyValue);
if (userKeyValue == null) {
hasKey = false;
} else {
hasKey = true;
}
}
void sendDataNav(BuildContext context) {
String textToSend = pinNumber.text;
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Confirm(text: textToSend),
));
}
var study_no;
var select_mon;
LocalStorage mon = LocalStorage('mon');
LocalStorage studyNumber = LocalStorage('UserstudyNumber');
void start(context) async {
select_mon = DateTime.now().toString().substring(5, 7);
print("study number $study_no");
if (study_no == null) {
print("in $study_no");
Future.delayed(Duration.zero, () {
Navigator.pushNamed(context, '/setting');
});
} else {
print(select_mon);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => HomeScreen(stu: study_no, mon: select_mon),
));
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomPadding: false,
key: scaffoldKey,
body: SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height / 2.5,
width: MediaQuery.of(context).size.width,
color: globals.primaryColor,
child: Image.asset('image/asset/Logob.png'),
),
Padding(
padding: const EdgeInsets.all(15.0),
child: Container(
width: MediaQuery.of(context).size.width,
child: TextField(
controller: pinNumber,
style: new TextStyle(
fontSize: 20.0,
),
decoration: InputDecoration(
contentPadding: const EdgeInsets.symmetric(
vertical: 10, horizontal: 20),
border: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.green, style: BorderStyle.solid),
borderRadius: new BorderRadius.horizontal(),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: globals.primaryColor,
style: BorderStyle.solid),
borderRadius: new BorderRadius.horizontal(),
),
//icon: Icon(Icons.calendar_today,),
hintText: 'PIN', suffixStyle: TextStyle(fontSize: 10),
labelText: 'Enter Your Pin',
),
// Navigator.pushNamed(context, '/afterCalender')
// keyboardType: TextInputType.number,
// autofocus: true,
onSubmitted: (ss) async {
if (pinNumber.text.length < 1) {
showInSnackBar("Enter Pin");
print('invalid');
return;
}
userKeyValue = await userKey.getItem('userKey');
if (userKeyValue == null) {
hasKey = false;
} else {
hasKey = true;
}
if (hasKey) {
if (userKeyValue != pinNumber.text) {
// show error message
showInSnackBar("Wrong Pin");
print('not valid');
} else {
print('valid');
study_no =
studyNumber.getItem('UserstudyNumber').toString();
start(context);
showInSnackBar("Sucessful");
}
} else {
if (pinNumber.text.length != 4) {
showInSnackBar("Enter Pin of 4 Numbers");
// show error message of length
print('hello');
} else {
setState(() {
sendDataNav(context);
});
// userKey.setItem('userKey', pinNumber.text);
}
}
},
),
),
),
VirtualKeyboard(
height: 300,
fontSize: 15,
textColor: Colors.black,
type: VirtualKeyboardType.Numeric,
onKeyPress: (key) => print(key.text)),
],
),
),
);
}
}
How i get focus of virtual keyboard rather than normal keyboard on textfiled .
onclick on textfiled i want system keyboard disabled and virtual keyboard to get focus and allow to add data..........................................................................................................................................................................................................................
When the onKeyPress callback get fired, you can set the text using the pinNumber text controller.

Categories

Resources