Ced
Ced

Reputation: 17337

Expandable button overflowing top of container

I'm trying to make an expandable button, a bit like the expandable fab, except it's not a fab as it is not floating. This is the expandable fab for perspective:

enter image description here

What I'm trying to achieve though is to have a self contained button that expands above it with a menu. Self contained is in bold because I'd like the widget to be used easily without having to modify the parents structure.

So if you copy paste the code below in dartpad you'll see a yellow bar at the bottom. However if you uncomment the lines which are commented, which represents the menu expanding, you'll see that the bottom bar is pushed to the top.

import 'package:flutter/material.dart';


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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: Column(
            children: [
              Expanded(child: Container(color: Colors.purple)),
              MyWidget(),
            ]
          ),
        ),
      ),
    );
  }
}

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    

    return SizedOverflowBox(
      size: Size(double.infinity, 100),
      child: Stack(
        children: [
          Container(color: Colors.amber, height: 100),
//           Transform.translate(
//               offset: Offset(0, -400),
//               child: Container(color: Colors.lightBlue, height: 400, width: 80),
//             ),  
        ]
      )
    );
  }
}

So my questions are:

Upvotes: 0

Views: 443

Answers (2)

Noman khanbhai
Noman khanbhai

Reputation: 581

Try this, run this code in dartpad. It contains one parent, three child which can be called using the menu buttons,

The FloatingActionButton.extended used in this code can be replaced by any custom Widget, you can give onTap methods for clicks,

I have used simple widgets, Let me know wether you were looking for something like that, or something different.

import 'package:flutter/material.dart';

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'I am Parent'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool showButtons = false;
  var index = 0;
  List<Widget> childList = [Child1(), Child2(), Child3()];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: Center(
          child: childList[index],
        ),
        floatingActionButton: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Visibility(
              visible: showButtons,
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  FloatingActionButton.extended(
                    heroTag: 'btn1',
                    onPressed: () {
                      setState(() {
                        index = 0;
                      });
                    },
                    label: Text(
                      "Sub Btn1",
                      style: TextStyle(color: Colors.black),
                    ),
                    elevation: 3,
                    backgroundColor: Colors.yellowAccent,
                  ),
                  Padding(
                      padding: EdgeInsets.only(top: 3),
                      child: FloatingActionButton.extended(
                        heroTag: 'btn1',
                        onPressed: () {
                          setState(() {
                            index = 1;
                          });
                        },
                        label: Text(
                          "Sub Btn2",
                          style: TextStyle(color: Colors.black),
                        ),
                        elevation: 3,
                        backgroundColor: Colors.yellowAccent,
                      )),
                  Padding(
                      padding: EdgeInsets.only(top: 3),
                      child: FloatingActionButton.extended(
                        heroTag: 'btn3',
                        onPressed: () {
                          setState(() {
                            index = 2;
                          });
                        },
                        label: Text(
                          "Sub Btn3",
                          style: TextStyle(color: Colors.black),
                        ),
                        elevation: 3,
                        backgroundColor: Colors.yellowAccent,
                      ))
                ],
              ),
            ),
            RaisedButton(
              onPressed: () {
                setState(() {
                  showButtons = !showButtons;
                });
              },
              child: Text("Self Contained"),
              shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(16)),
              color: Colors.yellow,
            ),
          ],
        ) // This trailing comma makes auto-formatting nicer for build methods.
        );
  }
}

class Child1 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text("I am Child 1"),
    );
  }
}

class Child2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text("I am Child 2"),
    );
  }
}

class Child3 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text("I am Child 3"),
    );
  }
}

Upvotes: 0

Ced
Ced

Reputation: 17337

Overlay and OverlayEntry can help to achieve this:

import 'package:flutter/material.dart';


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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: Column(
            children: [
              Expanded(child: Container(color: Colors.purple)),
              MyWidget(),
            ]
          ),
        ),
      ),
    );
  }
}

class MyWidget extends StatelessWidget {
  OverlayEntry? _overlayEntry;
  
  _hideMenu() {
    _overlayEntry?.remove();
  }
  
  _showMenu(BuildContext context) {
     final overlay = Overlay.of(context);
     _overlayEntry = OverlayEntry(
       builder: (ctx) => Stack(
         children: [
           GestureDetector(
             onTap: () => _hideMenu(),
             child: Container(color: Colors.grey.withAlpha(100)),
           ),
           Positioned(
             bottom: 100,
             left: 50,
             child: Container(color: Colors.pink, height: 200, width: 50,),
           ),
           
         ],
       )
       
     );
    overlay?.insert(_overlayEntry!);
  }
  
  @override
  Widget build(BuildContext context) {

    return GestureDetector(
      onTap: () => _showMenu(context),
      child: Container(color: Colors.amber, height: 100)
    );
  }
}

Upvotes: 1

Related Questions