I want to Create an TextField at the bottom of the page like message app.

There is also a IconButton, which adds the entered text into ListView if TextField is not empty. If it is empty then it will show error in SnackBar.

The Problem is the SnackBar stacks on top of TextField. But I want it to be either top or bottom of TextField.

import 'package:flutter/material.dart';

Future<void> main() async {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MainPage(),
    );
  }
}

class MainPage extends StatefulWidget {
  @override
  _MainPageState createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  final _textList = <String>[];

  TextEditingController _textController;

  bool _addText(context, String text) {
    print(text);
    if (text?.isNotEmpty == true) {
      setState(() {
        _textList.add(text);
      });
      return true;
    } else {
      Scaffold.of(context).showSnackBar(
        SnackBar(
          content: Text("Invalid Text Entered"),
          behavior: SnackBarBehavior.fixed,
        ),
      );
      return false;
    }
  }

  @override
  void initState() {
    _textController = TextEditingController();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Demo"),
      ),
      body: SafeArea(
        child: Column(
          children: <Widget>[
            Expanded(
              child: ListView.separated(
                itemCount: _textList.length,
                separatorBuilder: (_, __) => Divider(height: 1.0),
                itemBuilder: (context, index) => ListTile(
                  title: Text("${_textList[index]}"),
                ),
              ),
            ),
            _buildBottom(),
          ],
        ),
      ),
    );
  }

  Widget _buildBottom() {
    return Material(
      elevation: 5.0,
      color: Colors.blue[100],
      child: Row(
        children: <Widget>[
          Expanded(
            child: TextField(
              controller: _textController,
              decoration: InputDecoration(
                hintText: "Enter Text",
                contentPadding: EdgeInsets.symmetric(horizontal: 10.0),
                border: InputBorder.none,
              ),
            ),
          ),
          Builder(
            builder: (context) => IconButton(
              icon: Icon(Icons.add),
              onPressed: () {
                final success = _addText(context, _textController.text);
                if (success) _textController.clear();
              },
            ),
          ),
        ],
      ),
    );
  }
}

This is my code in DartPad


Solution 1: Arhaam Patvi

Perhaps using Flushbar might help with your problem. There are many properties that you can change, such as flushbarPosition.
It might not solve your problem exactly how you would expect it to but it can make the Flushbar appear from the top instead of the bottom and that's one way around your problem

Flushbar: https://pub.dev/packages/flushbar


Solution 2: Jay Gadariya

try this,

import 'package:flutter/material.dart';

Future<void> main() async {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MainPage(),
    );
  }
}

class MainPage extends StatefulWidget {
  @override
  _MainPageState createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  final _textList = <String>[];

  TextEditingController _textController;

  bool isVisible = false;

  bool _addText(context, String text) {
    print(text);
    if (text?.isNotEmpty == true) {
      setState(() {
        _textList.add(text);
      });
      return true;
    } else {
      Scaffold.of(context).showSnackBar(
        new SnackBar(
          content: Text("Invalid Text Entered"),
          behavior: SnackBarBehavior.fixed,
          duration: Duration(seconds: 3),
          onVisible: (() {
            setState(() {
              isVisible = true;
            });
            Future.delayed(Duration(seconds: 3)).then((_) => setState(() {
                  isVisible = false;
                }));
          }),
        ),
      );
      return false;
    }
  }

  @override
  void initState() {
    _textController = TextEditingController();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Demo"),
      ),
      body: SafeArea(
        child: Column(
          children: <Widget>[
            Expanded(
              child: ListView.separated(
                itemCount: _textList.length,
                separatorBuilder: (_, __) => Divider(height: 1.0),
                itemBuilder: (context, index) => ListTile(
                  title: Text("${_textList[index]}"),
                ),
              ),
            ),
            AnimatedContainer(
              margin: EdgeInsets.only(bottom: isVisible ? 50 : 0),
              child: _buildBottom(),
              duration: Duration(milliseconds: 100),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildBottom() {
    return Material(
      elevation: 5.0,
      color: Colors.blue[100],
      child: Row(
        children: <Widget>[
          Expanded(
            child: TextField(
              controller: _textController,
              decoration: InputDecoration(
                hintText: "Enter Text",
                contentPadding: EdgeInsets.symmetric(horizontal: 10.0),
                border: InputBorder.none,
              ),
            ),
          ),
          Builder(
            builder: (context) => IconButton(
              icon: Icon(Icons.add),
              onPressed: () {
                final success = _addText(context, _textController.text);
                if (success) _textController.clear();
              },
            ),
          ),
        ],
      ),
    );
  }
}


Solution 3: Stefano Saitta

I think the best thing you can do here is to change the behaviour to floating

SnackBar(
    behavior: SnackBarBehavior.floating,
    ...