Home > front end >  Flutter: Card layout with centered circle on top of card
Flutter: Card layout with centered circle on top of card

Time:03-02

I'm fairly new to flutter and I'm trying to have a card that has two sections each taking half of the space. And then I want an avatar circle image widget that lies on top in the centre of the card as illustrated in the image.

For now the code looks like this (includes the two sections):

@override
  Widget build(BuildContext context) {
    // it enable scrolling on small device
    return Center(
      child: Card(
        margin: const EdgeInsets.all(10.0),
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(16),
        ),
        color: cardColor,
        child: Flex(
          direction: Axis.vertical,
          children: [
            Expanded(
              child: ClipRRect(
                  borderRadius: const BorderRadius.only(
                      topLeft: Radius.circular(16),
                      topRight: Radius.circular(16)),
                  child: Container(
                    child: Image.asset("assets/images/card_background.jpg",
                        fit: BoxFit.fill),
                  )),
            ),
            Expanded(
              child: Column(
                children: [
                  Container(
                    child: Text("Test"),
                  )
                ],
              ),
            )
          ],
        ),
      ),
    );
  }

enter image description here

I am therefore wondering how I can get the avatar image positioned as illustrated in the image. Or if it is even possible with the code I have until now. In that case, I'm wondering which widgets I should use to solve this.

Thanks for any help!

CodePudding user response:

If I understand you correctly, you want a Card with a background image and a CircleAvatar widget in the top center.

You do this by using Stack like so:

Card(
  margin: const EdgeInsets.all(10),
  shape: RoundedRectangleBorder(
    borderRadius: BorderRadius.circular(16),
  ),
  clipBehavior: Clip.antiAlias,
  color: cardColor,
  child: Stack(
    children: [
      Positioned.fill(
        child: Image.asset(
          'assets/images/card_background.jpg',
          fit: BoxFit.fill,
        ),
      ),
      const Positioned.fill(
        child: Align(
          alignment: Alignment.topCenter
          child: CircleAvatar(
            backgroundColor: Colors.orangeAccent,
          ),
        ),
      )
    ],
  )
),

CodePudding user response:

You are on the right track, having a Column (or Flex) and 2 Expanded to equally divide it. You just need another Stack widget to overlay the circle on top. You can wrap the circle with an Align widget and set it to align center-left.

The code would look something like:

Stack
 Column
   - Expanded
   - Expanded
 Align
   - Circle

CodePudding user response:

Nothing that a simple Stack widget can't solve.

enter image description here


@override
  Widget build(BuildContext context) {
    // it enable scrolling on small device
    return Center(
      child: Card(
        margin: const EdgeInsets.all(10.0),
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(16),
        ),
        color: Colors.blue,
        child: Stack(
          children: [
            Flex(
              direction: Axis.vertical,
              children: [
                Expanded(
                  child: ClipRRect(
                    borderRadius: const BorderRadius.only(
                      topLeft: Radius.circular(16),
                      topRight: Radius.circular(16)),
                    child: Container(
                      color: Colors.red,
                    )),
                ),
                Expanded(
                  child: Column(
                    children: [
                      Container(
                        child: Text("Test"),
                      )
                    ],
                  ),
                )
              ],
            ),
            
            // align a circle center and left, with a left margin
            Align(
              alignment: Alignment.centerLeft,
              child: Container(
                margin: const EdgeInsets.only(left: 20),
                child: ClipOval(
                  child: Container(
                    width: 80,
                    height: 80,
                    color: Colors.black
                  )
                )
              )
           )
          ] 
        ),
      ),
    );
  }

CodePudding user response:

You can use Stack widget to place widgets on top of other widgets. Try this code

    @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Stack(
          children: [
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: Column(
                children: [
                  Expanded(
                    child: Container(
                      decoration: const BoxDecoration(
                        borderRadius: BorderRadius.only(topLeft: Radius.circular(10),topRight: Radius.circular(10)),
                        color: Colors.blue
                      ),
                    ),
                  ),
                  Expanded(
                    child: Container(
                      decoration: const BoxDecoration(
                          borderRadius: BorderRadius.only(bottomLeft: Radius.circular(10),bottomRight: Radius.circular(10)),
                          color: Colors.red
                      ),
                    ),
                  )
                ],
              ),
            ),
            Positioned.fill(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: const [
                  Padding(
                    padding: EdgeInsets.only(left: 20),
                    child: CircleAvatar(
                      radius: 40,
                      backgroundColor: Colors.grey,
                    ),
                  ),
                ],
              ),
            )
          ],
        )
      ),
    );
  }
  • Related