简体   繁体   中英

Hide/Dismiss keyboard on ListView scroll in Flutter app

I have chat window in Flutter app. Messages are presented as widgets inside ListView widget and I also have widget for message input attached to bottom of the window.

I want to

  1. hide keyboard when I scroll the ListView
  2. scroll to last message when new is added from InputWidget

code:

class _MessagesPageState extends State<MessagesPage> {
  final ScrollController listScrollController = ScrollController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
    ....
    body: Stack(
        children: [
          ListView.builder(
              controller: listScrollController
              ....
          ),
          InputWidget()]
    );
}

class InputWidget extends StatelessWidget {

  final TextEditingController _textEditingController = TextEditingController();

....
Row (
  children: [
    TextField(
     controller: _textEditingController
    ), 
    IconButton(icon: ...., onPressed: (){})
  ]
 )}

For hiding keyboard on listview scrolling, you simply add keyboardDismissBehavior to it. Example

ListView(
 keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
 children: [],
)

As to point 1 of you question :

You can create a listener function for listScrollController containing a call to an anonymous FocusNode (idea taken from this highly voted answer ), and when any scroll event occurs, focus will be taken from your TextField and keyboard will be dismissed:

 class _MessagesPageState extends State<MessagesPage> {

 final ScrollController listScrollController = ScrollController();

 @override
 void initState() {
   listScrollController.addListener(_scrollListener);
   super.initState();
 }

 _scrollListener() {
   FocusScope.of(context).requestFocus(FocusNode());
 }

 @override
 Widget build(BuildContext context) {
   return Scaffold(
   ....
   body: Stack(
    children: [
      ListView.builder(
          controller: listScrollController
          ....
      ),
      InputWidget(controller: listScrollController)]
   );
}

Point 2 :

You'll notice that I modified your InputWidget to take a ScrollController as a parameter, so you can pass your ListView controller to it. and when the IconButton is pressed, listScrollController will jump to the end as you desire.

 class InputWidget extends StatelessWidget {

 InputWidget({Key key,this.controller}) : super(key: key);

 final ScrollController controller ;

 final TextEditingController _textEditingController = TextEditingController();

 ....
 Row (
  children: [
    TextField(
      controller: _textEditingController
    ), 
    IconButton(icon: ...., onPressed: (){
      controller.jumpTo(controller.position.maxScrollExtent);
    })
  ]
 )}

it's easy..Follow these step..

  1. Change class to StatefullWidget
  2. create final ScrollController listScrollController = ScrollController();
  3. ListView should be like this:

     ListView.builder( controller: listScrollController, reverse: true,
  4. If you use firebase change order by like this:

    .orderBy('timestamp', descending: true)

  5. Add this code in your Send button

listScrollController.animateTo(0.0,duration: Duration(milliseconds: 300), curve: Curves.easeOut);

Automatically scroll up your textField, Add your textField and ListView inside Stack

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM