Flutter application development problems and fixes

Kadir Bekar
3 min readFeb 4, 2023

--

Hi everyone,

In this article, I will be sharing the problems and their fixes that I’ve faced during flutter application development.

For this purpose I’ll create a Github repository so that If you would like to add your custom solutions, it is really nice to have them in the same place.

TL;DR -> https://github.com/kadirbekar/flutter_problems_fixes

1- For all around the application, touch empty place on the screen and close keyboard

Let’s image a view where we have textfields and some random images. They cover the most part of the screen therefore there are little empty spaces left on the screen where we can touch.

When we tap on any textfield, keyboard pops up. For some reason if you would like to close keyboard, we are able to press on back button for Androids but for iPhones it is not that easy. There are some packages for displaying icons on top of keyboard for closing keyboard or you can implement your own solution with Stack widget for putting icons to top of keyboard and give the functionality. They are all fine but at some point it may not fit to your design.

But with the following code, you will be able to close the keyboard whenever you tap on any empty portion of the application without using any package.


// Adding custom CloseKeyboard widget in main.dart file.

return const CloseKeyboard(
child: MaterialApp(
home: CloseKeyboardDummyView(),
),
);


// Custom widget.
class CloseKeyboard extends StatelessWidget with SystemChannelsMethods {
const CloseKeyboard({
Key? key,
required this.child,
}) : super(key: key);

final Widget child;

@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => closeKeyboard(),
child: child,
);
}
}


// closeKeyboard functionality.
mixin SystemChannelsMethods {
void closeKeyboard() =>
SystemChannels.textInput.invokeMethod(_SystemChannels.textInputHide);
}

class _SystemChannels {
_SystemChannels._();

static const textInputHide = 'TextInput.hide';
}


// I've tried
FocusManager.instance.primaryFocus?.unfocus()
FocusScope.of(context).unfocus()
but didn't worked as expected for all around the application. FYI.

2- Keyboard safe widget

As our design needs, we may need to put some widgets at the bottom of the screen. Moreover, somehow when we pops up keyboard, the widgets that we’ve put at the bottom, they might be invisible behind keyboard. Because of this problem, we could use the following codes.

//  Custom widget

class KeyboardSafeWidget extends StatelessWidget {
const KeyboardSafeWidget({
Key? key,
required this.child,
}) : super(key: key);

final Widget child;

@override
Widget build(BuildContext context) {
return Padding(
padding: MediaQuery.of(context).viewInsets,
child: child,
);
}
}

// Usage

class KeyboardSafeDummyView extends StatelessWidget {
const KeyboardSafeDummyView({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
return Scaffold(
...
bottomNavigationBar: KeyboardSafeWidget(
child: Card(
child: TextFormField(
decoration: const InputDecoration(
border: OutlineInputBorder(),
hintText: 'Message',
),
),
),
),
);
}
}

3- Save user information (Login, address, payment etc.)

In most applications, we generally fill form information such as login, address, credit card etc. Instead of let users to enter same information again, for users, we can enable autofill services.

For using autofill service in real scenarios or testing purposes, looking at this article would be helpful.

I had seen autofilling options successfully when I signed in to my gmail account. FYI

        //  Usage

AutofillGroup(
child: Form(
key: _loginFormKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
_TextFormField(
controller: _emailController,
hintText: 'Email',
autofillHints: const [AutofillHints.email],
keyboardType: TextInputType.emailAddress,
),
_TextFormField(
controller: _passwordController,
hintText: 'Password',
autofillHints: const [AutofillHints.password],
textInputAction: TextInputAction.done,
keyboardType: TextInputType.text,
obscureText: true,
onEditingComplete: () =>
TextInput.finishAutofillContext(),
),
ElevatedButton(
onPressed: () => _login(context: context),
child: const Text('Login'),
)
],
),
),
)

4- Preserve tab state

In some of our screens, we have some operations such as taking photo with camera, incrementing counts etc.

In these cases, when we have saved values in our current state (took image with camera, incremented some numbers) and change the current tab to another one, we lost our previous state. For this, we use AutomaticKeepAliveClientMixin not to lose previous view’s state.

This mixin using with StatefulWidgets.

//  Usage

// Adding mixin
class _ViewState extends State<_View> with AutomaticKeepAliveClientMixin

// Override build method
@override
Widget build(BuildContext context) {
super.build(context)

// This must be true
bool get wantKeepAlive => true;

--------------------------------------

// Example view

part of '../tabbar_view.dart';

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

@override
State<_HomeView> createState() => _HomeViewState();
}

class _HomeViewState extends State<_HomeView>
with AutomaticKeepAliveClientMixin {
int _count = 0;

@override
Widget build(BuildContext context) {
super.build(context);
return Stack(
alignment: Alignment.center,
children: [
Text('Count: $_count'),
Positioned(
right: 20,
bottom: 20,
child: FloatingActionButton(
child: const Icon(Icons.add),
onPressed: () => setState(() => _count++),
),
),
],
);
}

@override
bool get wantKeepAlive => true;
}

--

--