Home > OS >  Flutter prevent keyboard from hiding TextField on tap in Dialog
Flutter prevent keyboard from hiding TextField on tap in Dialog

Time:12-22

I have a Dialog containing TextFields and when I tap on one of the fields lower down the list the keyboard pops up, causes the Dialog to resize and the tapped TextField is no longer visible. I would like the tapped TextField to be scrolled in to view.

So far I've tried the following without luck:

  • Making sure the android manifest doesn't declare the app as full screen (e.g. https://stackoverflow.com/a/62131025/2086746).
  • Adding a Scaffold to the Dialog and changing the resizeToAvoidBottomInset value.
  • Using MediaQuery to add an extra bottom padding when the keyboard is visible.

Example app demonstrating the issue:

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: Builder(
            builder: (context) => TextButton(
              child: const Text("Open dialog"),
              onPressed: () {
                showDialog(context: context, builder: (_) => _dialog());
              },
            ),
          ),
        ),
      ),
    );
  }

  Widget _dialog() {
    return Dialog(
      child: SingleChildScrollView(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Container(height: 200, color: Colors.red),
            const TextField(decoration: InputDecoration(hintText: 'TF 1')),
            const TextField(decoration: InputDecoration(hintText: 'TF 2')),
            const TextField(decoration: InputDecoration(hintText: 'TF 3')),
            const TextField(decoration: InputDecoration(hintText: 'TF 4')),
            const TextField(decoration: InputDecoration(hintText: 'TF 5')),
            const TextField(decoration: InputDecoration(hintText: 'TF 6')),
            const TextField(decoration: InputDecoration(hintText: 'TF 7')),
            Container(height: 200, color: Colors.blue),
          ],
        ),
      ),
    );
  }
}

CodePudding user response:

It looks like I finally find the solution myself. As I mention in my question I had already tried adding a Scaffold to the Dialog without success, however I was placing the Scaffold inside the Dialog. I've now tried placing the Dialog inside the Scaffold and the problem is solved. One side-effect is that the Dialog is no longer dismissible but this can be fixed by wrapping the Scaffold in a GestureDetector and manually dismissing. The full working code is now:

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

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

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: Builder(
            builder: (context) => TextButton(
              child: const Text("Open dialog"),
              onPressed: () {
                showDialog(
                  context: context,
                  builder: (context) => _dialog(context),
                  barrierDismissible: true,
                );
              },
            ),
          ),
        ),
      ),
    );
  }

  Widget _dialog(BuildContext context) {
    return GestureDetector(
      onTap: () {
        Navigator.of(context).pop();
      },
      child: Scaffold(
        backgroundColor: Colors.transparent,
        body: Dialog(
          child: SingleChildScrollView(
            child: Column(
              mainAxisSize: MainAxisSize.min,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Container(height: 200, color: Colors.red),
                const TextField(decoration: InputDecoration(hintText: 'TF 1')),
                const TextField(decoration: InputDecoration(hintText: 'TF 2')),
                const TextField(decoration: InputDecoration(hintText: 'TF 3')),
                const TextField(decoration: InputDecoration(hintText: 'TF 4')),
                const TextField(decoration: InputDecoration(hintText: 'TF 5')),
                const TextField(decoration: InputDecoration(hintText: 'TF 6')),
                const TextField(decoration: InputDecoration(hintText: 'TF 7')),
                Container(height: 200, color: Colors.blue),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

CodePudding user response:

For that, you need to remove SingleChildScrollView. Also, you can try to make TextFields slimmer using isDense:true. If it doesn't help you can create dialog as a new screen.

  • Related