Flutter overflow circle avatar overlaying a container

Viewed 7753

Here's the design that I want to build:

Image

This is where I am now:

Image

When I tried wrapping the Sized Box of the CircleAvatar with Overflow Box, I got the 'A RenderFlex overflowed by Infinity pixels on the bottom' error. I tried to use stack, but realise that it is making things more complicated. I feel like Overflow Box is the answer but couldn't get my head around it.

Container(
  child: Column(
    crossAxisAlignment: CrossAxisAlignment.stretch,
    children: [
      SizedBox(
        child: CircleAvatar(
          radius: 40.0,
          backgroundColor: Colors.white,
          child: CircleAvatar(
            child: Align(
              alignment: Alignment.bottomRight,
              child: CircleAvatar(
                backgroundColor: Colors.white,
                radius: 12.0,
                child: Icon(
                  Icons.camera_alt,
                  size: 15.0,
                  color: Color(0xFF404040),
                ),
              ),
            ),
            radius: 38.0,
            backgroundImage: AssetImage(
              'assets/images/user-image-default.png'),
          ),
        ),
      ),
      Center(
        child: Container(
          padding: EdgeInsets.only(top: 16.0),
          child: Text(
            'Hi Sir David',
            style: TextStyle(
              fontFamily: 'SF Pro',
              fontWeight: FontWeight.w700,
              fontSize: 24.0,
            ),
          ),
        ),
      ),
      Center(
        child: Container(
          padding: EdgeInsets.only(top: 8.0),
          child: Text(
            'Wildlife Advocate',
            style: TextStyle(
              fontFamily: 'SF Pro',
              fontSize: 12.0,
            ),
          ),
        ),
      ),
      Center(
        child: Padding(
          padding: const EdgeInsets.all(24.0),
            child: TextButton(
              onPressed: () {
                print('im pressed');
              },
              child: Container(
                padding:
                EdgeInsets.fromLTRB(16.0, 8.0, 16.0, 8.0),
                decoration: BoxDecoration(
                  color: Color(0xFFEF476F),
                  borderRadius:
                  BorderRadius.all(Radius.circular(20.0)),
                ),
                child: Text(
                  'Edit Profile',
                  style: TextStyle(
                    fontFamily: 'SF Pro',
                    color: Colors.white,
                    fontWeight: FontWeight.w500,
                    fontSize: 16.0,
                  ),
                ),
              ),
            ),
        ),
      ),
    ],
  ),
  margin: EdgeInsets.all(16.0),
  decoration: BoxDecoration(
    color: Colors.white,
    borderRadius: BorderRadius.circular(16.0),
  ),
),
4 Answers

I'm not giving full code of your example but this may help you. I just code this dartpad and hopefully it provides the solution ...

Stack(
  children: [
    
    Container(
      margin: EdgeInsets.only(top: 48),
    height: 300,decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16.0),
),),
    Align(
      alignment: Alignment.topCenter,
    child: SizedBox(
    child: CircleAvatar(
      radius: 40.0,
      backgroundColor: Colors.white,
      child: CircleAvatar(
        child: Align(
          alignment: Alignment.bottomRight,
          child: CircleAvatar(
            backgroundColor: Colors.white,
            radius: 12.0,
            child: Icon(
              Icons.camera_alt,
              size: 15.0,
              color: Color(0xFF404040),
            ),
          ),
        ),
        radius: 38.0,
        backgroundImage: AssetImage(
          'assets/images/user-image-default.png'),
      ),
    ),)
  ),
  ]
)

If these methods don't work, what you should do is wrapping the two widgets (i.e the widgets you want to stack together) with "Positioned" widget to understand more of this click on the link below:

https://www.youtube.com/watch?v=7njbf2mFcgM

I can see that you want two elements overlapped on top of one another. In such cases, Stack widget could prove to be helpful. Stack accepts an array of children to be stacked. Basically, the 2 components that you want to stack would be the CircleAvatar and the card Container underneath. Also, since by default the widgets are aligned on the top-left, you might want to align it on the top-center instead. You can use the alignment property and set it to Alignment.topCenter to align it accordingly.

Structure of Code


Putting it all together and you get this structure:

Container(
  margin: EdgeInsets.all(16.0),
  child: Stack(
    alignment: Alignment.topCenter,
    children: [
      // Avatar

      SizedBox(
        child: CircleAvatar(
          ...
        )
      ),

      // Card Container

      Container(
        child: Column(
          children: [
            // All the widgets after `CircleAvatar` goes here
            ⋮
            ⋮
          ]
        ),
        margin: EdgeInsets.only(top: 16.0),    // Change this based on the spacing between the card container and the avatar
        decoration: BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.circular(16.0),
        ),
      )
    )
  )
);

Note:

  • Based on how it all aligns, you may change the value of top margin. The one provided should be considered as a placeholder only.

  • This answer just provides the structure of the code to make it look clean and easy to understand.

Align(
alignment: Alignment.TopCenter,
 child: CircleAvatar(
   radius: 70,
   backgroundImage: AssetImage('assets/images/avatart.jpg'),
   backgroundColor: kPrimaryColor,
 ),
),
Related