How to set radio button to selected based on String value fetched from API?
I have an async function that does the API call and fetches the user profile. I need to set the selected gender to the radio button.
I tried calling SetState() from an async function but it results in infinite loop call for build().
Below is my code:
#override
Widget build(BuildContext context) {
if(isProfileExists) {
getProfileDetails();
print("selected radio : "+selectedRadio.toString());
if(selectedRadio >= 0) {
setMemberType(selectedRadio);
}
}
double width=MediaQuery.of(context).size.width;
double height=MediaQuery.of(context).size.height;
Future<bool> _onWillPop() async {
Navigator.pushNamedAndRemoveUntil(context, '/home', ModalRoute.withName('/home'));
}
return new WillPopScope(
child: Scaffold(
appBar: AppBar(
title: Text(
_userName+"\'s Profile ",
style: TextStyle(fontSize: 20.0),
),
actions: <Widget>[
Padding(
padding: EdgeInsets.only(right: 20.0),
child: GestureDetector(
onTap: () {},
child: Icon(
Icons.save
),
)
),
],
),
key: _scaffoldKey,
body: Container(
height: height,
width: width,
child: SingleChildScrollView(
padding: EdgeInsets.fromLTRB(0, 20.0, 0, 10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SingleChildScrollView(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
GestureDetector(
onTap: (){},
child: TextField(
decoration: InputDecoration(labelText: "Bio"),
controller: bioTextController,
),
),
SizedBox(height: 20.0,),
Padding(
padding: EdgeInsets.all(10.0),
child: Text("Basic Information", style: TextStyle(
color: Colors.black54,
fontSize: 14.0
),
),
),
TextField(
decoration: InputDecoration(labelText: "Height"),
controller: heightTextController,
),
TextFormField(
decoration: InputDecoration(labelText: "Weight"),
controller: weightTextController,
),
TextFormField(
decoration: InputDecoration(labelText: "BMI"),
controller: bmiTextController,
),
TextFormField(
decoration: InputDecoration(labelText: "Target Weight"),
controller: targetWeightTextController,
),
TextFormField(
decoration: InputDecoration(labelText: "Date Of Birth"),
controller: dateOfBirthController,
),
TextFormField(
decoration: InputDecoration(labelText: "Age"),
readOnly: true,
controller: ageTextController,
),
SizedBox(height: 15.0),
Text("Gender"),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Radio(
value: 0,
groupValue: radioValue,
onChanged: setMemberType,
),
Text("Female" ),
Radio(
value: 1,
groupValue: radioValue,
onChanged: setMemberType,
),
Text("Male"),
],
),
...
And the set state function is below:
void setMemberType(int i) {
setState(() {
radioValue = i;
if(i == 0)
_gender = "F";
else
_gender = "M";
});
}
You cannnot call setState from your build method.
Remove this:
if(isProfileExists) {
getProfileDetails();
print("selected radio : "+selectedRadio.toString());
if(selectedRadio >= 0) {
setMemberType(selectedRadio);
}
}
Instead, use an initState inside the State of your Stateful Widget:
#override
void initState() {
if(isProfileExists) {
getProfileDetails();
if(selectedRadio >= 0) {
radioValue = selectedRadio;
}
}
}
Related
this is my first time using community to ask about my project. First thing first, english isn't my first language and I'm a very beginner in flutter world. I'm trying to build my first mobile application using flutter and now I'm trying to connect my project to firebase (I looked at youtube tutorial). I don't know if the firebase already connect because when I'm trying to run the application and go to registration page, there this error message.
And here is my code:
import 'package:dfu_check_application/common/auth_controller.dart';
import 'package:flutter/material.dart';
import 'package:dfu_check_application/common/theme_helper.dart';
import 'package:dfu_check_application/pages/widgets/header_widget.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:hexcolor/hexcolor.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'profile_page.dart';
class RegistrationPage extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _RegistrationPageState();
}
}
class _RegistrationPageState extends State<RegistrationPage> {
final _formKey = GlobalKey<FormState>();
bool checkedValue = false;
bool checkboxValue = false;
#override
Widget build(BuildContext context) {
var nameController = TextEditingController();
var emailController = TextEditingController();
var passwordController = TextEditingController();
return Scaffold(
backgroundColor: Colors.white,
body: SingleChildScrollView(
child: Stack(children: [
Container(
height: 150,
child: HeaderWidget(150, false, Icons.person_add_alt_1_rounded),
),
Container(
margin: EdgeInsets.fromLTRB(25, 50, 25, 10),
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
alignment: Alignment.center,
child: Column(
children: [
Form(
key: _formKey,
child: Column(
children: [
GestureDetector(
child: Stack(
children: [
Container(
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(100),
border:
Border.all(width: 5, color: Colors.white),
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.black12,
blurRadius: 20,
offset: const Offset(5, 5),
),
],
),
child: Icon(
Icons.person,
color: Colors.grey.shade300,
size: 80.0,
),
),
Container(
padding: EdgeInsets.fromLTRB(80, 80, 0, 0),
child: Icon(
Icons.add_circle,
color: Colors.grey.shade700,
size: 25.0,
),
),
],
),
),
SizedBox(
height: 30,
),
Container(
child: TextFormField(
controller: nameController,
decoration: ThemeHelper().textInputDecoration(
'Full Name', 'Enter your full name'),
),
decoration: ThemeHelper().inputBoxDecorationShaddow(),
),
SizedBox(
height: 30,
),
SizedBox(height: 20.0),
Container(
child: TextFormField(
controller: emailController,
decoration: ThemeHelper().textInputDecoration(
"E-mail address", "Enter your email"),
keyboardType: TextInputType.emailAddress,
validator: (val) {
// ignore: prefer_is_not_empty
if (!(val!.isEmpty) &&
!RegExp(r"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+#[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,253}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,253}[a-zA-Z0-9])?)*$")
.hasMatch(val)) {
return "Enter a valid email address";
}
return null;
},
),
decoration: ThemeHelper().inputBoxDecorationShaddow(),
),
SizedBox(height: 20.0),
Container(
child: TextFormField(
obscureText: true,
controller: passwordController,
decoration: ThemeHelper().textInputDecoration(
"Password*", "Enter your password"),
validator: (val) {
if (val!.isEmpty) {
return "Please enter your password";
}
return null;
},
),
decoration: ThemeHelper().inputBoxDecorationShaddow(),
),
SizedBox(height: 15.0),
FormField<bool>(
builder: (state) {
return Column(
children: <Widget>[
Row(
children: <Widget>[
Checkbox(
value: checkboxValue,
onChanged: (value) {
setState(() {
checkboxValue = value!;
state.didChange(value);
});
}),
Text(
"I accept all terms and conditions.",
style: TextStyle(color: Colors.grey),
),
],
),
Container(
alignment: Alignment.centerLeft,
child: Text(
state.errorText ?? '',
textAlign: TextAlign.left,
style: TextStyle(
color: Theme.of(context).errorColor,
fontSize: 12,
),
),
)
],
);
},
validator: (value) {
if (!checkboxValue) {
return 'You need to accept terms and conditions';
} else {
return null;
}
},
),
SizedBox(height: 20.0),
GestureDetector(
onTap: () {
AuthController.instance.register(
nameController.text.trim(),
emailController.text.trim(),
passwordController.text.trim());
},
),
Container(
decoration: ThemeHelper().buttonBoxDecoration(context),
child: ElevatedButton(
style: ThemeHelper().buttonStyle(),
child: Padding(
padding: const EdgeInsets.fromLTRB(40, 10, 40, 10),
child: Text(
"Register".toUpperCase(),
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
onPressed: () {
if (_formKey.currentState!.validate()) {
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
builder: (context) => ProfilePage()),
(Route<dynamic> route) => false);
}
},
),
),
SizedBox(height: 30.0),
Text(
"Or create account using social media",
style: TextStyle(color: Colors.grey),
),
SizedBox(height: 25.0),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
GestureDetector(
child: FaIcon(
FontAwesomeIcons.google,
size: 35,
color: HexColor("#EC2D2F"),
),
onTap: () {
setState(() {
showDialog(
context: context,
builder: (BuildContext context) {
return ThemeHelper().alartDialog(
"Google Account",
"You tap on Google icon.",
context);
},
);
});
},
),
],
),
],
),
),
],
),
),
]),
),
);
}
}
If you guys see more error on my code, please tell me because I'm very clueless about this. Thank you in advance!
The issue occurs from Stack the one inside
Column(
children: [
Form(
key: _formKey,
child: Column(
children: [
GestureDetector(
child: Stack( // this one
Can be fixed by providing hight
GestureDetector(
child: SizedBox(
height: MediaQuery.of(context).size.height, //this based on your need
child: Stack(
I think you can re struct the widget and don't need to use multi-Stack.
More about /ui/layout and Unbounded height / width
Whenever I click on any textfield of the form, I get the following error in the screen:
Null check operator used on a null value
See also https://flutter.dev/docs
Also, the console is showing the following error:
The following ArgumentError was thrown resolving an image codec:
Invalid argument(s): No host specified in URI file:///
Here is the code of the login form. I can't figure out why this error is showing up.
// .....
child: Form(
key: _formKey,
autovalidateMode: AutovalidateMode.disabled,
child: ListView.builder(
itemCount: 1,
shrinkWrap: false,
itemBuilder: (BuildContext context, int index) {
return Column(
children: [
SizedBox(height: 30),
HeroImage(),
SizedBox(height: 20),
Container(
child: Padding(
padding: const EdgeInsets.only(left: 20, right: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
AppLableWidget(
title: Languages.of(context)!.labelEmail,
),
CardTextFieldWidget(
focus: (v) {
FocusScope.of(context).nextFocus();
},
textInputAction: TextInputAction.next,
hintText: Languages.of(context)!.labelEnterYourEmailID,
textInputType: TextInputType.emailAddress,
textEditingController: _textEmail,
validator: kvalidateEmail,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
AppLableWidget(
title: Languages.of(context)!.labelPassword,
),
],
),
CardPasswordTextFieldWidget(
textEditingController: _textPassword,
validator: kvalidatePassword,
hintText: Languages.of(context)!.labelEnterYourPassword,
isPasswordVisible: _passwordVisible),
Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
/* Row(
children: [
Padding(
padding: const EdgeInsets.all(10.0),
child: ClipRRect(
clipBehavior: Clip.hardEdge,
borderRadius: BorderRadius.all(Radius.circular(5)),
child: SizedBox(
width: 40.0,
height: ScreenUtil().setHeight(40),
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
child: Container(
child: Theme(
data: ThemeData(
unselectedWidgetColor: Colors.transparent,
),
child: Checkbox(
value: isRememberMe,
onChanged: (state) =>
setState(() => isRememberMe = !isRememberMe),
activeColor: Colors.transparent,
checkColor: Color(Constants.colorTheme),
materialTapTargetSize: MaterialTapTargetSize.padded,
),
),
),
),
),
),
),
Text(
Languages.of(context)!.labelRememberMe,
style: TextStyle(fontSize: 14.0, fontFamily: Constants.appFont),
),
],
),*/
Container(
padding: const EdgeInsets.all(10.0),
alignment: Alignment.centerRight,
child: GestureDetector(
onTap: () {
Navigator.of(context).push(Transitions(
transitionType: TransitionType.fade,
curve: Curves.bounceInOut,
reverseCurve: Curves.fastLinearToSlowEaseIn,
widget: ChangePassword()));
},
child: Text(
Languages.of(context)!.labelForgotPassword,
style: TextStyle(fontFamily: Constants.appFontBold,fontSize: ScreenUtil().setSp(16),),
),
),
),
],
),
Padding(
padding: EdgeInsets.only(left: 20.0, right: 20,top: 10, bottom: 10),
child: RoundedCornerAppButton(
onPressed: () {
if (
_formKey.currentState!.validate()) {
// if (SharedPreferenceUtil.getString(
// Constants
// .appPush_oneSingleToken)
// .isEmpty) {
// getOneSingleToken(SharedPreferenceUtil
// .getString(Constants
// .appSettingCustomerAppId));
// } else {
// }
Constants.checkNetwork().whenComplete(() => callUserLogin());
} else {
setState(() {
// validation error
//_autoValidate = true;
});
}
},
btnLabel: Languages.of(context)!.labelLogin,
),
),
SizedBox(
height: 10.0,
),
GestureDetector(
onTap: () {
Navigator.of(context).push(Transitions(
transitionType: TransitionType.slideUp,
curve: Curves.bounceInOut,
reverseCurve: Curves.fastLinearToSlowEaseIn,
widget: CreateNewAccount()));
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
Languages.of(context)!.labelDonthaveAcc,
style: TextStyle(fontFamily: Constants.appFont,fontSize: ScreenUtil().setSp(14),),
),
Text(
Languages.of(context)!.labelCreateNow,
style: TextStyle(fontFamily: Constants.appFontBold,fontSize: ScreenUtil().setSp(16),),
),
],
),
),
SizedBox(
height: 20,
),
InkWell(
onTap: () {
Navigator.of(context).push(Transitions(
transitionType: TransitionType.slideUp,
curve: Curves.bounceInOut,
reverseCurve: Curves.fastLinearToSlowEaseIn,
widget: DashboardScreen(0)));
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
Languages.of(context)!.labelSkipNow,
style: TextStyle(
color: Colors.black,
decoration: TextDecoration.underline,
decorationColor: Colors.black,
fontWeight: FontWeight.bold,
decorationThickness: 5,
fontSize: ScreenUtil().setSp(16),
fontFamily: Constants.appFontBold,),
),
],
),
),
],
),
),
),
],
);
},
),
),
//.....
String kvalidatePassword(String? value) {
Pattern pattern = r'^(?=.*?[a-z])(?=.*?[0-9]).{8,}$';
if (value!.isEmpty) return 'Username is Required.';
final RegExp nameExp = new RegExp(pattern as String);
if (!nameExp.hasMatch(value))
return 'Please enter only alphabetical characters.';
return value;
}
String kvalidatePassword(String? value) {
Pattern pattern = r'^(?=.*?[a-z])(?=.*?[0-9]).{8,}$';
if (value!.isEmpty) return 'Username is Required.';
final RegExp nameExp = new RegExp(pattern as String);
if (!nameExp.hasMatch(value))
return 'Please enter only alphabetical characters.';
return value;
}
Please help. New to Flutter and this is an old project I need to fix.
AppLableWidget(title: Languages.of(context)!.labelEmail),
Try This...
AppLableWidget(title: Languages.of(context)?.labelEmail ?? ''),
String value = 'Test String';
String? value1;
Text(value ?? ''), // output --> Test String
Text(value1 ?? ''), // output --> ''
// here manage if value are null then return ''(Blank Text) otherwise Text.
This error occurs when you use a bang operator (!) on a nullable instance which wasn't initialized.
For example:
String? foo; // Nullable String
void main() {
var len = foo!.length; // Runtime error: Null check operator used on a null value
}
Solution:
You need to find out where you're using the bang operator in your code. Once you are there, you can use any of the following solutions:
Use a local variable
var f = foo;
if (f != null) {
var len = f.length; // Safe
}
Use ?. and ??
var len = foo?.length ?? 0; // Provide a default value if foo was null.
I have created a page where user can input their exam result which are subject and grade.
On the page, user need to click the add subject button to add another subject depending on how many subject they have. User also can remove subject by clicking the remove subject button.
The problem is only TextFormField value submitted. How to get the data for DropDownFormField if the form created dynamically?
I have tried the read the data using the onChanged function of the drop down and yes the data was stored to the variable gradeController but it returns null when I submit the data.
This is the model
class SubjectGrade {
final String? name;
final String? grade;
SubjectGrade(this.name, this.grade);
#override
String toString() {
return 'SPM: name = $name, grade = $grade';
}
}
This is the form
import 'package:flutter/material.dart';
import 'package:testing_app/models/education_model.dart';
class EducationBackgroundForm extends StatefulWidget {
const EducationBackgroundForm({Key? key}) : super(key: key);
#override
_EducationBackgroundFormState createState() =>
_EducationBackgroundFormState();
}
class _EducationBackgroundFormState extends State<EducationBackgroundForm> {
final nameTECs = <TextEditingController>[];
final gradeTECs = <String?>[];
final forms = <Form>[];
Form createForm() {
TextEditingController nameController = TextEditingController();
String? gradeController;
nameTECs.add(nameController);
gradeTECs.add(gradeController);
final grades = ['A+', 'A', 'A-', 'B+', 'B', 'C+', 'C', 'D', 'E', 'G'];
DropdownMenuItem<String> buildMenuItem(String item) => DropdownMenuItem(
value: item,
child: Text(item),
);
return Form(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Row(
children: <Widget>[
Expanded(
flex: 2,
child: Column(
children: <Widget>[
TextFormField(
controller: nameController,
decoration: InputDecoration(
hintText: 'Subject Name',
labelText: 'Subject ${forms.length + 1}',
border: const OutlineInputBorder(),
contentPadding:
const EdgeInsets.only(left: 8, right: 8),
),
keyboardType: TextInputType.text,
textInputAction: TextInputAction.done,
),
],
),
),
const SizedBox(width: 5),
Expanded(
flex: 1,
child: Column(
children: <Widget>[
DropdownButtonHideUnderline(
child: DropdownButtonFormField(
value: gradeController,
isExpanded: true,
iconSize: 36,
icon: const Icon(Icons.arrow_drop_down,
color: Colors.black),
items: grades.map(buildMenuItem).toList(),
onChanged: (String? value) {
setState(() {
gradeController = value;
});
},
hint: const Text("Grade"),
decoration: const InputDecoration(
border: OutlineInputBorder(),
contentPadding: EdgeInsets.only(left: 8),
),
),
)
],
)),
],
),
const SizedBox(height: 10)
],
),
);
}
#override
void initState() {
super.initState();
forms.add(createForm());
}
saveSPMResultToFirebase() {
List<SubjectGrade> entries = [];
for (int i = 0; i < forms.length; i++) {
final name = nameTECs[i].text;
final grade = gradeTECs[i].toString();
entries.add(SubjectGrade(name, grade));
}
debugPrint(entries.toString());
//Navigator.pop(context, entries);
}
#override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
const Text("SPM Result", style: TextStyle(fontSize: 18)),
const SizedBox(height: 20),
Expanded(
child: ListView.builder(
itemCount: forms.length,
itemBuilder: (BuildContext context, int index) {
return forms[index];
},
),
),
const SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: SizedBox(
width: double.infinity,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.all(14),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8))),
onPressed: () => setState(() {
forms.add(createForm());
}),
child: const Text(
'Add Subject',
style: TextStyle(
fontSize: 16,
),
),
),
),
),
const SizedBox(width: 5),
Expanded(
child: SizedBox(
width: double.infinity,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.all(14),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8))),
onPressed: () => setState(() {
if (forms.length > 1) {
forms.removeAt(forms.length - 1);
}
}),
child: const Text(
'Remove Subject',
style: TextStyle(
fontSize: 16,
),
),
),
),
),
],
),
const SizedBox(height: 10),
SizedBox(
width: double.infinity,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.all(14),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8))),
onPressed: () {
saveSPMResultToFirebase();
},
child: const Text(
'Update',
style: TextStyle(
fontSize: 16,
),
),
),
),
],
);
}
}
When I submit the form, the debug output I get from the submit function for grade is null.
Output:
[SPM: name = English, grade = null]
You should add value of DropDownButton in onChanged method not at top of create form.
change your code to this:
First Delete gradeTECs.add(gradeController); line from top of createForm().
Form createForm() {
TextEditingController nameController = TextEditingController();
String? gradeController;
nameTECs.add(nameController);
// gradeTECs.add(gradeController); <==== DELETE THIS LINE.
Add gradeTECs.add(gradeontroller); in onChanged method of DropdownButtonFormField
DropdownButtonHideUnderline(
child: DropdownButtonFormField(
value: gradeController,
isExpanded: true,
iconSize: 36,
icon: const Icon(Icons.arrow_drop_down,
color: Colors.black),
items: grades.map(buildMenuItem).toList(),
onChanged: (String? value) {
setState(() {
gradeController = value;
gradeTECs.add(gradeController); <=== ADD HERE ==>
});
},
hint: const Text("Grade"),
decoration: const InputDecoration(
border: OutlineInputBorder(),
contentPadding: EdgeInsets.only(left: 8),
),
),
),
Am a newbie though. I followed a tutorial for my code below which is a register form. How can i validate each input field since it's just one widget which is reused for the entire input field.
............................................................................................................................................................
Code
import 'package:flutter/material.dart';
import 'package:flutterlogindesign/utils/color.dart';
import 'package:flutterlogindesign/widgets/btn_widget.dart';
import 'package:flutterlogindesign/widgets/herder_container.dart';
class RegPage extends StatefulWidget {
#override
_RegPageState createState() => _RegPageState();
}
class _RegPageState extends State<RegPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
padding: EdgeInsets.only(bottom: 30),
child: Column(
children: <Widget>[
HeaderContainer("Register"),
Expanded(
flex: 1,
child: Container(
margin: EdgeInsets.only(left: 20, right: 20, top: 30),
child: Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
_textInput(hint: "Fullname", icon: Icons.person),
_textInput(hint: "Email", icon: Icons.email),
_textInput(hint: "Phone Number", icon: Icons.call),
_textInput(hint: "Password", icon: Icons.vpn_key),
Expanded(
child: Center(
child: ButtonWidget(
btnText: "REGISTER",
onClick: () {
Navigator.pop(context);
},
),
),
),
RichText(
text: TextSpan(children: [
TextSpan(
text: "Already a member ? ",
style: TextStyle(color: Colors.black)),
TextSpan(
text: "Login",
style: TextStyle(color: orangeColors)),
]),
)
],
),
),
)
],
),
),
);
}
Widget _textInput({controller, hint, icon}) {
return SingleChildScrollView(
child: Container(
margin: EdgeInsets.only(top: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(20)),
color: Colors.white,
),
padding: EdgeInsets.only(left: 10),
child: TextFormField(
controller: controller,
decoration: InputDecoration(
border: InputBorder.none,
hintText: hint,
prefixIcon: Icon(icon),
),
),
),
);
}
}
Use Form Widget like the following
final _formKey = GlobalKey<FormState>();
bool autoValidate = false;
String phone;
child:Form( key: _formKey,
autovalidateMode: autoValidate ? AutovalidateMode.always : AutovalidateMode.disabled,
child: Column(
children: [
AppTextFormField(
initialValue: phone,
onChanged: (value) {
phone = value;
},
validator: (value) {
if (value.isEmpty) {
return 'Enter Phone number';
}
},
),
PrimaryButton(
text: 'Go',
onTap: () {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
} else {
autoValidate = true;
}
},
),
],
),
),
I am trying to come up with a code editor which takes input from a text form field and shows the output on a Rich Text widget using DartSyntaxHighlighter.
While it works fine for a short snippet of code, it doesn't show all the code for a larger snippet. Here's what I've done so far :
class CodeEditorWidget extends StatefulWidget {
CodeEditorWidget();
#override
_ContentWidgetState createState() {
return _ContentWidgetState();
}
}
class _ContentWidgetState extends BaseState<CodeEditorWidget> {
String _currentCode = "";
#override
void initializeData() {
_currentCode = "class HelloWorld {\n"
"public static void main() {\n"
"System.out.println(\"Hello again\");\n"
"}\n"
"}";
_contentController.addListener(() {
_currentCode = _contentController.value.text;
setState(() {
});
});
}
#override
Widget build(BuildContext context) => _buildContent();
Widget _buildContent() {
//return _buildBody();
userState = AppStateWidget.of(context).userState;
return _buildBody();
}
Scaffold _buildBody() => Scaffold(
key: _scaffoldLoginKey,
appBar: buildAppBar("Code Editor"),
body: _buildCodeEditor(),
floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
floatingActionButton: _buildFab(),
);
_buildCodeEditor() => Card(
margin: const EdgeInsets.fromLTRB(BaseState.horizontalMargin, 0, BaseState.horizontalMargin, 0),
child: Column(
children: <Widget>[
Expanded(
child: _buildCodeView()//buildSyntaxCodeBlock(_currentCode, 12)//_buildCodeView(),
),
_buildInputContainer()
],
),
);
_buildCodeView() => SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Container(
width: double.infinity,
height: double.maxFinite,
padding: EdgeInsets.all(12),
decoration: BoxDecoration(color: Colors.black),
child: RichText(
text: TextSpan(
style: TextStyle(fontFamily: 'VarelaRound-Regular', fontSize: 12),
children: <TextSpan>[
DartSyntaxHighlighter(SyntaxHighlighterStyle.darkThemeStyle()).format(_currentCode)
],
),
),
),
),
);
Container _buildInputContainer() {
return Container(
color: Colors.grey,
padding: EdgeInsets.all(8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
_buildInputLayout(),
],
),
);
}
_buildInputLayout() => Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[_buildTextForm()],
);
Widget _buildTextForm() => Flexible(
child: Container(
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
style: buildTextStyleBlack(16),
decoration: InputDecoration.collapsed(hintText: "Type here..."),
maxLines: 10,
validator: _validateEmptyCode,
controller: _contentController,
keyboardType: TextInputType.multiline,
onSaved: (String contentString) {
//_currentCode = contentString;
},
),
),
),
);
String _validateEmptyCode(String value) {
return value.isEmpty ? "Required" : null;
}
var _contentController = TextEditingController();
_buildFab() => FloatingActionButton(
onPressed: () {
setState(() {
});
},
child: Icon(Icons.add),
foregroundColor: Colors.white,
backgroundColor: Colors.green,
);
var _scaffoldLoginKey = GlobalKey<ScaffoldState>();
_showSnackBar(String message) => _scaffoldLoginKey.currentState
.showSnackBar(SnackBar(content: Text(message, style: buildTextStyle(16),)));
}
Here's a screen shot for reference :
This is a web page I am trying to build in flutter.
For me, this piece of code is doing what you are trying to acheive.
TextEditingController text1Controller = new TextEditingController();
TextEditingController text2Controller = new TextEditingController();
#override
Widget build(BuildContext context) {
Size screenSize = MediaQuery.of(context).size;
return new Scaffold(
backgroundColor: Colors.white,
appBar: new PreferredSize(
preferredSize: new Size(screenSize.width, 55.0),
child: new AppBar(
elevation: 5.0,
title : new Text(
"Code Editor",
style: new TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 18.0)),
centerTitle: true,
backgroundColor: Colors.blue,
),
),
body: Container(
child: Column(
children: <Widget>[
new Padding(padding: EdgeInsets.only(bottom: 20.0, top: 20.0)),
new TextField(
onChanged: (text) {
setState(() {
text2Controller.text = text;
});
},
controller: text1Controller,
keyboardType: TextInputType.text,
autofocus: false,
decoration: InputDecoration(
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
focusedBorder: OutlineInputBorder(borderSide: const BorderSide(color: Colors.black, width: 2.0)),
),
),
new Padding(padding: EdgeInsets.only(bottom: 20.0)),
new TextField(
controller: text2Controller,
keyboardType: TextInputType.text,
autofocus: false,
decoration: InputDecoration(
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
focusedBorder: OutlineInputBorder(borderSide: const BorderSide(color: Colors.black, width: 2.0)),
),
)
],),),
);
}