skip to Main Content

Using Flutter, I am trying to position a widget (a button) at the bottom of a SingleChildScrollView.

A specific requirement is that the button should at the bottom of the screen if the content of the SingleChildScrollView does not take the whole screen.

Here is what I tried:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: const Scaffold(
        body: MyWidget(),
      ),
    );
  }
}

class MyWidget extends StatelessWidget {
  const MyWidget({super.key});

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
        child: Column(children: [
      Container(
        height: 1000,
        color: Colors.lightBlue,
      ),
      // Expanded(
      //   child: Container(
      //     color: Colors.yellow,
      //   ),
      // ),
      TextButton(
        onPressed: () {},
        style: TextButton.styleFrom(
          backgroundColor: Colors.red,
        ),
        child: const Icon(
          Icons.edit,
        ),
      ),
    ]));
  }
}

This gives the following result with various heights:

scrollview-1
scrollview-2

As expected, the button is positioned at the bottom of the SingleChildScrollView but not at the bottom of the screen. I tried to use a Spacer (or an Expandable) but this always fails with the following error:

FlutterError (RenderFlex children have non-zero flex but incoming height constraints are unbounded.

3

Answers


  1. How about using the constarins of maxhight to the parent of singlechild scroll view..
    try the below

     return Scaffold(
          body: SafeArea(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.start,
              children: [
                Container(
                  constraints: BoxConstraints(
                      maxHeight: MediaQuery.of(context).size.height - 75),//75 is the size of button
                  child: SingleChildScrollView(
                    child: Column(
                      children: [
                        for (var i = 0; i < 100; i++)
                          Padding(
                            padding: const EdgeInsets.all(8.0),
                            child: Container(
                              height: 100,
                              color: Colors.lightBlue,
                            ),
                          ),
                      ],
                    ),
                  ),
                ),
                Container(
                  height: 75,//size of button
                  child: Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: TextButton(
                      onPressed: () {},
                      style: TextButton.styleFrom(
                        backgroundColor: Colors.red,
                      ),
                      child: const Icon(
                        Icons.edit,
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
        );
    
    Login or Signup to reply.
  2. You can achieve it via

    Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: Column(
          children: [
            Expanded(
                child: SingleChildScrollView(
                    child: Column(
              children: [
                Container(
                  height: 100,
                  color: Colors.red,
                ),
                Container(
                  height: 500,
                  color: Colors.blue,
                ),  
              ],
            ),),),
            TextButton(
              onPressed: () {},
              style: TextButton.styleFrom(
                backgroundColor: Colors.red,
              ),
              child: const Icon(
                Icons.edit,
              ),
            ),
          ],
        ));
    
    Login or Signup to reply.
  3. Expected output

    Currently you have made the singleChildScrollView as the parent of all the remaining widgets including the Textbutton, Instead what you can do is make the column as the parent of all the remaining widgets and the singleChildScrollView and TextButton as a two separate children of this parent column as shown in the code.

        Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      children: [
        SingleChildScrollView(
          child: Column(
            children: [
              Container(
                height: 500,
                color: Colors.lightBlue,
              ),
              // You may add other widgets
            ],
          ),
        ),
        // The text Button Is out side of the singleChildScrollView
        TextButton(
          onPressed: () {},
          style: TextButton.styleFrom(
            backgroundColor: Colors.red,
          ),
          child: const Icon(
            Icons.edit,
          ),
        )
      ],
    );}}
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search