How to write styles in flutter as classes - flutter

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,
);
}
}

Related

Flutter checkbox inside textfield

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

How to extract TextFormField as reusable widget in flutter

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 be a nullable parameter in a custom widget

i make a custom widget and using this widget in 7-8 place. i need to add a mask but in widget source said "it cant be null". i dont want to sent null parameter in all usage because i need to use only one place
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class TextFieldWidget extends StatelessWidget {
final text;
final controller;
final validation;
final mask;
final bool maxLength;
const TextFieldWidget({
Key? key,
this.text,
this.validation,
this.controller,
required this.maxLength, this.mask,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return TextFormField(
inputFormatters: [
LengthLimitingTextInputFormatter(maxLength ? 20 : null),
mask
],
validator: validation,
decoration: InputDecoration(
labelText: text,
border: OutlineInputBorder(
borderSide: const BorderSide(color: Colors.grey, width: 0.0),
borderRadius: BorderRadius.circular(10)),
),
);
}
}
i need to be nullable this "mask" parameter. thanks all!
It's a good practice assigning the types of parameters instead of leaving them dynamic as you do. A simple workaround is below :
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class TextFieldWidget extends StatelessWidget {
final text;
final controller;
final validation;
final TextInputFormatter? mask;
final bool maxLength;
const TextFieldWidget({
Key? key,
this.text,
this.validation,
this.controller,
required this.maxLength,
this.mask,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return TextFormField(
inputFormatters: [
LengthLimitingTextInputFormatter(maxLength ? 20 : null),
if (mask != null) mask!
],
validator: validation,
decoration: InputDecoration(
labelText: text,
border: OutlineInputBorder(
borderSide: const BorderSide(color: Colors.grey, width: 0.0),
borderRadius: BorderRadius.circular(10)),
),
);
}
}

I'm having issues trying to convert my StatelessWidget code..why?

I was trying to code a stateful widget on a statelessWidget class to put a bool and a stateState((), (show or hide password). So I followed some post which said that the solution is to convert.
I converted my class and I have some errors, maybe I should update my code but I don't know how to do that and I'm always getting errors like this:
36:32: Error: The setter '_isSecret' isn't defined for the class '_RoundedPasswordFieldState'.
-'_RoundedPasswordFieldState' is from 'package:yona/Login/Components/rounded_password_field.dart' ('lib/Login/Components/rounded_password_field.dart').
Try correcting the name to the name of an existing setter, or defining a setter or field named '_isSecret'.
Can you help me please ?
The problem is resolved, this is the new code
class _RoundedPasswordFieldState extends State<RoundedPasswordField> {
bool _isSecret = true;
#override
Widget build(BuildContext context) {
return TextFieldContainer(
child: TextFormField(
obscureText: _isSecret,
decoration: InputDecoration(
hintText: "Password",
border: InputBorder.none,
icon: Icon(
Icons.lock,
color: DarkTurquoise,
),
suffixIcon: InkWell(
onTap: () =>
setState(() => _isSecret = !_isSecret),
child: Icon(!_isSecret
? Icons.visibility
: Icons.visibility_off, color: DarkTurquoise),
),
),
),
);
}
}
To access _isSecret, you need to use widget.:
class RoundedPasswordField extends StatefulWidget {
final ValueChanged<String> onChanged;
const RoundedPasswordField({
required this.onChanged,
Key? key,
}) : super(key: key);
#override
_RoundedPasswordFieldState createState() => _RoundedPasswordFieldState();
}
class _RoundedPasswordFieldState extends State<RoundedPasswordField> {
bool _isSecret = true;
#override
Widget build(BuildContext context) {
return TextFieldContainer(
child: TextFormField(
obscureText:_isSecret,
decoration: InputDecoration(
hintText: "Password",
icon: Icon(
Icons.lock,
color: DarkTurquoise,
),
suffixIcon: InkWell(
onTap: () =>
setState(() => _isSecret = !_isSecret),
child: Icon(!_isSecret
? Icons.visibility
: Icons.visibility_off),
),
),
),
);
}
}
in setState you should change _isSecret to RoundedPasswordField._isSecret and the other problem is you are not calling onChanged.
working code:
class RoundedPasswordField extends StatefulWidget {
static bool _isSecret = true;
final ValueChanged<String> onChanged;
const RoundedPasswordField({
required this.onChanged,
Key? key,
}) : super(key: key);
#override
_RoundedPasswordFieldState createState() => _RoundedPasswordFieldState();
}
class _RoundedPasswordFieldState extends State<RoundedPasswordField> {
#override
Widget build(BuildContext context) {
return TextFieldContainer(
child: TextFormField(
obscureText: RoundedPasswordField._isSecret,
onChanged: widget.onChanged,
decoration: InputDecoration(
hintText: "Password",
icon: Icon(
Icons.lock,
color: DarkTurquoise,
),
suffixIcon: InkWell(
onTap: () =>
setState(() => RoundedPasswordField._isSecret = !RoundedPasswordField._isSecret),
child: Icon(!RoundedPasswordField._isSecret
? Icons.visibility
: Icons.visibility_off),
),
),
),
);
}
}
If you don't want to change _isSecret from outside of your widget then just use this code
class RoundedPasswordField extends StatefulWidget {
final ValueChanged<String> onChanged;
const RoundedPasswordField({
required this.onChanged,
Key? key,
}) : super(key: key);
#override
_RoundedPasswordFieldState createState() => _RoundedPasswordFieldState();
}
class _RoundedPasswordFieldState extends State<RoundedPasswordField> {
bool _isSecret = true;
#override
Widget build(BuildContext context) {
return TextFieldContainer(
child: TextFormField(
obscureText: _isSecret,
onChanged: widget.onChanged,
decoration: InputDecoration(
hintText: "Password",
icon: Icon(
Icons.lock,
color: DarkTurquoise,
),
suffixIcon: InkWell(
onTap: () => setState(() => _isSecret =
!_isSecret),
child: Icon(!_isSecret
? Icons.visibility
: Icons.visibility_off),
),
),
),
);
}
}

Flutter/Dart: Pass Parameters to a Stateful Widget?

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;
});
},
),
),