0

I am trying to layout a basic page with a single text field for input and some UI elements. The build tree is shown below for reference:

Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: NthConstants.primaryColor,
      resizeToAvoidBottomInset: false,
      body: SafeArea(
        child: Column(
          children: <Widget>[
            Expanded(
              flex: 6,
              child: Padding(
                padding: EdgeInsets.all(20),
                child: Stack(
                  children: <Widget>[
                    LayoutBuilder(
                      builder: (context, constraints) {
                        return Center(
                          child: Image.asset(
                            NthConstants.imageDir +
                                NthConstants.phoneBackgroundFileName,
                            height: constraints.maxHeight,
                            fit: BoxFit.contain,
                          ),
                        );
                      },
                    ),
                    Column(
                      children: <Widget>[
                        Expanded(
                          child: LayoutBuilder(
                            builder: (BuildContext context,
                                BoxConstraints constraints) {
                              return Align(
                                  alignment: Alignment.bottomCenter,
                                  child: Stack(children: [
                                    FaIcon(
                                      FontAwesomeIcons.userSecret,
                                      size: constraints.maxHeight / 2,
                                    ),
                                    Positioned(
                                      bottom: 7,
                                      right: 7,
                                      child: FaIcon(
                                        FontAwesomeIcons.solidCircle,
                                        size: 12,
                                        color: Colors.grey,
                                      ),
                                    )
                                  ]));
                            },
                          ),
                        ),
                        Flexible(
                          child: Padding(
                            padding: const EdgeInsets.only(top: 8.0),
                            child: Row(
                              mainAxisAlignment: MainAxisAlignment.center,
                              crossAxisAlignment: CrossAxisAlignment.center,
                              children: <Widget>[
                                (_agentName?.length ?? 0) > 0
                                    ? (FaIcon(FontAwesomeIcons.shieldAlt,
                                        color:
                                            NthConstants.primaryColor.shade800,
                                        size: Theme.of(context)
                                            .textTheme
                                            .headline
                                            .fontSize))
                                    : Container(),
                                Padding(
                                  padding: const EdgeInsets.only(left: 8.0),
                                  child: Text(
                                    _agentName,
                                    style: Theme.of(context)
                                        .textTheme
                                        .headline
                                        .copyWith(
                                          color: NthConstants
                                              .primaryColor.shade900,
                                          fontWeight: FontWeight.bold,
                                        ),
                                  ),
                                ),
                              ],
                            ),
                          ),
                        )
                      ],
                    )
                  ],
                ),
              ),
            ),
            Expanded(
              flex: 4,
              child: Column(
                children: <Widget>[
                  Expanded(
                    flex: 4,
                    child: Column(
                      children: <Widget>[
                        Expanded(
                            child: Padding(
                          padding: EdgeInsets.symmetric(
                              horizontal: 40, vertical: 20),
                          child: TextFormField(
                            onChanged: (newValue) {
                              setState(() {
                                _agentName = newValue;
                              });
                            },
                            cursorColor: NthConstants.primaryColor.shade800,
                            enableSuggestions: true,
                            autocorrect: true,
                            cursorWidth: 5,
                            cursorRadius: Radius.elliptical(5, 5),
                            maxLength: 25,
                            style: Theme.of(context).textTheme.headline,

                            decoration: InputDecoration(
                                //hintStyle: TextStyle(fontWeight: FontWeight.w300, color: Colors.red),
                                hintText: "Agent Name",
                                border: OutlineInputBorder(
                                    borderSide: BorderSide(
                                        color: NthConstants
                                            .primaryColor.shade800)),
                                focusColor: NthConstants.primaryColor.shade800,
                                fillColor: Colors.grey,
                                hasFloatingPlaceholder: true,
                                prefixIcon: Icon(FontAwesomeIcons.shieldAlt,
                                    color: NthConstants.primaryColor.shade800),
                                focusedBorder: OutlineInputBorder(
                                    borderRadius: BorderRadius.circular(10),
                                    borderSide: BorderSide(
                                        color: NthConstants
                                            .primaryColor.shade800))),
                            // The validator receives the text that the user has entered.
                          ),
                        )),
                        Flexible(
                          child: Padding(
                            padding: EdgeInsets.only(top: 20),
                            child: LayoutBuilder(
                              builder: (BuildContext context,
                                  BoxConstraints constraints) {
                                return ConnectionSlider(
                                    iconRotateAngle: -90 * pi / 180,
                                    icon: FontAwesomeIcons.ethernet,
                                    iconColor:
                                        NthConstants.primaryColor.shade700,
                                    textStyle: Theme.of(context)
                                        .textTheme
                                        .subhead
                                        .copyWith(
                                            color: NthConstants
                                                .primaryColor.shade700),
                                    text: "Slide to connect",
                                    foregroundColor:
                                        NthConstants.primaryColor.shade500,
                                    backgroundColor:
                                        Colors.white.withOpacity(0.2),
                                    onConfirmation: () {
                                      print("Agent $_agentName connected!");
                                    });
                              },
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                  Expanded(
                    flex: 1,
                    child: Padding(
                      padding: EdgeInsets.all(8),
                      child: NthHeroLogo(),
                    ),
                  )
                ],
              ),
            )
          ],
        ),
      ),
    );
  }

The screenshots show the issue that the text field gets hidden behind the keyboard. I tried putting that in the SingleChildScrollView but I get an error saying hasSize is not available because I have used Expanded in Column ...

RenderBox was not laid out: RenderSemanticsGestureHandler#37de9 relayoutBoundary=up4 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
'package:flutter/src/rendering/box.dart':
Failed assertion: line 1687 pos 12: 'hasSize'

Any pointers how can I fix this layout?

The original layout with no issues

The keyboard hides the text field

If the resize flag is set to true

Sangram Mohite
  • 735
  • 4
  • 11
  • 23

1 Answers1

0

Try it with resizeToAvoidBottomInset: true, (or simply remove the line, as this is the default value) in your scaffold. The page should then resize when the keyboard becomes visible, and you can arrange your layout accordingly.

Joel
  • 1
  • 1
  • Yes that causes the expanded and the layout gets messed up. – Sangram Mohite May 01 '20 at 07:12
  • You need to create a design/layout that works for both these sizes. For this page my preference would be to set the height of the elements you don't want resized. What do you want your page to look like when the keyboard appears? – Joel May 01 '20 at 07:42
  • If you really want it to be scrollable and keep the expanded take a look at [this answer](https://stackoverflow.com/a/56327933/13446265) – Joel May 01 '20 at 07:48
  • I tried that. I get the following error now - The following assertion was thrown during performLayout(): LayoutBuilder does not support returning intrinsic dimensions. Calculating the intrinsic dimensions would require running the layout callback speculatively, which might mutate the live render object tree. The relevant error-causing widget was IntrinsicHeight – Sangram Mohite May 01 '20 at 08:17
  • I want to make the phone frame and the icon inside responsive to the screen size. Hence I am using expanded and managing the sizes accordingly. – Sangram Mohite May 01 '20 at 08:18
  • In such case make sure you only wrap the widgets you want to be resized in `Flex` (`Expanded` or `Flexible`), i.e. not `TextField`, slider etc. Instead set their height exactly the number of pixels you want them to be. If you want spacing between them that adjust to the screen size, look at the `Spacer` widget, which can be defined using a flex parameter, in the same way as you have done with your `Expandable`. – Joel May 01 '20 at 09:02