listener – Detecting(Reading) Keyborad Keys on Flutter Desktop App Development

I’m working on a desktop application for Windows with Flutter. I want to listen to keyboard keys. I made a Login page and it has two TextFormFields, (one for Username and the other for Password). When I press the ‘enter’ key on the keyboard, I want the form to be submitted as I pressed on the ‘Login’ button. So if I pressed the ‘enter’ key from either Username or Password text fields, I want the app to act exactly as if I pressed the ‘Login’ Button.

Here is a picture of the Login Page: –> Login Page

Here is the code of Login Page:

import 'package:flutter/material.dart';
import '../../api/services/login_services.dart';
import '../../api/models/login_models.dart';
import '../../constants/constant_methods.dart';
import '../main_page/main_screen.dart';
import '../../constants/constant_variables.dart';

class LoginPage extends StatefulWidget {
  const LoginPage({Key? key}) : super(key: key);

  @override
  _LoginPageState createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
TextEditingController usernameController = TextEditingController();
TextEditingController passwordController = TextEditingController();
late LoginRequestModel loginRequestModel;
bool isUsernameEmpty = false;
bool isPasswordEmpty = false;
bool secure = true;
bool notSecure = false;
bool isLoading = false;

@override
void initState() {
  super.initState();
  loginRequestModel = LoginRequestModel(
    usernameController.text,
    passwordController.text,
  );
}

@override
Widget build(BuildContext context) {
  return SafeArea(
    child: Scaffold(
      body: Container(
        height: MediaQuery.of(context).size.height,
        width: MediaQuery.of(context).size.width,
        decoration: const BoxDecoration(
          gradient: loginPageGradient,
        ),
        child: Center(
          child: SingleChildScrollView(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.center,
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Image.asset(
                  'assets/images/cloud_soft_logo.png',
                  height: 90,
                ),
                const SizedBox(height: 15),
                Text(
                  'Hoomy's Real Estate',
                  style: Theme.of(context).textTheme.headline4,
                ),
                const SizedBox(height: 20),
                Container(
                  width: 310,
                  decoration: BoxDecoration(
                  color: Colors.white,
                  borderRadius: borderRadius(10.0),
                  ),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.center,
                    children: [
                      const SizedBox(height: 20),
                      Text(
                        'Welcome',
                        style: Theme.of(context)
                            .textTheme
                            .headline6!
                            .copyWith(
                                fontWeight: FontWeight.w600,
                                foreground: Paint()..shader = linearGradient),
                      ),
                      Text(
                        'Please Log in to Your Account',
                        style: Theme.of(context).textTheme.headline2,
                      ),
                      const SizedBox(height: 10),
                      loginTextField("Username", "Username can't be empty",
                          usernameController),
                      loginTextField("Password", "Password can't be empty",
                          passwordController),
                      forgetPasswordButton(),
                      loginButton(context),
                      const SizedBox(height: 40),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    ),
  );
}

Widget loginTextField(
  String labelText,
  String errorText,
  TextEditingController controller,
) {
  return SizedBox(
    width: 250,
    child: TextFormField(
      decoration: InputDecoration(
        labelText: labelText,
        errorText: labelText == "Username"
            ? isUsernameEmpty
                ? errorText
                : null
            : isPasswordEmpty
                ? errorText
                : null,
        suffixIcon: labelText == "Username"
             ? IconButton(
                onPressed: () {}, icon: const Icon(Icons.person, size: 20))
            : IconButton(
                onPressed: () {
                  setState(() {
                    secure = !secure;
                  });
                },
                icon: Icon(
                  secure ? Icons.visibility_off : Icons.visibility,
                  size: 20,
                ),
              )),
      obscureText: labelText == "Username" ? notSecure : secure,
      controller: controller,
    ),
  );
 }

 Padding forgetPasswordButton() {
   return Padding(
     padding: const EdgeInsets.all(20).copyWith(right: 30),
     child: Row(
       mainAxisAlignment: MainAxisAlignment.end,
       children: [
         Theme(
           data: ThemeData(splashColor: Colors.transparent),
           child: TextButton(
             child: const Text('Forget Password'),
             onPressed: () {},
           ),
         ),
       ],
     ),
   );
 }

 DecoratedBox loginButton(BuildContext context) {
   return DecoratedBox(
     decoration: BoxDecoration(
       borderRadius: borderRadius(50.0),
       gradient: loginButtonGradient,
     ),
     child: ElevatedButton(
       style: ElevatedButton.styleFrom(
         primary: Colors.transparent,
         fixedSize: const Size(250, 50),
         shape: RoundedRectangleBorder(
           borderRadius: borderRadius(50.0),
       )),
       child: isLoading
         ? CircularProgressIndicator(
             color: Colors.blue[800],
             backgroundColor: Colors.grey,
           )
         : const Text('Login'),
       onPressed: () {
         setState(() {
           usernameController.text.isEmpty
              ? isUsernameEmpty = true
              : isUsernameEmpty = false;
           passwordController.text.isEmpty
              ? isPasswordEmpty = true
              : isPasswordEmpty = false;
         });
         setState(() {
           isLoading = true;
         });
         LoginService.login(usernameController.text, passwordController.text)
             .then((response) {
           setState(() {
             isLoading = false;
           });
           if (response) {
             Navigator.of(context).push(
               MaterialPageRoute(
                 builder: (context) => const MainScreen(),
               ),
             );
           } else if (!response &&
               usernameController.text.isNotEmpty &&
               passwordController.text.isNotEmpty) {
             showErrorDialog(context, "Invalid Username or Password!");
            }
         });
       }),
   );
 }

 Future<dynamic> showErrorDialog(BuildContext context, String dialogContent) {
   return showDialog(
    context: context,
    builder: (BuildContext context) {
      return Center(
        child: SingleChildScrollView(
          scrollDirection: Axis.vertical,
          child: SizedBox(
            width: 350,
            child: AlertDialog(
              backgroundColor: Colors.white,
              shape: RoundedRectangleBorder(borderRadius: borderRadius(10.0)),
              title: Text("Error",
                style: Theme.of(context)
                    .textTheme
                    .bodyText1!
                    .copyWith(color: Colors.red)),
              content: Text(dialogContent,
                style: Theme.of(context)
                    .textTheme
                    .headline2!
                    .copyWith(color: Colors.black87)),
              actions: <Widget>[
                TextButton(
                  child: Text("OK",
                    style: Theme.of(context)
                        .textTheme
                        .bodyText1!
                        .copyWith(color: Colors.blue)),
                  onPressed: () {
                    Navigator.of(context).pop();
                  },
                ),
              ],
            ),
          ),
        ),
      );
    },
  );
}
}

Leave a Comment