Hahnemann
Hahnemann

Reputation: 4688

Create a button with an image in Flutter?

How do you create a button with an image using Flutter? It seems like the simplest thing to do, but the image does not fill the parent widget completely. This is what I have:

Container(child: ConstrainedBox(
    constraints: BoxConstraints.expand(),
    child: FlatButton(onPressed: null,
        child: Image.asset('path/the_image.png'))))

I followed this post as guidance. My image looks like this:

enter image description here

Notice the padding around the PNG image - it's not in the code. Where does it come from? The PNG itself does not have canvas padding, so this must not be the correct technique.

All I need is a button with an image that fills the entire FlatButton, or another widget I can add actions to, without distorting the image.

Upvotes: 62

Views: 160762

Answers (14)

user12227098
user12227098

Reputation:

Place your image in a gestureDetector like this:

GestureDetector(
    onTap: () {},
    child: Image.asset('path/the_image.png')
)

Upvotes: 4

Suramack
Suramack

Reputation: 135

If you have a rounded rectangle button then follow the below code

TextButton(
                        style: TextButton.styleFrom(
                          alignment: Alignment.topLeft,
                          backgroundColor: Colors.lightBlue,
                          minimumSize: const Size(double.infinity, 200),
                          padding: const EdgeInsets.all(0),
                          shape: RoundedRectangleBorder(
                              borderRadius: BorderRadius.circular(20)),
                        ),
                        onPressed: () => null,
                        child: SizedBox(
                          height: 100,
                          width: 500,
                          child: Stack(
                            children: [
                              **Positioned(
                                top: 0,
                                left: 0,
                                right: 0,**
                                child: ClipRRect(
                                  borderRadius: const BorderRadius.vertical(
                                    top: Radius.circular(20),
                                  ),
                                  child: Image.asset(
                                    'assets/miniMartGrocery.png',
                                    fit: BoxFit.cover,
                                  ),
                                ),
                              ),
                              Positioned(
                                  top: 10,
                                  left: screenSize.width * 0.84,
                                  child: Container(
                                    width: 40,
                                    height: 40,
                                    decoration: BoxDecoration(
                                        borderRadius:
                                            BorderRadius.circular(100),
                                        color: Colors.white),
                                    child: IconButton(
                                      icon: Icon(
                                        FontAwesomeIcons.flag,
                                      ),
                                      onPressed: () => null,
                                    ),
                                  ))
                            ],
                          ),
                        ),
                      ),

Upvotes: 0

DAVE chintan
DAVE chintan

Reputation: 332

FlatButton(
                onPressed: (){},
                color: Colors.orange,
                padding: EdgeInsets.all(10.0),
                child: Column( 
                  children: <Widget>[
                   Image.asset(name),
                    Text("Add")
                  ],
                );
              

you can add icons and images

Upvotes: 1

Deepraj Muwadiya
Deepraj Muwadiya

Reputation: 71

Can use TextButton for this.

 TextButton.icon(
                  style: ButtonStyle(
                      backgroundColor:
                          MaterialStateProperty.all(Colors.white)),
                  onPressed: () {},
                  icon: Image.asset('path/the_image.png'),
                  label: Text(
                    'Button Text',
                    style: TextStyle(
                      color: Colors.black,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                )

Upvotes: 7

Mahmoud Abu Alheja
Mahmoud Abu Alheja

Reputation: 3668

I'm create own inkwell have triple anim that take child and callback onPress for non transparent background like image

class InkWellApp extends StatelessWidget {
  final Function onTap;
  final Widget child;
  final EdgeInsets margin;

  final BorderRadius borderRadius;

  const InkWellApp(
      {Key key,
      this.onTap,
      this.child,
      this.borderRadius = BorderRadius.zero,
      this.margin = EdgeInsets.zero})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: margin,
      child: Stack(
        children: [
          child,
          Positioned.fill(
            child: Material(
              color: Colors.transparent,
              borderRadius: borderRadius,
              child: InkWell(
                borderRadius: borderRadius,
                onTap: onTap,
              ),
            ),
          ),
        ],
      ),
    );
  }
}

and then you can use it inside app with any widget or image like this

 InkWellApp(
        onTap: (){
                //your code here
           },
        child: yourWidget,
  ),

Note : borderRadius and margin is optional parameters

Upvotes: 1

CopsOnRoad
CopsOnRoad

Reputation: 268504

Screenshot:

enter image description here


Code:

InkWell(
  onTap: () {}, // Handle your callback.
  splashColor: Colors.brown.withOpacity(0.5),
  child: Ink(
    height: 100,
    width: 100,
    decoration: BoxDecoration(
      image: DecorationImage(
        image: AssetImage('your_image_asset'),
        fit: BoxFit.cover,
      ),
    ),
  ),
)

Upvotes: 20

Jakub S.
Jakub S.

Reputation: 6090

Image button with Ripple Effect and Text on the bottom

(of course you can remove the text part and Stack)

  Material(
    elevation: 4.0,
    clipBehavior: Clip.hardEdge,
    color: Colors.transparent,
    child: Stack(
      alignment: Alignment.bottomCenter,
      fit: StackFit.passthrough,
      children: [
        Ink.image(
          image: AssetImage(imagePath),
          fit: BoxFit.cover,
          width: 120,
          height: 120,
          child: InkWell(onTap: () {}),
        ),
        Align(
          alignment: Alignment.bottomCenter,
          child: Padding(
            padding: const EdgeInsets.all(8.0),
            child: Text(label, style: const TextStyle(fontSize: 20)),
          ),
        )
      ],
    ),
  );

Upvotes: 0

Prakash Mandal
Prakash Mandal

Reputation: 77

GestureDetector(
    onTap: () {print('click on edit');},
    child: Image(
        image: AssetImage('assets/images/icons/edit-button.png'),
        fit: BoxFit.cover,
        height: 20,
    )
),

Upvotes: 6

wasim
wasim

Reputation: 19

you can do this easily using Stack

      Stack(
        children: <Widget>[
          Container(
            height: MediaQuery.of(context).size.height / 3.6,
            width: MediaQuery.of(context).size.width / 2.2,
            child: ClipRRect(
              borderRadius: BorderRadius.circular(8.0),
              child:imageLoader1(img),
             /* Image.asset(
                "$img",
                fit: BoxFit.cover,
              ),*/
            ),
          ),

          Positioned(
            right: -10.0,
            bottom: 3.0,
            child: RawMaterialButton(
              onPressed: (){},
              fillColor: Colors.white,
              shape: CircleBorder(),
              elevation: 4.0,
              child: Padding(
                padding: EdgeInsets.all(5),
                child: Icon(
                  isFav
                      ?Icons.favorite
                      :Icons.favorite_border,
                  color: Colors.red,
                  size: 17,
                ),
              ),
            ),
          ),
        ],


      ),

Upvotes: 0

Avi Cohen
Avi Cohen

Reputation: 3414

IconButton(
  icon: Image.asset('path/the_image.png'),
  iconSize: 50,
  onPressed: () {},
)

Upvotes: 92

Wagner Braga
Wagner Braga

Reputation: 497

My opinion, the easier way and also most versatile is to use GestureDetector as it allows you to call different functions for different gestures like one tap, double-tap, long tap and so on.

GestureDetector(
                onTap: () => _yourFunction('yourParameter'),
                child: Image.asset('yourimagefolder/yourimage.png'),
              ),

Upvotes: 20

voytez
voytez

Reputation: 1842

Display image icon button with ripple effect over the image when pressed:

          Material(
            // needed
            color: Colors.transparent,
            child: InkWell(
              onTap: () => myOnTap, // needed
              child: Image.asset(
                "assets/resize.png",
                width: 22,
                fit: BoxFit.cover,
              ),
            ),
          )

Upvotes: 9

YashBhalodi
YashBhalodi

Reputation: 403

I think this should work as well. Just specify the padding for the FlatButton to zero.

Container(child: ConstrainedBox(
constraints: BoxConstraints.expand(),
child: FlatButton(
         onPressed: null,
         padding: EdgeInsets.all(0.0),
         child: Image.asset('path/the_image.png'))))

Upvotes: 38

Dario Ielardi
Dario Ielardi

Reputation: 825

Having an image inside a FlatButton might not fit your requirements, as it takes care of some styling ( like that padding ) on its own.

To have full control on your button aspect you might want to build a custom widget ( even a simple Container with a custom BoxDecoration to display the image ) and wrap it with a gesture recognizer to handle user interactions ( a simple tap, in your case ). The simplest implementation would use a GestureDetector, but there are also other widgets, like InkWell that renders a material design ripple over the tappable widget surface on tap.

Upvotes: 16

Related Questions