I am learning flutter I want a particular widget to be reused with different images at run time.
How to attain this is giving me difficulties I would like to know how to get this.
I am writing the peice of code kindly suggest what is a correct way
scaffold: CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
trailing: Image.asset('assets/Menu_Button.png'),
automaticallyImplyLeading: false,
backgroundColor: Colors.blueAccent,
),
child: SafeArea(
child: Material(
child: Container(
child: Column(
children: [
Column(
children: <Widget>[
new Stack(children: <Widget>[
new Container(
child: background.Row1
),
Container(
color: Colors.blueAccent,
child: Image.asset('assets/card_bg.png')
),
]
),
Container(
color: Colors.blueAccent,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ShowingOptions('assets/image1.png').Options,//*****calling function with parameter so that it can put widget**********//
ShowingOptions('assets/image2.png').Options,
ShowingOptions('assets/image3.png').Options,
ShowingOptions('assets/image4.png').Options,
],
),
background.Row2,
background.Row3
],
),
),
))
),
);
}
}
/**********function defination starts *************/
ShowingOptions(image) {
Widget Options = padding: EdgeInsets.only(bottom: 5, left: 7,
right: 7, top: 5),
child: Container(
height: 55.0,
width: 55.0,
child: Padding(
padding: EdgeInsets.all(1),
child: CircleAvatar(
backgroundColor: Colors.transparent,
radius: 10,
child: new Image.asset(image, height: 150, width:
150),
)),
decoration: new BoxDecoration(
shape: BoxShape.circle,
color: Colors.white,
border: new Border.all(
color: Colors.orange,
width: 5.0,
),
)
),
);
}
}
/**********function defination ends *************/
What Iam doing is making a funciton and when I am calling the function 'showOptions('assets/image1')' I am passing the image that I need to show.
Inside the function defination I am writing a widget that I wanted to be placed whenevr I call that funcition bys showing the image that I have passed
the way I implemented this whole is not working want a solution. I know this is not the proper way as I am new I would like to have some guidance.
Create a Custom Widget,
Create a Stateless or Stateful Class
declare Required Vairables
return your Custom Widget
below is Example of CustomButton with onPressed event.
//Create a Stateless or Stateful Class
class CustomButton extends StatelessWidget {
//declare Required Vairables
final String buttonText;
final VoidCallback onPressed;
final bool loading;
//constructor
CustomButton({this.buttonText,this.onPressed,this.loading});
#override
Widget build(BuildContext context) {
return Row(
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.only(left: 30,right: 30),
child: Container(
decoration: BoxDecoration(borderRadius: BorderRadius.all(Radius.circular(100)),
color: Colors.red),
child: Material(
color: Colors.transparent,
child: InkWell(
borderRadius: BorderRadius.all(Radius.circular(100)),
splashColor: Colors.green,
onTap: onPressed,
child: Padding(
padding: const EdgeInsets.all(15.0),
child: Center(child:
loading==true?
CircularProgressIndicator(backgroundColor: Colors.white,)
:
Text(buttonText,style: TextStyle(fontSize: 30,color: Colors.white),)),
),
),
),
),
),
),
],
);
}
}
Use :
CustomButtonSmall(buttonText: "Direction",onPressed: (){})
Here is a wonderfully explained example of how to achieve this easily.
I just copy the code from there. You basically have to create a separate class for the widget you have in mind:
import 'package:flutter/material.dart';
class AppTextFormField extends StatelessWidget {
//
AppTextFormField({
this.controller,
this.hintText,
this.helpText,
this.prefixIcon,
this.suffixIcon,
this.isPassword,
this.enabled,
this.readOnly,
this.borderColor,
});
final TextEditingController controller;
final String hintText;
final String helpText;
final IconData prefixIcon;
final IconData suffixIcon;
final bool isPassword;
final bool enabled;
final bool readOnly;
final Color borderColor;#override
Widget build(BuildContext context) {
return Container(
child: TextFormField(
controller: controller,
readOnly: null == readOnly ? false : true,
obscureText: null == isPassword ? false : true,
decoration: InputDecoration(
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.greenAccent,
width: 1.0,
),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.greenAccent,
width: 1.0,
),
),
border: OutlineInputBorder(
borderSide: BorderSide(
color: null == borderColor ? Colors.teal : borderColor,
width: 1.0,
),
),
hintText: null == hintText ? '' : hintText,
helperText: null == helpText ? '' : helpText,
prefixIcon: null == prefixIcon ? null : Icon(prefixIcon),
suffix: null == suffixIcon ? null : Icon(suffixIcon),
enabled: null == enabled ? true : false,
),
),
);
}
}
And then in the class where you want to use the widget you call the it like this:
Container(
child: Column(
children: [
AppTextFormField(
controller: _emailController,
helpText: 'Email',
hintText: 'Email',
prefixIcon: Icons.email,
),
AppTextFormField(
controller: _passwordController,
helpText: 'Password',
hintText: 'Password',
isPassword: true,
prefixIcon: Icons.lock_open,
),
You don't have to use all the methods, just the ones you need.
Related
I'm trying to display the input value below onto another page that contains radio buttons . my aim is that every time i write or change a value in a textfield it gets updated and displays onto a different page with the radio options . The snippet of code below is for the textfield - i used riverpod to connect it to firestore:
class AddMealPage extends ConsumerWidget {
const AddMealPage({Key? key}) : super(key: key);
static const String route = "/addMeal";
#override
Widget build(BuildContext context, WidgetRef ref) {
final model = ref.read(addMealProvider);
return LoadingLayer(
child: Scaffold(
appBar: AppBar(
elevation: 0,
iconTheme: const IconThemeData(
color: Colors.black,
),
title: const Text(
"Create Meal",
style: TextStyle(color: Colors.black, fontWeight: FontWeight.bold),
),
backgroundColor: Colors.white,
),
bottomNavigationBar: Padding(
padding: const EdgeInsets.fromLTRB(24, 0, 24, 24),
child: MaterialButton(
padding: const EdgeInsets.all(16),
color: Colors.black,
onPressed: model.enabled
? () async {
try {
await model.writeMeal();
Navigator.pop(context);
} catch (e) {
AppSnackbar(context).error(e);
}
}
: null,
child: const Text(
"Add meal",
style: TextStyle(color: Color.fromARGB(255, 247, 245, 245)),
),
),
),
body: SingleChildScrollView(
child: Container(
padding:
const EdgeInsets.symmetric(vertical: 60.0, horizontal: 10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
GestureDetector(
onTap: () async {
final picked = await ImagePicker()
.pickImage(source: ImageSource.gallery);
if (picked != null) {
model.file = File(picked.path);
}
},
child: Container(
margin: const EdgeInsets.only(),
width: MediaQuery.of(context).size.width,
height: 210.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
image: (model.mealUrl != null || model.file != null)
? DecorationImage(
image: model.file != null
? FileImage(model.file!)
: NetworkImage(model.mealUrl!)
as ImageProvider,
fit: BoxFit.cover,
)
: null),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
if (model.mealUrl == null && model.file == null)
const Expanded(
child: Center(
child: Icon(
Icons.photo,
),
),
),
const Material(
color: Colors.transparent,
child: Padding(
padding: EdgeInsets.all(8.0),
),
),
],
),
),
),
const SizedBox(
height: 10,
),
const Padding(
padding: EdgeInsets.only(left: 15.0),
child: Text(
"Meal Name",
style: TextStyle(fontSize: 17, fontWeight: FontWeight.w500),
),
),
Container(
height: 50,
padding: const EdgeInsets.only(top: 10),
width: MediaQuery.of(context).size.width,
margin: const EdgeInsets.symmetric(horizontal: 20),
child: TextFormField(
textInputAction: TextInputAction.done,
initialValue: model.mealName,
maxLines: 1,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(color: Colors.grey),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: const BorderSide(color: Colors.grey),
),
),
onChanged: (v) => model.mealName = v,
),
),
I want to display the input value i get from the textfield above in the format of a radioButton on a seperate page :
enum Variant { mealName }
class RadioOption extends StatefulWidget {
const RadioOption({Key? key}) : super(key: key);
#override
State<RadioOption> createState() => _RadioOptionState();
}
class _RadioOptionState extends State<RadioOption> {
Variant? _character = Variant.mealName;
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
RadioListTile<Variant>(
title: const Text('$mealName'),
value: Variant.MealName,
groupValue: _character,
onChanged: (Variant? value) {
setState(() {
_character = value;
});
},
),
I don't see the whole architecture of the app. But if you want to transfer model.mealName, you can make String value (mealName) in your RadioOption, and pass it through the constructor:
final mealName;
RadioOption({required this.mealName});
And then access it in _RadioOptionState by:
title: const Text(widget.mealName);
You can use TextEditingController and add this controller to your TextFormField which have controller properties but you can't use initialValue and controller both so avoid initialValue. To put value you can use controller.text = your_value;
You value will be filled in text field.
To get value from TextFormField Use var newValue = controller.text; and send this newValue to another page in constructor.
I am using TextField widget in my project. I need to show the InputBox above the keyboard if the user clicks and start typing on the TextField, WhatsApp has this functionality in Landscape mode:
I need this functionality in my flutter application too, any little help will be very welcome, Thank you in advance.
Issue updated it here
below code will help you
import 'package:chat_system_flutter/utils/common_logic.dart';
import 'package:chat_system_flutter/utils/common_string.dart';
import 'package:flutter/material.dart';
import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart';
import 'package:get/get.dart';
class ChatScreen extends StatefulWidget {
const ChatScreen({
Key? key,
}) : super(key: key);
#override
_ChatScreenState createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> with AutomaticKeepAliveClientMixin {
TextEditingController messageController = TextEditingController();
#override
void initState() {
super.initState();
}
#override
bool get wantKeepAlive => true;
#override
Widget build(BuildContext context) {
super.build(context);
return KeyboardVisibilityBuilder(
builder: (BuildContext context, bool isKeyboardVisible) {
if (isKeyboardVisible) {
// blok of code
}
return Obx(
() => Scaffold(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
body: body(),
),
);
},
);
}
Widget body() {
return GestureDetector(
onTap: () {
hideKeyboard(context);
},
child: SafeArea(
child: Column(
children: [
Expanded(
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
//message listview
],
),
),
),
Divider(
color: Theme.of(context).cardColor,
thickness: 2,
),
Container(
padding: const EdgeInsets.symmetric(
horizontal: 10,
vertical: 0,
),
child: Row(
children: [
Expanded(
child: TextField(
controller: messageController,
autocorrect: true,
enableSuggestions: true,
maxLines: 2,
onChanged: (val) {
// block of code
},
style: TextStyle(
fontSize: 16,
color: Theme.of(context).canvasColor,
),
decoration: InputDecoration(
hintText: typeYourMsgStr,
hintStyle: TextStyle(
fontSize: 16,
color: Theme.of(context).hintColor,
),
border: const UnderlineInputBorder(
borderSide: BorderSide(
color: Colors.transparent,
),
),
enabledBorder: const UnderlineInputBorder(
borderSide: BorderSide(
color: Colors.transparent,
),
),
focusedBorder: const UnderlineInputBorder(
borderSide: BorderSide(
color: Colors.transparent,
),
),
),
textInputAction: TextInputAction.newline,
/* onSubmitted: (_) {
sendMsg();
},*/
),
),
GestureDetector(
onTap: () {
// send message
},
child: Container(
padding: const EdgeInsets.all(8),
child: Icon(
Icons.arrow_upward,
color: Theme.of(context).canvasColor,
),
decoration: BoxDecoration(
color: Theme.of(context).primaryColor,
borderRadius: BorderRadius.circular(10)),
),
),
],
),
),
],
),
),
);
}
}
output
You need to add a padding in your main Container which contains your TextField like this:
padding: EdgeInsets.only(
top: 10,
right: 10,
left: 10,
bottom: MediaQuery.of(context).viewInsets.bottom + 10,
),
What MediaQuery.of(context).viewInsets.bottom does is that it takes the height of onscreen keyboard and adds it to padding whenever the keyboard appears on the screen. This makes your TextField to move 10 pixels above your keyboard (that's because we added 10 to bottom padding separately).
Another Widget that would help with scrolling is wrapping your main widget with a SingleChildScrollView.
Feel free to clear up any confusions in the comments :)
I want to implement OTP verification screen without any package.
when i entered the number it should move to next input field
I m using this code in my current project take a refrence this will help
class Otp extends StatefulWidget {
final String? phnNumber;
final String ? code;
String? from;
Otp({Key ?key, this.phnNumber, this.from, this.code}) : super(key:
key);
#override
_OtpState createState() => _OtpState();
}
class _OtpState extends State<Otp> {
double ? height ;
double ? width;
TextEditingController ? contrller1;
TextEditingController ? contrller2;
TextEditingController ? contrller3;
TextEditingController ? contrller4;
SendOtpRequest resend = SendOtpRequest();
SharedPreferences ? prefs;
getSharedPreferences () async
{
prefs = await SharedPreferences.getInstance();
}
String Code = "";
#override
void initState() {
// TODO: implement initState
super.initState();
contrller1 = TextEditingController();
contrller2 = TextEditingController();
contrller3 = TextEditingController();
contrller4 = TextEditingController();
getSharedPreferences();
}
#override
Widget build(BuildContext context) {
height= MediaQuery.of(context).size.height;
width = MediaQuery.of(context).size.height;
final verifyprovider = Provider.of<PostDataProvider>(context);
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
toolbarHeight:height! * 0.07802345,
titleSpacing: 0,
backgroundColor: HexColor("#18263d"),
automaticallyImplyLeading: false,
leading: Padding(
padding: const EdgeInsets.only(left: 8.0,),
child: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Container(
color: Colors.transparent,
child: Image.asset("assets/images/back_ic-1.png")),
),
),
// SizedBox(width: width!*0.001234,),
title:Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
height: height!/15,
width: height!/15,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
width: 2,
color:HexColor("#fc4f00"),
)),
child: Padding(
padding: const EdgeInsets.all(1.0),
child: Container(
height: height!/11,
width: height!/11,
decoration: BoxDecoration(
image: const DecorationImage(
image:
AssetImage("assets/images/home_logo.png"),
fit: BoxFit.fill
),
shape: BoxShape.circle,
border: Border.all(
width: 1,
color:HexColor("#fc4f00"),
)),
),
),
),
SizedBox(width: width! * 0.04234,),
Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: Text("Verification",
style: GoogleFonts.oswald(fontWeight: FontWeight.bold,
color: Colors.white,
fontSize: width! * 0.03345
),),
),
],
) ,
),
body: SafeArea(
child: Padding(
padding: EdgeInsets.symmetric(vertical: 24, horizontal: 32),
child: Column(
children: [
Text("We have send verification code on your mobile number",
style: GoogleFonts.oswald(fontStyle: FontStyle.normal,
fontSize: width!*0.0234,
color: HexColor("#8b8b8b")),
),
SizedBox(height: height!/38,),
Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_textFieldOTP(first: true, last: false,controllerr:
contrller1),
_textFieldOTP(first: false, last: false,controllerr:
contrller2),
_textFieldOTP(first: false, last: false,controllerr:
contrller3),
_textFieldOTP(first: false, last: true, controllerr:
contrller4),
],
),
Padding(
padding: const EdgeInsets.all(8.0),
child: InkWell(
onTap:() {
resend.phoneNumber= widget.phnNumber;
resend.countryCode = widget.code;
verifyprovider.resendOtp(context,
jsonEncode(resend));
},
child: Text("Resend OTP?",
style: GoogleFonts.oswald(fontStyle:
FontStyle.normal,
fontSize: width!*0.0234,
color: HexColor("#fc4f00")),
),
),
),
SizedBox(height: height!/28,),
GestureDetector(
onTap: (){
if(contrller1!.text.isNotEmpty&&
contrller2!.text.isNotEmpty&&contrller3!.
text.isNotEmpty&&contrller4!.text.isNotEmpty){
verifyOtpRequest verify = verifyOtpRequest();
verify.phoneNumber = widget.phnNumber;
verify.otp=
contrller1!.text+contrller2!.
text+contrller3!.text+contrller4!.text;
verifyprovider.otpVerification(context,
jsonEncode(verify), widget.from);
}else{
CommonUtils.showToast(msg: "Please fill all the
fields ");
}
},
child: Container(
height: height!/18,
width: width,
decoration: BoxDecoration(
color: HexColor("#fc4f00"),
borderRadius: BorderRadius.circular(10)
),
child: Center(
child: Text("Verify",style: TextStyle(
color: Colors.white,
fontSize: width!*0.02345
),),
)
),
),
],
),
],
),
),
),
);
}
Widget _textFieldOTP({bool ? first, last,
TextEditingController ?
controllerr}) {
return Container(
height:height!/12 ,
child: AspectRatio(
aspectRatio: 1.0,
child: TextField(
controller: controllerr,
autofocus: true,
onChanged: (value) {
if (value.length == 1 && last == false) {
FocusScope.of(context).nextFocus();
}
if (value.length == 0 && first == false) {
FocusScope.of(context).previousFocus();
}
},
showCursor: false,
readOnly: false,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
keyboardType: TextInputType.number,
maxLength: 1,
decoration: InputDecoration(
counter: Offstage(),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(width: 2, color: Colors.black54),
borderRadius: BorderRadius.circular(12)),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(width: 2, color: Colors.black54),
borderRadius: BorderRadius.circular(12)),
),
),
),
);
}
}
When the length of the input data reaches one, you will have to change the text field focus node.
For Example
If you are in the first field, and you enter a number field one focus should be lost, and field two should be in focus. This can be done, by requestFocus.
This article will of help for you: Flutter Focus
I want to scroll the loginform but NOT the background, but i noticed that the cointaner that contains these "circles" are moved to the up when keyboards appears, so i added
resizeToAvoidBottomInset: true,
To the scaffold, but now i cant scroll anything in the loginform and thats is what i dont want, i want to scroll ONLY the loggin form..
Here is the screenshot of the emulator, just click this
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:landscapes/bloc/inherited_provider.dart';
import 'package:landscapes/bloc/login_bloc.dart';
import 'package:landscapes/pages/register_page.dart';
class LoginPage extends StatefulWidget {
LoginPage({Key key}) : super(key: key);
#override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
final formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: true,
body: Form(
key: formKey,
child: Stack(
children: <Widget>[
_crearFondo(),
_loginForm(context),
],
),
));
}
Widget _crearFondo() {
Size size = MediaQuery.of(context).size;
final fondoGris = Container(
height: size.height, width: size.width, color: Colors.grey[850]);
final circulo = Container(
width: 90.0,
height: 90.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(100.0),
color: Color.fromRGBO(255, 255, 255, 0.05)),
);
return Stack(
children: <Widget>[
fondoGris,
Positioned(top: 50.0, left: 30.0, child: circulo),
Positioned(top: 150.0, right: 50.0, child: circulo),
Positioned(bottom: 180.0, right: 20.0, child: circulo),
Positioned(bottom: 280.0, left: 40.0, child: circulo),
],
);
}
Widget _loginForm(context) {
final bloc = InheritedProvider.loginBlocInherit(context);
final size = MediaQuery.of(context).size;
return SingleChildScrollView(
child: Column(
children: <Widget>[
SafeArea(child: Container(height: size.height * 0.05)),
SizedBox(height: size.height * 0.05),
welcomeBackForm(),
SizedBox(height: 55.0),
_formEmail(bloc),
SizedBox(height: 30.0),
_formPassword(),
SizedBox(height: 38),
_button(),
SizedBox(height: 50),
_crearCuenta(),
],
),
);
}
//MENSAJE BIENVENIDA
Widget welcomeBackForm() {
return Container(
alignment: Alignment.topLeft,
margin: EdgeInsets.only(left: 40.0),
child: Text(
'Hello!\nWelcome back',
style: GoogleFonts.playfairDisplay(
fontSize: 30, fontWeight: FontWeight.w600, color: Colors.white),
),
);
}
//TEXTFORMFIELD DEL EMAIL
Widget _formEmail(LoginBloc bloc) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 30.0),
child: TextFormField(
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
icon: Icon(
Icons.email,
color: Colors.white,
),
hintText: 'Email adress',
filled: true,
fillColor: Colors.grey[600],
enabledBorder: OutlineInputBorder(borderSide: BorderSide.none),
border: OutlineInputBorder(borderSide: BorderSide.none)),
style: TextStyle(height: 1),
validator: (value) {
Pattern pattern =
r'^(([^<>()[\]\\.,;:\s#\"]+(\.[^<>()[\]\\.,;:\s#\"]+)*)|(\".+\"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$';
RegExp regExp = new RegExp(pattern);
if (regExp.hasMatch(value)) {
return null;
} else {
return ('El email no es correcto');
}
},
),
);
}
//TEXTFORMFIELD DEL PASSWORD
Widget _formPassword() {
return Container(
padding: EdgeInsets.symmetric(horizontal: 30.0),
child: TextFormField(
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
icon: Icon(
Icons.lock,
color: Colors.white,
),
hintText: 'Password',
filled: true,
fillColor: Colors.grey[600],
enabledBorder: OutlineInputBorder(borderSide: BorderSide.none),
border: OutlineInputBorder(borderSide: BorderSide.none),
),
style: TextStyle(height: 1),
),
);
}
//BOTON INGRESAR
Widget _button() {
return RaisedButton(
color: Color.fromRGBO(254, 200, 140, 1),
padding: EdgeInsets.symmetric(horizontal: 90.0, vertical: 15.0),
child: Text('ingresar'),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5.0),
),
elevation: 0.0,
onPressed: () => _submit(),
);
}
//FLATBUTTON DE CREAR CUENTA
Widget _crearCuenta() {
return FlatButton(
onPressed: () => Navigator.pushReplacementNamed(context, 'registerpage'),
child: Text(
'Crear una nueva cuenta',
style: TextStyle(fontSize: 14),
),
textColor: Colors.white,
);
}
//SUBMIT DEL BOTON
void _submit() async {
if (!formKey.currentState.validate()) return null;
formKey.currentState.save();
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (BuildContext context) => RegisterPage()));
// Navigator.pushReplacementNamed(context, HomePage.routName).then((value) { setState(() { });});
}
}
You may try wrapping your _loginForm with SingleChildScrollView as follows :
SingleChildScrollView(child: _loginForm(context)),
By doing so the widgets within _crearFondo() will not scroll, however the widgets within _loginForm will scroll.
Please review the Flutter Documentation for SingleChildScrollView
SingleChildScrollView
A box in which a single widget can be scrolled.
This widget is useful when you have a single box that will normally be
entirely visible, for example a clock face in a time picker, but you
need to make sure it can be scrolled if the container gets too small
in one axis (the scroll direction).
It is also useful if you need to shrink-wrap in both axes (the main
scrolling direction as well as the cross axis), as one might see in a
dialog or pop-up menu. In that case, you might pair the
SingleChildScrollView with a ListBody child.
When you have a list of children and do not require cross-axis
shrink-wrapping behavior, for example a scrolling list that is always
the width of the screen, consider ListView, which is vastly more
efficient that a SingleChildScrollView containing a ListBody or Column
with many children.
I have created my own custom textinputfield, everything do has come up well but the thing is how to give that a validator upon the button click?
This is my custom inputfield,
class CustomInputField extends StatelessWidget {
bool _validate = false;
Icon fieldIcon;
String hintText;
TextInputType textType;
CustomInputField(this.fieldIcon, this.hintText, this.textType);
#override
Widget build(BuildContext context) {
return Container(
width: 300,
child: Material(
elevation: 5.0,
borderRadius: BorderRadius.all(Radius.circular(10.0)),
color: Colors.deepOrange,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(12.0),
child: fieldIcon,
),
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(topRight: Radius.circular(10.0), bottomRight: Radius.circular(10.0)),
),
width: 250,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
controller: _text,
decoration: InputDecoration(
border: InputBorder.none,
hintText: hintText,
fillColor: Colors.white,
errorText: _validate? 'Value can\'t be empty' : null,
filled: true,
),
keyboardType: textType,
style: TextStyle(
fontSize: 15.0,
color: Colors.black,
),
),
),
),
],
)
),
);
}
}
And this is how I'm calling that in different pages
CustomInputField(
Icon(
Icons.lock,
color: Colors.white,
),
'Password',
TextInputType.visiblePassword),
So upon click of the button if the text field is empty, i need to give in the errorText, so could anyone help me out?
You need to do a couple of things.
Create a GlobalKey type FormState for your Stateful Widget.
GlobalKey<FormState> _formKey = GlobalKey<FormState>();
Create a TextFormField with a validator and onSave callback.
Form(
key: _formKey, //Give you form it's key.
child: Column(
children: <Widget>[
TextFormField(
validator: (input) {
if (input.isEmpty) { //Here I check if the field data is empty.
return "Field cannot be empty.;
}
},
//Update what ever variable you want with the validated data.
//Here I picked a variable named foo.
onSaved: (input) => foo = input,
],
),
),
Make a button that uses the _formKey to call the validate function and save function.
RaisedButton(
child: Text("Do Something"),
onPressed: () {
//Validate will run on the TextFormField and return the error provided.
if (_formKey.currentState.validate()) {
_formKey.currentState.save(); //If validated, we will update our foo variable.
}
},
),