Flutter AlertDialog with ListView and bottom TextField

5,522

You can copy paste run full code below
You can in content use SingleChildScrollView
code snippet

 content: SingleChildScrollView(
        child: Container(
          width: double.maxFinite,

working demo

enter image description here

full code

import 'package:flutter/material.dart';

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

class Exercise {
  String name;
  Exercise({this.name});
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  List<Exercise> exercises = [
    Exercise(name: 'A'),
    Exercise(name: 'B'),
    Exercise(name: 'C'),
    Exercise(name: 'D'),
    Exercise(name: 'E'),
    Exercise(name: 'F'),
    Exercise(name: 'G')
  ];
  int _selected;
  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return AlertDialog(
      title: Text(widget.title),
      shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.all(Radius.circular(20))),
      actions: <Widget>[
        FlatButton(
          child: const Text('CANCEL'),
          materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
          textColor: Theme.of(context).accentColor,
          onPressed: () {
            //widget.onCancel();
          },
        ),
        FlatButton(
          child: const Text('OK'),
          materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
          textColor: Theme.of(context).accentColor,
          onPressed: () {
            //widget.onOk();
          },
        ),
      ],
      content: SingleChildScrollView(
        child: Container(
          width: double.maxFinite,
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              Divider(),
              ConstrainedBox(
                constraints: BoxConstraints(
                  maxHeight: MediaQuery.of(context).size.height * 0.4,
                ),
                child: ListView.builder(
                    shrinkWrap: true,
                    itemCount: exercises.length,
                    itemBuilder: (BuildContext context, int index) {
                      return RadioListTile(
                          title: Text(exercises[index].name),
                          value: index,
                          groupValue: _selected,
                          onChanged: (value) {
                            setState(() {
                              _selected = index;
                            });
                          });
                    }),
              ),
              Divider(),
              TextField(
                autofocus: false,
                maxLines: 1,
                style: TextStyle(fontSize: 18),
                decoration: new InputDecoration(
                  border: InputBorder.none,
                  hintText: "hint",
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
Share:
5,522
Javierd98
Author by

Javierd98

Updated on December 19, 2022

Comments

  • Javierd98
    Javierd98 over 1 year

    I'm working on a Flutter project and I was trying to achieve an AlertDialog similar to the option's dialog specified on MaterialDesign Guidelines, but with a TextInput at the bottom.

    I have managed to get something similar to what I want but I there's a problem I can't solve: when the user taps on TextInput and the keyboard appears, I'd like the TextInput to be on top of the keyboard with the listview getting smaller on the y-axis (that's why I'm just setting maxHeight on ConstrainedBox), so that the user can see what he texts, but I'm getting just the opposite, the listview keeps the same size and the InputText is not visible.

    I have tried changing the listview with a column nested on a SingleChildScrollView, or wrapping the entire original Column on a SingleChildScrollView, but none of them seems to work. This is my current code:

    @override
      Widget build(BuildContext context) {
        return AlertDialog(
          title: Text(widget.title),
          shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.all(Radius.circular(20))
          ),
          actions: <Widget>[
            FlatButton(
              child: const Text('CANCEL'),
              materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
              textColor: Theme.of(context).accentColor,
              onPressed: () {
                widget.onCancel();
              },
            ),
            FlatButton(
              child: const Text('OK'),
              materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
              textColor: Theme.of(context).accentColor,
              onPressed: () {
                widget.onOk();
              },
            ),
          ],
          content: Container(
            width: double.maxFinite,
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                Divider(),
                ConstrainedBox(
                  constraints: BoxConstraints(
                    maxHeight: MediaQuery.of(context).size.height*0.4,
                  ),
                  child: ListView.builder(
                      shrinkWrap: true,
                      itemCount: widget.exercises.length,
                      itemBuilder: (BuildContext context, int index){
                        return RadioListTile(
                            title: Text(widget.exercises[index].name),
                            value: index,
                            groupValue: _selected,
                            onChanged: (value){
                              setState(() {
                                _selected = index;
                              });
                            }
                        );
                      }
                  ),
                ),
                Divider(),
                TextField(
                  autofocus: false,
                  maxLines: 1,
                  style: TextStyle(fontSize: 18),
                  decoration: new InputDecoration(
                    border: InputBorder.none,
                    hintText: widget.hintText,
                  ),
                ),
              ],
            ),
          ),
        );
      }
    

    Could somebody provide me some help?

    Thanks a lot!!

  • Javierd98
    Javierd98 about 4 years
    Wow, so it was really that simple. Thanks a lot!!
  • chunhunghan
    chunhunghan about 4 years
    Glad to help. please mark this as answer if it help you. thanks.