flutterflutter-container

Overlap a button at the bottom center edge in Flutter


List Item Image with Button

I'm a newbie in Flutter. From what I can figure out, I need to use Stack, Container, Position to get the result, but unable to come close to it. If anyone can point to a related article to achieve this or code block, it'll be of great help.

Requirement: Need to place the "ADD" button above the bottom middle edge of the underlying image.

class FoodList extends StatelessWidget {
  const FoodList(
      {super.key, required this.foods, required this.restaurantName});

  final List<Food> foods;
  final String restaurantName;

  @override
  Widget build(BuildContext context) {
    return ListView.separated(
      //scrollDirection: Axis.horizontal,
      itemCount: foods.length,
      /* separatorBuilder: (BuildContext context, int index) =>
                const Divider(), */ // Add a divider between each item in the list
      itemBuilder: (BuildContext context, int index) => foodItem(context, index),
      separatorBuilder: (BuildContext context, int index) {
        return const Divider(
          height: 1,
          color: Color.fromARGB(255, 212, 210, 210),
        );
      },
    );
  }

  InkWell foodItem(BuildContext context, int index) {
    return InkWell(
      onTap: () {
        timeDilation = 2.0;
        Navigator.push(
          context,
          MaterialPageRoute(
              builder: (context) => 
              ItemDetailsHero(
                restaurantName: restaurantName,
                    itemName: foods[index].title,
                    imageUrl: foods[index].image,
                    description: foods[index].description,
              )
              
                  ),
        );
      },
      child: Padding(
        padding: const EdgeInsets.only(bottom: 10.0),
        child: Column(

          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.start,
          children: [
            Column(
              children: [
                Padding(
                  padding: const EdgeInsets.fromLTRB(6, 20, 2, 20),
                  child: Row(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: <Widget>[
                      Expanded(
                          flex: 2,
                          child:  Hero(
                                tag: 'item',
                                child:

                                Container(
                                  //height: 240,
                                  child: ItemThumbnailCard(
                                    foods: foods,
                                    index: index,
                                  ),
                                ),
                              ),
                          ),
                      Expanded(
                          flex: 2,
                          child: _ItemDescription(
                              title: foods[index].title,
                              description: foods[index].description,
                              price: foods[index].price,
                              totalAveargeReview:
                                  foods[index].totalAveargeReview,
                              preparationTime: foods[index].preparationTime,
                              typeOfFood: foods[index].typeOfFood)),
                    ],
                  ),
                ),
                //const SizedBox(height: 20,)
              ],
            ),
            //ListTileWidget(foods: foods, index: index,),
            //const Divider(height: sqrt1_2,)
          ],
        ),
      ),
    );
  }
}

I tried the below code as experimental inside a ListView.builder() just to understand the concept of Stack and Container.

import 'package:flutter/material.dart';

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

  double itemHeight =0;
  double itemWidth =0;

  @override
  Widget build(BuildContext context) {
    itemHeight = MediaQuery.of(context).size.height;
    itemWidth = MediaQuery.of(context).size.width;
    return Container(
      height: itemHeight * 0.4,
      decoration: BoxDecoration(
          color: Colors.red[400],
          borderRadius: BorderRadius.circular(20)
      ),
      margin: EdgeInsets.symmetric(vertical: 15),
      child: Column(
        children: [
          Stack(

            children: [
              Container(
                //clipBehavior: Clip.hardEdge,
                height: 200,
                decoration: BoxDecoration(
                    color: Colors.blue[100],
                    borderRadius: BorderRadius.only(topLeft: Radius.circular(20), topRight: Radius.circular(20))
                ),
                //margin: EdgeInsets.only(top:70),

              ),
              Container(
                clipBehavior: Clip.hardEdge,
                //height: 100,
                decoration: BoxDecoration(
                    color: Colors.green[200],
                    borderRadius: BorderRadius.only(topLeft: Radius.circular(20), topRight: Radius.circular(20))
                ),
                //margin: EdgeInsets.only(top:70),
                child: Container(
                  //clipBehavior: Clip.hardEdge,
                  height: 100,
                  decoration: BoxDecoration(
                      color: Colors.green[100],
                      borderRadius: BorderRadius.only(topLeft: Radius.circular(20), topRight: Radius.circular(20))
                  ),
                  //margin: EdgeInsets.only(top:70),

                )
              ),




            ],
          ),
        ],
      ),
    );
  }
}


Solution

  • After trying hard and going through "Stack" and "Container" basics, I could able to replicate the desired result of positioning the button at the middle edge of the bottom of the image as shown in figure. I'm posting the code, if anyone wants to do the same.

    Android Simulator Pixel 3a

    Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Center(
            child:
                Text('Container Basics', style: TextStyles.appNameTextStyle)),
      ),
      body: Center(
        child: Container(
          width:300,
          height: 225,
          decoration: BoxDecoration(
            //color: Colors.grey[200]
          ),
          child: Stack(
            alignment: AlignmentDirectional.topCenter,
            children: [
              Container(
                height: 200,
                width: 230,
                decoration: BoxDecoration(
                  color: Colors.green[700],
    
                borderRadius: BorderRadius.circular(20)),
                child: ClipRRect(
                  borderRadius: BorderRadius.circular(20),
                    child: Image.network('https://twamashrita.com/api/images/1705478087845.jpg', fit: BoxFit.fitHeight,)
                )
                /*Text(
                  'Container-1',
                  textAlign: TextAlign.center,
                  style: TextStyles.containerTextStyle,
                ),*/
              ),
              Positioned(
                bottom: 5,
                child: Container(
    
                    //padding: const EdgeInsets.all(10),
                    height: 45,
                    width: 140,
                    decoration: BoxDecoration(
                      color: Colors.white,
                      borderRadius: BorderRadius.circular(10),
                        /*gradient: LinearGradient(
                          begin: Alignment.topLeft,
                            end: Alignment.topRight,
                            colors: [Colors.red, Colors.yellow]
                        ),*/
                        boxShadow: [
                          BoxShadow(
                              color: Colors.grey.withOpacity(0.4),
                              //spreadRadius: 5.0,
                              blurRadius: 5,
                              offset: Offset(0, 2),
                              blurStyle: BlurStyle.solid),
                        ],
                      border: Border.all(color: Colors.grey.withOpacity(0.5))
                    ),
                    child: TextButton.icon(
                      onPressed: () {  },
                      label: Text(
                        'ADD',
                        textAlign: TextAlign.center,
                        style: TextStyles.containerTextStyle,
                      ),
                      icon: Icon(Icons.add_shopping_cart, size: 20, color: Colors.green[600], weight: 20,),
    
                    )
                    /*Text(
                      'ADD',
                      textAlign: TextAlign.center,
                      style: TextStyles.containerTextStyle,
                    )*/
                ),
              ),
            ],
          ),
        ),
      ),
    );
    

    }