I have a Dialog
containing TextField
s 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 TextField
s slimmer using isDense:true
. If it doesn't help you can create dialog as a new screen.