aksn
aksn

Reputation: 2559

Flutter Dynamic maxHeight

I build a scrolling textfield like proposed in https://github.com/flutter/flutter/issues/9365. Now I want the maxHeight of the ConstrainedBox change dynamically, according to the shown or not shown keyboard. Is there a way to accomplish this?

Widget _buildTextInput() {
 return new Container(
  padding: new EdgeInsets.all(7.0),
  child: new ConstrainedBox(
    constraints: new BoxConstraints(
      maxHeight: 150.0 <-- This should be dynamic
    ),

    child: new SingleChildScrollView(
      scrollDirection: Axis.vertical,
      reverse: true,

      // here's the actual text box
      child: new TextField(
        keyboardType: TextInputType.multiline,
        maxLines: null, //grow automatically
        decoration: new InputDecoration.collapsed(
            hintText: 'Please enter a lot of text',
        ),
      ),
    ),
  ),
 );
}

The red box should be the constrained box with open keyboard.

And like so with a closed keyboard.

EDIT: I'm trying to build an input field that's kind of like posting on Twitter. I need to combine a CircleAvatar, a TextField and a GridView to display the user's avatar, his post and a few images. Like on Twitter, I want the whole thing to scroll, not only the TextField - both while typing and while reviewing what the user typed or uploaded. Besides, the (multiline) TextField should scroll while typing in the visible area (keeping the open or closed keyboard in mind), so the user can see what he's typing.

Even though the Flutter TextField autoscrolls now, I can't get this whole cluster working. Any idea?

Upvotes: 3

Views: 8557

Answers (1)

rmtmckenzie
rmtmckenzie

Reputation: 40443

Autoscroll has been supported natively in the textfield widget since I believe the beginning of June (2018) - I think this is the commit that added it. You may need to update to the most recent flutter build for it to work, but that is included in version 5.5.

This simplifies matters a bit - this should be all you need to do to get it to work as you want:

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => new MyAppState();
}

class MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text("Example"),
        ),
        body: new Container(
          padding: new EdgeInsets.all(7.0),
          child: new TextField(
            keyboardType: TextInputType.multiline,
            maxLines: null,
            decoration: new InputDecoration.collapsed(
              hintText: 'Please enter a lot of text',
            ),
          ),
        ),
      ),
    );
  }
}

EDIT: To answer the OP's edited question - wanting to have other elements within the same scrolling pane as the textview, I've made this:

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => new MyAppState();
}

class MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text("Example"),
        ),
        body: new SingleChildScrollView(
          child: new Container(
            padding: new EdgeInsets.all(7.0),
            child: new Row(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                new CircleAvatar(
                  backgroundColor: Colors.blue,
                  child: new Text("AB"),
                ),
                new Expanded(
                  child: new Column(
                    children: [
                      new TextField(
                        keyboardType: TextInputType.multiline,
                        maxLines: null,
                        decoration: new InputDecoration.collapsed(
                          hintText: 'Please enter a lot of text',
                        ),
                      ),
                      new Container(
                        height: 300.0,
                        width: 100.0,
                        color: Colors.green,
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

By using a SingleChildScrollView, we're still allowing the children to set the size of the viewport (as opposed to a MultiChildLayoutDelegate etc which has to have that size set). The textview grows as big as it needs to be, but doesn't scroll itself as its height is not constrained. The Expanded is needed within the row to make sure that the right side (with the text & pictures) is as large as it can be horizontally.

Upvotes: 1

Related Questions