Align IconButton tigthly to the edge of the screen

Issue

I have a custom PreferredSize widget which functions as an application bar and I would want to align the edge of the rightmost action button to the right as if it is cropped by its bounding box. Right know I have this:

enter image description here

What I want to achieve is basically this (note the position of the three dots):

enter image description here

My code looks like this:

class MaterialIconButton extends StatelessWidget {
  final Icon icon;

  const MaterialIconButton({
    Key? key,
    required this.icon
  }): super(key: key);

  @override
  Widget build(BuildContext context) {
    return  ClipOval(
      child: 
      Material(
        color: Colors.transparent,
        child: Padding(
          padding: const EdgeInsets.all(0),
          child: IconButton(
            onPressed: () {}, 
            icon: icon,
            iconSize: 36,
            padding: EdgeInsets.zero,
            splashColor: Colors.black.withAlpha(40),
            highlightColor: Colors.black.withAlpha(20),
          )
        ),
      ),
    );
  }
}

class HomeHeader extends StatelessWidget {
  const HomeHeader({Key? key}): super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(
        color: Colors.indigo[100]
      ),
      padding: const EdgeInsets.fromLTRB(16, 32, 16, 16),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.start,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          RichText(
            text: TextSpan(
              children: [
                TextSpan(
                  text: "Example",
                  style: TextStyle(
                    fontWeight: FontWeight.w600,
                    fontSize: 20,
                    color: Colors.blueGrey[800]
                  )
                ),
              ]    
            )
          ),
          Row(
            mainAxisAlignment: MainAxisAlignment.end,
            children: const [
              MaterialIconButton(
                icon: Icon(
                  Icons.settings
                )
              ),
              MaterialIconButton(
                icon: Icon(
                  Icons.more_vert
                )
              )
            ],
          )
        ]
      )
    );
  }
}

class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: const PreferredSize(
        child: HomeHeader(),
        preferredSize: Size.fromHeight(120),
      ),
      body: (...)
    );
  }
}

Is there any way to achieve this using only built-in Flutter SVG Icons? Note that in general I can’t know the exact size of icon’s bounding box in advance.

Solution

Wrapping everything in a Positioned widget inside a Stack seems to work; I was able to achieve my original design with the help of negative absolute positioning inside a Positioned. Going with the example I’ve provided in my question the final result might look like this:

class HomeHeader extends StatelessWidget {
  const HomeHeader({Key? key}): super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(
        color: Colors.indigo[100]
      ),
      padding: const EdgeInsets.fromLTRB(0, 32, 0, 32),
      child: Stack(
        children: [
          Positioned(
            left: -16,
            right: -16,
            child: Container(
              padding: const EdgeInsets.fromLTRB(16, 0, 16, 0),
              child: Column(
                children: [
                  RichText(
                    text: TextSpan(
                      children: [
                        TextSpan(
                          text: "Example",
                          style: TextStyle(
                            fontWeight: FontWeight.w600,
                            fontSize: 20,
                            color: Colors.blueGrey[800]
                          )
                        )
                      ]
                    )
                  ),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.end,
                    children: const [
                      MaterialIconButton(
                        icon: Icon(
                          Icons.settings
                        )
                      ),
                      MaterialIconButton(
                        icon: Icon(
                          Icons.more_vert
                        )
                      )
                    ],
                  )
                ],
              ),
            )
          )
        ],
      )
    );
  }
}

The result:

enter image description here

When I set padding to zero:

enter image description here

Which gives me kind of what I wanted.

Answered By – user3808059

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published