I was wondering how I could recreate the Samsung Notes App. To be more precise I want to have the checkbox functionality within the textfield. See picture below:
Thanks for your support!
I've just tried it myself and this looks like how you want it to look:
TextField(
decoration: InputDecoration(
prefixIcon: Checkbox(value: value, onChanged: (value) {//bool magic here}),
hintText: 'TextField'
),
),
Check out https://api.flutter.dev/flutter/material/InputDecoration-class.html for more InputDecoration() options to prettify things.
if I understood you correctly you can use Textformfield. You can add the checkbox widget to the textformfield prefix parameter. I hope this gives you an idea and helps.
For Example:
class MyHomePage extends StatefulWidget {
final String title;
const MyHomePage({
Key? key,
required this.title,
}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool isChecked = false;
TextEditingController textController = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: TextField(
controller:textController,
style:TextStyle(decoration: isChecked ? TextDecoration.lineThrough : TextDecoration.none),
decoration: InputDecoration(
prefixIcon: Checkbox(value:isChecked, onChanged: (value) {
setState(() { isChecked=value!;});
}),
hintText: 'To Do'
),
),
),
);
}
}
Dartpad => https://dartpad.dev/?id=e75b493dae1287757c5e1d77a0dc73f1
Related
Let's say I have a souple of components using the same styles but I want it to write as classes like in html and css
Is there a way this is possible?
By the way I'm a noob to coding started a year ago I'm 14 years old
I have added an example for read only text field for your reference.
class ReadOnlyTextWidget extends StatefulWidget {
final TextEditingController controller;
final String label;
final Function() onPressedCallback;
const ReadOnlyTextWidget({
required this.controller,
required this.label,
required this.onPressedCallback,
Key? key,
}) : super(key: key);
#override
State<ReadOnlyTextWidget> createState() => _ReadOnlyTextWidgetState();
}
class _ReadOnlyTextWidgetState extends State<ReadOnlyTextWidget> {
#override
Widget build(BuildContext context) {
return TextFormField(
controller: widget.controller,
decoration: InputDecoration(
label: Text(widget.label),
hintText: 'Enter ${widget.label}',
border: const OutlineInputBorder(),
icon: TextButton.icon(
onPressed: widget.onPressedCallback,
label: const Text('Refresh'),
icon: const Icon(Icons.refresh),
)),
readOnly: true,
);
}
}
I'm using TextFormField in Flutter to input email for register page.
What I want is if there's no char '#' and '.' then it will get rejected.
This is the result I hope for :
input : name
errorText : "You should enter valid email address"
input : name#gmail.com
response : success
And this is my code :
TextFormField(
keyboardType: TextInputType.emailAddress,
inputFormatters: [
FilteringTextInputFormatter.allow(
RegExp("[a-z0-9#._-]")),
],
onChanged: (text) {
_onSearchChanged(text);
},
controller: emailController,
decoration: InputDecoration(
errorText:
isEmailInvalid ? "Email is already taken" : null,
hintText: 'Enter your email',
suffixIcon: isEmailvalid
? const Icon(
Icons.check,
color: Colors.green,
)
: const Icon(
Icons.check_circle,
color: Colors.transparent)
)),
You can use it to validate email, tell me if have any problem
bool isEmail = RegExp(r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+#[a-zA-Z0-9]+\.[a-zA-Z]+").hasMatch(your_email_here);
You need to wrap your TextFieldForm inside a Form and set the validator for it. You can refer to this example code:
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return const MaterialApp(
title: _title,
home: MyStatefulWidget(),
);
}
}
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key? key}) : super(key: key);
#override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
#override
Widget build(BuildContext context) {
return Material(
child: Center(
child: Form(
autovalidateMode: AutovalidateMode.always,
onChanged: () {
Form.of(primaryFocus!.context!)!.save();
},
child: Padding(
padding: const EdgeInsets.all(8.0),
child: ConstrainedBox(
constraints: BoxConstraints.tight(const Size(200, 50)),
child: TextFormField(
validator: (String? value) {
return value != null && RegExp(r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+#[a-zA-Z0-9]+\.[a-zA-Z]+").hasMatch(value) ? null : 'Invalid email';
}
),
),
),
),
),
);
}
}
I want to make my flutter project highly manageable, apply clean code and maintain DRY concept strictly. There are a lot of input elements in any flutter project. So I want to make this element as a separate widget so that if I want to change in future then I will change in one place. Here is my approach:
import 'package:flutter/material.dart';
import '../utility/validatation.dart';
class RegistrationPage extends StatefulWidget {
static const String routeName = '/registrationPage';
#override
State<RegistrationPage> createState() => _RegistrationPageState();
}
class _RegistrationPageState extends State<RegistrationPage> {
final _formKey = GlobalKey<FormState>();
final TextEditingController nameInput = TextEditingController();
final TextEditingController businessName = TextEditingController();
final TextEditingController productTypeId = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
body: new Form(
key: _formKey,
autovalidateMode: AutovalidateMode.onUserInteraction,
child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
Container(
height: 70,
margin: EdgeInsets.only(bottom: 50),
child: Image(image: AssetImage('assets/logo.png')),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 30.0),
child: TextInput(inputController: nameInput, label: 'আপনার নাম'),
),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
_register(context);
}
},
child: Text('Next'),
)
]),
),
);
}
void _register(BuildContext context) {}
}
class TextInput extends StatelessWidget {
const TextInput({
Key? key,
required this.inputController,
required this.label,
}) : super(key: key);
final TextEditingController inputController;
final String label;
#override
Widget build(BuildContext context) {
return TextFormField(
controller: inputController,
keyboardType: TextInputType.text,
decoration: const InputDecoration(
border: UnderlineInputBorder(),
prefixIcon: Icon(Icons.phone),
labelText: label,
),
validator: (value) {
return Validation.required(value);
},
);
}
}
But I got this error:
What is wrong in my code? Is there any problem in my approach or should I stop thinking to refactor my code as I do? Please also suggest if there is any smarter way to make code more clean and manageable.
Oh I see so you have this
class TextInput extends StatelessWidget {
const TextInput({
Key? key,
required this.inputController,
required this.label,
}) : super(key: key);
final TextEditingController inputController;
final String label;
#override
Widget build(BuildContext context) {
return TextFormField(
controller: inputController,
keyboardType: TextInputType.text,
// Notice the const here right?
// So the idea is that decoration objects could rebuild to either change one thing or the other, so 'label' here cannot be a constant
//So to solve this InputDecoration should not have const.
decoration: const InputDecoration(
border: UnderlineInputBorder(),
prefixIcon: Icon(Icons.phone),
labelText: label,
),
validator: (value) {
return Validation.required(value);
},
);
}
}
Since you are using a variable in InputDecoration, you should not declare InputDecoration with const keyword.
I need to call pass my title and oldtitle parameters to my EditPage Stateful widget. But if I do this;
class EditPage extends StatefulWidget {
String title;
String oldtitle;
EditPage({this.title, this.oldtitle})
The strings are not available to the build unless I call it them as widget.title and widget.oldtitle.
But I'm using a textfield within a form that doesn't seem to work right if I use these widgets.
Here's the form code:
Container(
child: TextField(
decoration: new InputDecoration(
hintText: widget.oldtitle,
contentPadding: new EdgeInsets.all(1.0),
border: InputBorder.none,
filled: true,
fillColor: Colors.grey[300],
),
keyboardType: TextInputType.text,
autocorrect: false,
onChanged: (titleText) {
setState(() {
widget.title= titleText;
});
},
),
),
But then if I do this;
class _EditPageState extends State<EditPage> {
String title;
String oldtitle;
EditPage({this.title, this.oldtitle})
I can't pass the title parameter to it from another screen. IE:
`EditPage(title:mytitle, oldtitle:myoldtitle);`
So What's the correct way to pass a parameter to a Stateful widget?
You should never pass the variables to the state directly, since it does not guarantee that widget will get rebuilt when state will be updated. You should accept parameters via your stateful widget and access them from the state itself via widget.variable.
Example:
class TestWidget extends StatefulWidget {
final String variable;
TestWidget({Key key, #required this.variable}) : super(key: key);
#override
_TestWidgetState createState() => _TestWidgetState();
}
class _TestWidgetState extends State<TestWidget> {
#override
Widget build(BuildContext context) {
return Container(
child: Center(
// Accessing the variables passed into the StatefulWidget.
child: Text(widget.variable),
),
);
}
}
Looks like the solution was to separate the title from the oldtitle;
class EditPage extends StatefulWidget {
String oldtitle;
EditPage({this.oldtitle})
and then;
class _EditPageState extends State<EditPage> {
String title;
So now for the form;
Container(
child: TextField(
decoration: new InputDecoration(
hintText: widget.oldtitle,
contentPadding: new EdgeInsets.all(1.0),
border: InputBorder.none,
filled: true,
fillColor: Colors.grey[300],
),
keyboardType: TextInputType.text,
autocorrect: false,
onChanged: (titleText) {
setState(() {
title= titleText;
});
},
),
),
Please help for my 2 questions.
1st Question. Why text value disappear?[FIXED] by #Praneeth
I added gif
please click
I used this way my code,
In my widget I called UsernameTextField class.
Widget looks like this,
Widget build > WillPopScope > Scaffold > Form > ListView > children>
Container (below container) I added key: _scaffoldKey, and key: formKey, also.
Container(
padding: EdgeInsets.all(16.0),
margin: EdgeInsets.only(top: 30.0),
child: UsernameTextField(),
),
UsernameTextField()
class UsernameTextField extends StatefulWidget{
final usernameController = TextEditingController();
#override
State<StatefulWidget> createState() {
return UsernameTextFieldState(usernameController);
}
}
class UsernameTextFieldState extends State<UsernameTextField>{
final usernameController;
UsernameTextFieldState(this.usernameController);
#override
Widget build(BuildContext context) {
return AppTextField(
decoration: InputDecoration(
contentPadding: const EdgeInsets.all(20.0),
labelText: AppTranslations.of(context)
.text("loginpage_username"),
),
myController: usernameController,
textInputType: TextInputType.emailAddress
);
}
}
AppTextField() class, I used this class for my every TextField Widget
class AppTextField extends StatelessWidget {
final InputDecoration decoration;
final myController;
final TextInputType textInputType;
AppTextField({
this.decoration,
this.myController,
this.textInputType
});
#override
Widget build(BuildContext context) {
return TextFormField(
controller: myController,
keyboardType: textInputType,
textAlign: TextAlign.left,
decoration: decoration
);}}
2nd Question. How to get textField value?
In my button onPressed() method I called, I called validation method, But result is null
usernameValidation(){
String username = UsernameTextField().usernameController.text;
print(username);
}
First convert UsernameTextField class to a Stateful one by extending as a StatefulWidget instead of StatelessWidget.
Then you can get value from usernameController.text
UPDATE
class UsernameTextField extends StatefulWidget{
final usernameController = TextEditingController();
UsernameTextField(this.usernameController)
#override
State<StatefulWidget> createState() {
return UsernameTextFieldState(usernameController);
}
}
class UsernameTextFieldState extends State<UsernameTextField>{
#override
Widget build(BuildContext context) {
return AppTextField(
decoration: InputDecoration(
contentPadding: const EdgeInsets.all(20.0),
labelText: AppTranslations.of(context)
.text("loginpage_username"),
),
myController: widget.usernameController,
textInputType: TextInputType.emailAddress
);
}
}