Want to add login button only when user input credentials

I want to make the login button visible only when user enter the credentials in Text Form Field (Email and Password), otherwise login button should be invisible.

LoginPage

My LoginPage is designed as below:-

class _LoginPageState extends State<LoginPage> {
final _formKey = GlobalKey<FormState>();
late String _email, _password, error = '';
bool _obscureText = true;
bool _isKeyboardVisible = true;
bool _canShowButton = true;
final AuthenticationService _authenticationService = AuthenticationService();
_hideWidget(){
setState(() {
_canShowButton = !_canShowButton;
});
}
_toggle() {
setState(() {
_obscureText = !_obscureText;
});
}
_submit() async {
if(_formKey.currentState!.validate()){
_formKey.currentState?.save();
dynamic result = await _authenticationService.loginWithEmail(email: _email, password: _password);
if(result == null) {
setState(() => error = 'Es wurde kein Benutzerkonto gefunden. Bitte erstellen Sie zuerst das Konto');
} else {
Navigator.pushNamed(context, HomePage.id);
}
print(_email);
print(_password);
}
}
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
_isKeyboardVisible = MediaQuery.of(context).viewInsets.bottom != 0;
if(!_isKeyboardVisible) {
return GestureDetector(
onTap: (){
FocusScopeNode currentFocus = FocusScope.of(context);
if(!currentFocus.hasPrimaryFocus){
currentFocus.unfocus();
}
},
child: Scaffold(
resizeToAvoidBottomInset: false,
backgroundColor: Colors.white,
body: SingleChildScrollView(
child: Column(
children: [
Container(
margin: EdgeInsets.only(top: 20),
alignment: Alignment.center,
child: Text("Bitte Melde Dich an",
style: TextStyle(color: color, fontWeight: FontWeight.bold, fontSize: 28),),
),
Form(
key: _formKey,
autovalidateMode: AutovalidateMode.onUserInteraction,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(horizontal: 30.0, vertical: 10.0),
child: Padding(
padding: EdgeInsets.only(left: 5.0, right: 5.0, top: 5.0),
child: SizedBox(
child: TextFormField(
autofocus: false,
decoration: InputDecoration(
labelText: 'Email',
border: OutlineInputBorder(borderRadius: BorderRadius.all(
const Radius.circular(10.0),
)
),
filled: true,
fillColor: Colors.white,
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: color, width: 2.0),
borderRadius: BorderRadius.circular(10.0)
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: color, width: 2.0),
borderRadius: BorderRadius.circular(10.0)
)
),
validator: (input) => !EmailValidator.validate(input!, true)
? 'Please enter valid email'
: null,
onSaved: (input) => _email = input!,
),
),
),
),
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 30.0, vertical: 10.0
),
child: Padding(
padding: const EdgeInsets.only(left: 5, right: 5, top: 5, bottom: 5),
child: Stack(
alignment: const Alignment(0, 0),
children: <Widget>[
TextFormField(
autofocus: false,
decoration: InputDecoration(
labelText: 'Password',
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
const Radius.circular(10.0)
)
),
filled: true,
fillColor: Colors.white,
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: color, width: 2.0),
borderRadius: BorderRadius.circular(10.0)
),
suffixIcon: IconButton(
onPressed: (){
_toggle();
},
icon: Icon(_obscureText ? Icons.visibility : Icons.visibility_off)
)
),
validator: (input) => input!.length < 6
? 'Must be at least 6 characters': null,
onSaved: (input) => _password = input!,
obscureText: _obscureText,
)
],
),
),
),
Padding(
padding: const EdgeInsets.only(top: 10),
child: Container(
width: MediaQuery.of(context).size.width - 70,
height: MediaQuery.of(context).size.height * 0.09,
child: !_canShowButton ? SizedBox.shrink() : TextButton(
style: TextButton.styleFrom(
primary: Colors.white,
backgroundColor: color,
elevation: 5,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10.0))
),
onPressed: () {
_hideWidget();
},
child: Text('Anmelden')),
),
),
],
),
)
],
),
),
),
);
} else {
return GestureDetector(
onTap: (){
FocusScopeNode currentFocus = FocusScope.of(context);
if(!currentFocus.hasPrimaryFocus){
currentFocus.unfocus();
}
},
child: Scaffold(
resizeToAvoidBottomInset: false,
body: SingleChildScrollView(
child: Column(
children: [
Container(
margin: EdgeInsets.only(top: 60),
alignment: Alignment.center,
child: Text(
'Login Credentials',
style: TextStyle(color: color, fontWeight: FontWeight.bold, fontSize: 28),
overflow: TextOverflow.clip,
)
),
Container(
margin: EdgeInsets.only(top: 20),
alignment: Alignment.center,
child: Text("Bitte Melde Dich an",
style: TextStyle(color: color, fontWeight: FontWeight.bold, fontSize: 28),),
),
Form(
key: _formKey,
autovalidateMode: AutovalidateMode.onUserInteraction,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(horizontal: 30.0, vertical: 10.0),
child: Padding(
padding: EdgeInsets.only(left: 5.0, right: 5.0, top: 5.0),
child: SizedBox(
/*height: _animation.value,*/
child: TextFormField(
decoration: InputDecoration(
labelText: 'Email',
border: OutlineInputBorder(borderRadius: BorderRadius.all(
const Radius.circular(10.0),
)
),
filled: true,
fillColor: Colors.white,
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: color, width: 2.0),
borderRadius: BorderRadius.circular(10.0)
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: color, width: 2.0),
borderRadius: BorderRadius.circular(10.0)
)
),
// focusNode: _focusNode,
validator: (input) => !EmailValidator.validate(input!, true) ? 'Please provide valid email':null,
onSaved: (input) => _email = input!,
),
),
),
),
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 30.0, vertical: 10.0
),
child: Padding(
padding: const EdgeInsets.only(left: 5, right: 5, top: 5, bottom: 5),
child: Stack(
alignment: const Alignment(0, 0),
children: <Widget>[
TextFormField(
decoration: InputDecoration(
labelText: 'Password',
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
const Radius.circular(10.0)
)
),
filled: true,
fillColor: Colors.white,
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: color, width: 2.0),
borderRadius: BorderRadius.circular(10.0)
),
suffixIcon: IconButton(
onPressed: (){
_toggle();
},
icon: Icon(_obscureText ? Icons.visibility : Icons.visibility_off)
)
),
validator: (input) => input!.length < 6
? 'Must be at least 6 characters': null,
onSaved: (input) => _password = input!,
obscureText: _obscureText,
)
],
),
),
),
],
),
)
],
),
),
),
);

In short I have added the bool variable and function as below. After that in onPressed of login Button I called _hideWidget().

bool _canShowButton = true;
_hideWidget(){
setState(() {
_canShowButton = !_canShowButton;
}); 
Padding(
padding: const EdgeInsets.only(top: 10),
child: Container(
width: MediaQuery.of(context).size.width - 70,
height: MediaQuery.of(context).size.height * 0.09,
child: !_canShowButton ? SizedBox.shrink() : TextButton(
style: TextButton.styleFrom(
primary: Colors.white,
backgroundColor: color,
elevation: 5,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10.0))
),
onPressed: () {
_hideWidget();
},
child: Text('Anmelden')),
),
),

What I have achieved is: The Login Button is there on the page and when I click on TextFormField it gets disappear.

Want to achieve: Login Button should be invisible on the screen and when user enters the credentials after that it should appear.

Is there any way to achieve this??

Answer

This is how you can tell if there’s data in the textfield or not, if there is it’ll change isFilled to true.

bool isFilled = false;
TextFormField(
onChanged: (val) {
setState(() {
(val.isEmpty) ? isFilled = false : isFilled = true;
});
},
)

Now to show the button when there’s data in the textfield you can use ternary operator.

(isFilled)?TextButton(onPressed: (){}, child: Container()) : Container()

Just switch TextButton with your button. Ternary operators work like so

(condition) ? (do if true) : (do if false)

in this case, you’re showing the button if isFilled = true, and an empty container if not