Flutter fixed button position - flutter

I'm developing an application on flutter and I'm having a problem with the position of the ElevatedButton. When the Validator returns the error message below the TextFormField, the widget expands downward and the position of the add button changes. I would like to keep the add button pinned to the same position as the beginning of the app
button in normal position
Button out of its original position after returning the validator
My code:
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Lista de Compras"),
backgroundColor: Colors.green,
centerTitle: true,
),
body: Column(
children: <Widget>[
Container(
padding: EdgeInsets.fromLTRB(15, 10, 5, 10),
child: Form(
key: _formKey,
child: Row(
children: <Widget>[
Theme(
data: ThemeData(
primaryColor: Colors.green,
hintColor: Colors.green),
child: Expanded(
child: TextFormField(
controller: _controlador,
validator: (value) {
if (value.isEmpty) {
return "Insira um item";
}
return null;
},
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.green),
borderRadius:
BorderRadius.circular(100)),
border: OutlineInputBorder(
borderRadius:
BorderRadius.circular(100)),
labelText: "Novo item",
hintText: "Insira um item",
hintStyle: TextStyle(color: Colors.grey),
labelStyle:
TextStyle(color: Colors.green),
suffixIcon: IconButton(
onPressed: () => _controlador.clear(),
icon: Icon(Icons.clear,
color: Colors.grey),
))))),
Padding(padding: EdgeInsets.only(right: 6)),
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.green,
shape: CircleBorder(),
padding: EdgeInsets.all(12)),
child: Icon(Icons.add, color: Colors.white),
onPressed: () {
if (_formKey.currentState.validate()) {
_addCompras();
}
}),
],
),
)),

This is an expected behaviour, when TextFormField show an errorText this will append a text below the TextFormField adding extra height for about 22. Check working example below :
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.light(),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Column(
children: [
MeasureSize(
child: FormWidget(),
onChange: (size) {
print(size);
},
),
MeasureSize(
child: FormWidget(hideError: false),
onChange: (size) {
print(size);
},
),
FormWidget(
hideError: false,
addPaddingToTrailingButton: true,
),
],
),
),
);
}
}
class FormWidget extends StatelessWidget {
final bool hideError;
final bool addPaddingToTrailingButton;
FormWidget({
this.hideError = true,
this.addPaddingToTrailingButton = false,
});
#override
Widget build(BuildContext context) {
Widget trailingButton = ElevatedButton(
style: ElevatedButton.styleFrom(
shape: CircleBorder(),
padding: EdgeInsets.all(12),
),
child: Icon(Icons.add),
onPressed: () {},
);
if (addPaddingToTrailingButton) {
trailingButton = Padding(
padding: const EdgeInsets.only(bottom: 22),
child: trailingButton,
);
}
return Container(
color: Colors.grey[300],
margin: const EdgeInsets.symmetric(vertical: 16),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(width: 8),
Expanded(
child: TextField(
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(100),
),
labelText: "Label text field",
hintText: "Hint text field",
errorText: hideError ? null : 'Error text shown',
suffixIcon: IconButton(
onPressed: () {},
icon: Icon(Icons.clear),
),
),
),
),
SizedBox(width: 8),
trailingButton,
],
),
);
}
}
typedef void OnWidgetSizeChange(Size size);
class MeasureSizeRenderObject extends RenderProxyBox {
Size oldSize;
final OnWidgetSizeChange onChange;
MeasureSizeRenderObject(this.onChange);
#override
void performLayout() {
super.performLayout();
Size newSize = child.size;
if (oldSize == newSize) return;
oldSize = newSize;
WidgetsBinding.instance.addPostFrameCallback((_) {
onChange(newSize);
});
}
}
class MeasureSize extends SingleChildRenderObjectWidget {
final OnWidgetSizeChange onChange;
const MeasureSize({
Key key,
#required this.onChange,
#required Widget child,
}) : super(key: key, child: child);
#override
RenderObject createRenderObject(BuildContext context) {
return MeasureSizeRenderObject(onChange);
}
}
I have adding a background so it will show the height difference :
TextField without errorText shown.
TextField with errorText shown.
TextField with errorText shown, with additional padding on icon button.
Check dartpad here

the answer by Allan above is very great.
But if you are facing issues learning that do it this way:
Add Elevated button to Column and add SizedBox with height 22 as its children. Here the height is calculated as (Height of TextFormField with error - of TextFormField without error) using flutter inspector.
Column(
children: [
ElevatedButton(...),
SizedBox(
height: 22,
),
],
),
Now add helperText: ' ', in TextFormField InputDecoration:
TextFormField(
validator: (value) {
if (value == null || value.isEmpty) {
return "Insira um item";
}
return null;
},
decoration: InputDecoration(
helperText: ' ',
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.green),
borderRadius: BorderRadius.circular(100)),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(100)),
labelText: "Novo item",
hintText: "Insira um item",
hintStyle: TextStyle(color: Colors.grey),
labelStyle: TextStyle(color: Colors.green),
),
),
Here you can see the dartpad for full code.
This will get you this result:

Related

Separate suffixIcon for password visibility

How to separate suffixIcon for password visibility? If I press icon on field password it also does the same thing on field confirm password.
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
bool isObsecure = false;
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: const Text('Text Form Field'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextFormField(
obscureText: isObsecure,
decoration: InputDecoration(
hintText: 'Password',
suffixIcon: IconButton(
onPressed: () {
setState(() {
isObsecure = !isObsecure;
});
},
icon: Icon(
isObsecure ? Icons.visibility_off : Icons.visibility,
),
),
),
),
TextFormField(
obscureText: isObsecure,
decoration: InputDecoration(
hintText: 'Confirm Password',
suffixIcon: IconButton(
onPressed: () {
setState(() {
isObsecure = !isObsecure;
});
},
icon: Icon(
isObsecure ? Icons.visibility_off : Icons.visibility,
),
),
),
),
],
),
),
),
);
}
}
you have to define 2 flags. 1 for password visibility and 1 for confirm:
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
bool isObsecure = false;
bool isConfirmObsecure = false;
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: const Text('Text Form Field'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextFormField(
obscureText: isObsecure,
decoration: InputDecoration(
hintText: 'Password',
suffixIcon: IconButton(
onPressed: () {
setState(() {
isObsecure = !isObsecure;
});
},
icon: Icon(
isObsecure ? Icons.visibility_off : Icons.visibility,
),
),
),
),
TextFormField(
obscureText: isConfirmObsecure,
decoration: InputDecoration(
hintText: 'Confirm Password',
suffixIcon: IconButton(
onPressed: () {
setState(() {
isConfirmObsecure = !isConfirmObsecure;
});
},
icon: Icon(
isConfirmObsecure
? Icons.visibility_off
: Icons.visibility,
),
),
),
),
],
),
),
),
);
}
}
///You can use the provider also to hide and visible the password icon. Hope this will work for you.
////This is my forgot password screen
import 'package:flutter/material.dart';
import 'package:form_field_validator/form_field_validator.dart';
import 'package:provider/provider.dart';
import 'package:traveling/Provider/common/ObscureTextState.dart';
import 'package:traveling/helpers/AppColors.dart';
import 'package:traveling/helpers/AppStrings.dart';
import 'package:traveling/screens/Employee/home/BottomNavBar.dart';
class ForgotPasswordA extends StatefulWidget {
#override
_ForgotPasswordAState createState() => _ForgotPasswordAState();
}
class _ForgotPasswordAState extends State<ForgotPasswordA> {
/// These variables are used for getting screen height and width
double? _height;
double? _width;
///controllers are used to get text which user enter in TextFiled
TextEditingController confirmPasswordController = TextEditingController();
TextEditingController passwordController = TextEditingController();
GlobalKey<FormState> _formkey = GlobalKey();
String? confirmPassword, password;
#override
void initState() {
// TODO: implement initState
super.initState();
}
///this widget is the main widget and it is used for building a UI in the app
#override
Widget build(BuildContext context) {
_height = MediaQuery.of(context).size.height;
_width = MediaQuery.of(context).size.width;
return Material(
child: Scaffold(
backgroundColor: AppColors.white,
body:Consumer<LoginProvider>(
builder:(context, obs, child) {
///Consumer is used to get value from the loginProvider class
return GestureDetector(
onTap: () {
FocusScope.of(context).unfocus();
},
child: Container(
height: _height,
width: _width,
margin: EdgeInsets.only(top: 70),
padding: EdgeInsets.only(bottom: 5),
child: SingleChildScrollView(
child: Column(
children: <Widget>[
SizedBox(height: _height! / 22),
appText(),
SizedBox(height: _height! / 18),
Container(
width: _width! * .85,
child: Form(
///define global key for validation
key: _formkey,
autovalidateMode: AutovalidateMode.onUserInteraction,
child: Column(
children: <Widget>[
SizedBox(height: _height! / 50),
TextFormField(
controller: passwordController,
validator: (value) {
if (value!.isEmpty) {
return "Please Enter Password!";
} else if (value.length < 6) {
return "Please Enter more than 6 digit .";
} else {
return null;
}
},
obscureText:
Provider.of<LoginProvider>(context, listen: false)
.isTrue,
keyboardType: TextInputType.emailAddress,
autofillHints: [AutofillHints.email],
cursorColor: AppColors.black,
style: TextStyle(
color: Color(0xff919AAA),
),
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.0),
borderSide: BorderSide(
color: AppColors.textFieldColor,
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.0),
borderSide: BorderSide(
color: AppColors.textFieldColor,
),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.0),
borderSide: BorderSide(
color: AppColors.red,
),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.0),
borderSide: BorderSide(
color: AppColors.red,
),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.0),
borderSide: BorderSide(
color: AppColors.textFieldColor,
),
),
floatingLabelBehavior: FloatingLabelBehavior.never,
suffixIcon: IconButton(
onPressed: () {
Provider.of<LoginProvider>(context, listen: false)
.toggleObs();
},
icon: Provider.of<LoginProvider>(context,
listen: false)
.switchObsIcon,
),
labelText: 'Password',
errorStyle: TextStyle(color: AppColors.red),
hintStyle: TextStyle(
color: Color(0xff919AAA),
),
),
),
//passwordTextFormField(),
SizedBox(height: _height! / 30.0),
///password visibility handle by provider state management
TextFormField(
controller: confirmPasswordController,
validator: (value) {
if (value!.isEmpty) {
return "Please Enter Password!";
} else if (value.length < 6) {
return "Please Enter more than 6 digit .";
} else {
return null;
}
},
obscureText:
Provider.of<LoginProvider>(context, listen: false)
.isConfirmPassword,
keyboardType: TextInputType.emailAddress,
autofillHints: [AutofillHints.email],
cursorColor: AppColors.black,
style: TextStyle(
color: Color(0xff919AAA),
),
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.0),
borderSide: BorderSide(
color: AppColors.textFieldColor,
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.0),
borderSide: BorderSide(
color: AppColors.textFieldColor,
),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.0),
borderSide: BorderSide(
color: AppColors.red,
),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.0),
borderSide: BorderSide(
color: AppColors.red,
),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.0),
borderSide: BorderSide(
color: AppColors.textFieldColor,
),
),
floatingLabelBehavior: FloatingLabelBehavior.never,
suffixIcon: IconButton(
onPressed: () {
Provider.of<LoginProvider>(context, listen: false)
.toggleObsData();
},
icon: Provider.of<LoginProvider>(context,
listen: false)
.switchObsIcons,
),
labelText: 'Confirm Password',
errorStyle: TextStyle(color: AppColors.red),
hintStyle: TextStyle(
color: Color(0xff919AAA),
),
),
),
],
),
),
),
SizedBox(height: _height! / 28),
SizedBox(height: _height! / 22),
submitButton(),
SizedBox(height: _height! / 35),
],
),
),
),
);}
),
),
);
}
///app-text Widget is used for app logo and icon in top side
Widget appText() {
return Container(
width: _width! * 0.90,
child: Column(
children: <Widget>[
Image.asset(
"assets/traveling-text-icon.png",
height: 60,
),
SizedBox(
height: 5,
),
],
),
);
}
///for validation we used a submit button
Widget submitButton() {
return Card(
elevation: 20.0,
shadowColor: Colors.blue[100],
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20.0))),
child: Container(
height: 60,
width: _width! * .85,
decoration: BoxDecoration(
// boxShadow: [BoxShadow(color: AppColors.grey, blurRadius: 20.0)],
borderRadius: BorderRadius.circular(20.0),
gradient: LinearGradient(colors: [
AppColors.blue,
Colors.blue.shade900,
])),
child: MaterialButton(
onPressed: () {
if(passwordController.text==confirmPasswordController.text){
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (context) => EmployeeBottomNavBar()));}
else{
print("password did not match");
}
},
child: Text(
AppStrings.submit,
style: TextStyle(
color: Colors.white, fontSize: 14, fontWeight: FontWeight.bold),
),
),
),
);
}
}
////provider class
import 'package:flutter/material.dart';
import 'package:traveling/helpers/AppColors.dart';
class LoginProvider extends ChangeNotifier {
bool _isTrue = true;
bool _isConfirmPassword = true;
bool get isTrue => _isTrue;
bool get isConfirmPassword => _isConfirmPassword;
get switchObsIcons {
return _isConfirmPassword ? Icon(Icons.visibility_off,color: AppColors.textFieldTextColor,) : Icon(Icons.visibility,color: AppColors.textFieldTextColor,);
}
get switchObsIcon {
return _isTrue ? Icon(Icons.visibility_off,color: AppColors.textFieldTextColor,) : Icon(Icons.visibility,color: AppColors.textFieldTextColor,);
}
void toggleObsData() {
_isConfirmPassword = !_isConfirmPassword;
notifyListeners();
}
void toggleObs() {
_isTrue = !_isTrue;
notifyListeners();
}
}

Validating 2 things for TextFormField

I have a textformfield which validates min length to be at least 3 characters. Later on, I'll validate with backend that the username is unique.
But currently, I'm having trouble showing 2 error text for 2 errors. Namely, one for min length ( "Please enter at least 3 characters for your username") and one for non-unique username ('Your username is popular, please try another one.')
Questions:
How to make the suffix icon appear only when at least 1 character is typed? instead of by default, I know it's linked to hasMinLengthUnique = false.
How to show different error text for respective errors?
And later on, how to put a ternary operator on the navigation to another page based on value hasMinLengthUnique = true.
Bcos right now, whether hasMinLengthUnique = true or false, the navigation doesn't happen.
Form(
key: _formKey,
autovalidateMode: AutovalidateMode.always,
child: TextFormField(
controller: _controller,
validator: (value) {
return (0 < value.length && value.length < 3)
? "Please enter at least 3 characters for your username"
: null;
},
onChanged: (value) {
setState(() {
value.length > 2
// && username must be unique
? hasMinLengthUnique = true
: hasMinLengthUnique = false;
});
},
style: TextStyle(color: Colors.white),
autofocus: true,
maxLength: 15,
decoration: InputDecoration(
suffix: hasMinLengthUnique
? IconButton(
icon:
Icon(Icons.check_circle, color: Colors.green))
: IconButton(
icon: Icon(Icons.cancel, color: Colors.red)),
errorBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.blue, width: 1.0),
),
errorStyle: TextStyle(color: Color(0xff4aa3f8)),
focusedErrorBorder: UnderlineInputBorder(
borderSide: BorderSide.none,
),
border: OutlineInputBorder(),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(15)),
// borderSide: BorderSide(width: 1, color: Colors.white),
),
),
),
),
),
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.18,
),
Padding(
padding: EdgeInsets.only(
right: MediaQuery.of(context).size.height * 0.015,
),
child: DelayedDisplay(
delay: Duration(seconds: 3),
child: Align(
alignment: Alignment.centerRight,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
onPrimary: Colors.white,
primary: Color(0xff3a327f)),
child: Icon(Icons.chevron_right, size: 27),
onPressed: () async {
// if (formKey.currentState.validate()) {
Navigator.push(context, _createRoute());
// }
})),
))
]),
));
Here is the code
It checks whether a username is greater than 2 or not
Then it will check whether your username is popular or not (try typing admin)
It will update your hasMinLengthUnique accordingly that will update your UI of IconButton()
It will update your ElevatedButton() as well. It becomes disable if hasMinLengthUnique is false and become enable if hasMinLengthUnique is true.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool hasMinLengthUnique = false;
var _controller = TextEditingController();
GlobalKey<FormState> _formKey = GlobalKey();
var defUsername = ["admin"];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Container(
color: Colors.lightBlue[900],
child: Column(
children: [
Form(
key: _formKey,
autovalidateMode: AutovalidateMode.always,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
controller: _controller,
validator: (value) {
if (value.length < 3) {
return "Please enter at least 3 characters for your username";
}
if (value.contains(defUsername[0])) {
return "Username is too popular";
}
return null;
},
onChanged: (value) {
setState(() {
if (value.contains(defUsername[0]) ||
value.length <= 2) {
hasMinLengthUnique = false;
} else {
hasMinLengthUnique = true;
}
});
},
style: TextStyle(color: Colors.white),
autofocus: true,
maxLength: 15,
decoration: InputDecoration(
contentPadding:
EdgeInsets.symmetric(vertical: 0, horizontal: 10),
labelText: "Username",
suffix: hasMinLengthUnique
? Icon(Icons.check_circle, color: Colors.green)
: _controller.text.isEmpty
? Icon(null, color: Colors.red)
: Icon(Icons.cancel, color: Colors.red),
border: OutlineInputBorder(),
),
),
),
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.18,
),
Padding(
padding: EdgeInsets.only(
right: MediaQuery.of(context).size.height * 0.015,
),
child: Container(
child: Align(
alignment: Alignment.centerRight,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
onPrimary: Colors.white, primary: Color(0xff3a327f)),
child: Icon(Icons.chevron_right, size: 27),
onPressed: hasMinLengthUnique
? () {
print("go to next screen");
}
: null,
),
),
),
)
],
),
),
),
);
}
}
Thank you!
Have you tried if else statement in onChanged Value
var isValidate;
onChanged(){
if(1st condition){
setState(){}
}
else if(2nd condition){
setState(){}
}
}

Comment Box as Facebook in flutter

Here is my code
TextField(
controller: commentController,
maxLines: 3,
selectionHeightStyle: BoxHeightStyle.tight,
decoration: new InputDecoration(
hintText: 'Write a Comment',
hintStyle: new TextStyle(
color: Colors.grey,
),
prefixIcon: InkWell(
child: Icon(Icons.camera_alt),
onTap: () {
chooseImage();
},
),
suffixIcon: InkWell(
child: Icon(
Icons.send,
),
onTap: () {
if (filePickedName == 'nofile') {
insertMethod();
commentController.clear();
_fleshScreen();
getCommentData();
} else {
upload();
commentController.clear();
_fleshScreen();
getCommentData();
}
},
)),
style: new TextStyle(
color: Colors.black,
),
),
I want to create as this box with ImageView
facebook comment multimedia box
let me give you a widget for that
class CommentBox extends StatefulWidget {
final Widget image;
final TextEditingController controller;
final BorderRadius inputRadius;
final Function onSend,onImageRemoved;
const CommentBox({Key key, this.image, this.controller, this.inputRadius, this.onSend , this.onImageRemoved }) : super(key: key);
#override
_CommentBoxState createState() => _CommentBoxState();
}
class _CommentBoxState extends State<CommentBox> {
Widget image;
#override
void initState() {
image = widget.image;
super.initState();
}
#override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Divider(
height: 1,
color: Colors.grey[300],
thickness: 1,
),
const SizedBox(height: 20),
if (image != null)
_removable(
context,
_imageView(context),
),
if(widget.controller!=null) TextFormField(
controller: widget.controller,
decoration: InputDecoration(
suffixIcon: IconButton(
icon: Icon(Icons.send,color: Theme.of(context).primaryColor,),
onPressed: widget.onSend,
),
filled: true,
border: OutlineInputBorder(
borderSide: BorderSide.none,
borderRadius: widget.inputRadius ?? BorderRadius.circular(32),
),
),
),
],
);
}
Widget _removable(BuildContext context, Widget child) {
return Stack(
alignment: Alignment.topRight,
children: [
child,
IconButton(
icon: Icon(Icons.clear),
onPressed: () {
setState(() {
image = null;
widget.onImageRemoved();
});
},
)
],
);
}
Widget _imageView(BuildContext context) {
return Padding(
padding: EdgeInsets.all(16),
child: ClipRRect(
borderRadius: BorderRadius.circular(16),
child: image,
),
);
}
}
USE IT LIKE ANY WIDGET
MaterialApp(
home: Scaffold(
body: SafeArea(
child: Column(
children: [
SizedBox(height: 128,),
Spacer(),
CommentBox(
image: Image.asset(
"assets/svg/barber.svg",
height: 64,
width: 64,
),
controller: TextEditingController(),
onImageRemoved: (){
//on image removed
},
onSend: (){
//on send button pressed
},
),
],
),
),
),
)

raised button does not shows answer until I select a drop down item even after assigning a default value

I was making a simple S.I Calculator which has a field for principal amount intrest, and time along with that i have a dropdown to select the currency.
Problem is when I press 'calculate' RaisedButton(looking at the image might help) nothing appears on screen (Initially I thought there is problem with buttton but later ) I found out that after pressing RaisedButton if I selected any item from dropdown then answer appears why is this happening, I have set an inital value as _selected = 'Rupee' am I doing something wrong?.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Simple Intrest Calculator',
home: MyHomePage(),
theme: ThemeData(
brightness: Brightness.dark,
primaryColor: Colors.indigo,
accentColor: Colors.indigoAccent,
),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var _currencies = ['Rupee', 'Dollar', 'Pound'];
final _minPadding = 5.0;
var _selected = 'Rupee';
TextEditingController principalCntr = TextEditingController();
TextEditingController roiCntr = TextEditingController();
TextEditingController termCntr = TextEditingController();
String _amount = '0';
#override
Widget build(BuildContext context) {
TextStyle styles = Theme.of(context).textTheme.headline6;
return Scaffold(
//resizeToAvoidBottomPadding: false,
appBar: AppBar(
title: Text('S.I Calculator'),
centerTitle: true,
),
body: Container(
margin: EdgeInsets.symmetric(vertical: 0, horizontal: _minPadding * 2),
child: ListView(
children: [
getImg(),
Padding(
padding: const EdgeInsets.symmetric(vertical: 5),
child: TextField(
controller: principalCntr,
keyboardType: TextInputType.number,
style: styles,
decoration: InputDecoration(
labelText: 'Principal',
hintText: 'Enter principal amount',
labelStyle: styles,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0),
),
),
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 5),
child: TextField(
controller: roiCntr,
keyboardType: TextInputType.number,
style: styles,
decoration: InputDecoration(
labelText: 'Intrest',
hintText: 'Enter intrest rate',
labelStyle: styles,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0),
),
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Expanded(
child: TextField(
controller: termCntr,
keyboardType: TextInputType.number,
style: styles,
decoration: InputDecoration(
labelText: 'Time',
hintText: 'Time in years',
labelStyle: styles,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0),
),
),
),
),
SizedBox(width: 50,),
Expanded(
child: DropdownButton(
value: _selected,
onChanged: (newVal) {
setState(() {
_selected = newVal;
});
},
items: _currencies.map((selectedVal) {
return DropdownMenuItem(
value: selectedVal,
child: Text(selectedVal),
);
}).toList(),
),
),
],
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Expanded(
child: RaisedButton(
color: Theme.of(context).accentColor,
textColor: Theme.of(context).primaryColor,
child: Text('Calculate'),
onPressed: (){
_amount = _calculateReturns();
},
),
),
SizedBox(width: 20),
Expanded(
child: RaisedButton(
color: Theme.of(context).primaryColorDark,
textColor: Theme.of(context).primaryColorLight,
child: Text('Clear', style: TextStyle(fontSize: 20,),),
onPressed: (){
debugPrint('pressed');
},
),
),
],
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(_amount, style: styles,),
),
],
),
),
);
}
String _calculateReturns(){
double principal = double.parse(principalCntr.text);
double roi = double.parse(roiCntr.text);
double year = double.parse(termCntr.text);
double sI = principal + (principal*roi*year)/100;
String res = 'After $year years, you get $sI';
return res;
}
Widget getImg() {
AssetImage img = AssetImage('images/money.jpg');
Image image = Image(image: img, width: 125, height: 125);
return Container(
child: image,
margin: EdgeInsets.all(_minPadding * 10),
);
}
}
This is after i click Raised Button
This is after i select an item from dropdown but do not click on the button again:
Code walkthrough:
made a list of _currencies.
added textinput fields dropdown button and two raised buttons.
when calculate button is pressed _calculateReturns() is called which returns a value and stores it in _amount
Output is just a Text widget.
you forgot to update the screen when pressing on the button, remember every time you need to change the content of the page or update it you have to call the method :
setState(() {
// code here for values to be updated
});
so in your onPressed function of Raised button you have to add it like that :
onPressed: (){
_amount = _calculateReturns();
setState(() { });
}

Flutter bottom sheet changing background heigth

I am using bottom sheet in my app but its changing the background screen height. I need my background page fixed. And need to increase bottom sheet height
Here is my bottom sheet code
import "package:flutter/material.dart";
import 'package:flutter/services.dart';
import 'package:flutter/cupertino.dart';
import 'dart:io';
class addQuestion extends StatefulWidget {
#override
_addQuestionState createState() => _addQuestionState();
}
class _addQuestionState extends State<addQuestion> {
void _submitData(){
Navigator.of(context).pop();
}
#override
Widget build(BuildContext context) {
double stackHeight = (MediaQuery.of(context).size.height);
return Container(
decoration: BoxDecoration(
color: Color(0xff404040),
borderRadius: BorderRadius.only(topLeft: Radius.circular(15.0), topRight: Radius.circular(15.0))
),
child: SingleChildScrollView(
child: Card(
elevation: 5,
color: Color(0xff404040),
child: Container(
padding: EdgeInsets.only(top: 10, left: 10, right:10,
bottom: MediaQuery.of(context).viewInsets.bottom + 10 ,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
TextField(
maxLength: 56,
style: TextStyle(
color: Colors.white,
),
textAlign: TextAlign.center,
decoration: InputDecoration(
counterText: '',
labelText: 'Would Question',
labelStyle: TextStyle(
color: Colors.blue
),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.blue),
),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.blue),
),
),
onSubmitted: (_) => _submitData(),
),
TextField(
maxLength: 56,
style: TextStyle(
color: Colors.white,
),
textAlign: TextAlign.center,
decoration: InputDecoration(
counterText: '',
labelText: 'Rather Question',
labelStyle: TextStyle(
color: Colors.red
),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.red),
),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.red),
),
),
keyboardType: TextInputType.number,
onSubmitted: (_) => _submitData(),
),
RaisedButton(onPressed: () {
_submitData();
}, child: Text('Add Question', style: TextStyle(
color: Colors.white
),),color: Theme.of(context).primaryColor,
),
],
),
),
),
),
);
}
}
As you see when keyboard open the background page is moving on the upside. And in rounded orders of bottom sheet, it's showing white corner don't know why its showing the need to transparent or remove this.
There are two kinds of bottom sheets in material design:
Persistent. A persistent bottom sheet shows information that supplements the primary content of the app. A persistent bottom sheet remains visible even when the user interacts with other parts of the app. Persistent bottom sheets can be created and displayed with the ScaffoldState.showBottomSheet function or by specifying the Scaffold.bottomSheet constructor parameter.
Modal. A modal bottom sheet is an alternative to a menu or a dialog and prevents the user from interacting with the rest of the app. Modal bottom sheets can be created and displayed with the showModalBottomSheet function.
showBottomSheet method
class MyStatelessWidget extends StatelessWidget {
MyStatelessWidget({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Center(
child: RaisedButton(
child: const Text('showBottomSheet'),
onPressed: () {
Scaffold.of(context).showBottomSheet<void>(
(BuildContext context) {
return Container(
height: 200,
color: Colors.amber,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const Text('BottomSheet'),
RaisedButton(
child: const Text('Close BottomSheet'),
onPressed: () => Navigator.pop(context),
)
],
),
),
);
},
);
},
),
);
}
}
**showModalBottomSheet function **
class MyStatelessWidget extends StatelessWidget {
MyStatelessWidget({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Center(
child: RaisedButton(
child: const Text('showModalBottomSheet'),
onPressed: () {
showModalBottomSheet<void>(
context: context,
builder: (BuildContext context) {
return Container(
height: 200,
color: Colors.amber,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const Text('Modal BottomSheet'),
RaisedButton(
child: const Text('Close BottomSheet'),
onPressed: () => Navigator.pop(context),
)
],
),
),
);
},
);
},
),
);
}
}
The BottomSheet widget itself is rarely used directly. Instead, prefer to create a persistent bottom sheet with ScaffoldState.showBottomSheet or Scaffold.bottomSheet, and a modal bottom sheet with showModalBottomSheet.