¿Cómo crear un botón de icono circular en Flutter?

82

No puedo encontrar ningún ejemplo que muestre cómo crear un círculo IconButtonsimilar al FloatingActionButton. ¿Alguien puede sugerir cómo / qué se necesita para crear un botón personalizado como el FloatingActionButton?

Edmand Looi
fuente

Respuestas:

183

RawMaterialButton es más adecuado, creo.

RawMaterialButton(
  onPressed: () {},
  elevation: 2.0,
  fillColor: Colors.white,
  child: Icon(
    Icons.pause,
    size: 35.0,
  ),
  padding: EdgeInsets.all(15.0),
  shape: CircleBorder(),
)
UpaJah
fuente
Aunque FloatingActionButton también es una opción, este es definitivamente el mejor enfoque.
subwaymatch
10
Obtengo un gran relleno horizontal con este enfoque y no puedo eliminarlo sin importar lo que intente. ¿Algunas ideas?
Rod
4
Resolví este problema usando la propiedad de restricciones de las restricciones RawMaterialButton: BoxConstraints (minWidth: 36.0, maxWidth: 36.0, minHeight: 36.0, maxHeight: 36.0 probablemente no es la mejor solución, pero funcionó.
Mualki
2
para eliminar el relleno alrededor del botón por completo también agreguematerialTapTargetSize: MaterialTapTargetSize.shrinkWrap
kashlo
1
Para mí, para quitar el relleno agregué:constraints: BoxConstraints.expand(width: 42, height: 42),
Leonardo
72

Puedes probar esto, es totalmente personalizable.

ClipOval(
  child: Material(
    color: Colors.blue, // button color
    child: InkWell(
      splashColor: Colors.red, // inkwell color
      child: SizedBox(width: 56, height: 56, child: Icon(Icons.menu)),
      onTap: () {},
    ),
  ),
)

Salida:

ingrese la descripción de la imagen aquí

CopsOnRoad
fuente
1
muchas gracias por esta respuesta @CopsOnRoad
Jason Waku
26

Solo necesitas usar la forma: CircleBorder()

MaterialButton(
  onPressed: () {},
  color: Colors.blue,
  textColor: Colors.white,
  child: Icon(
    Icons.camera_alt,
    size: 24,
  ),
  padding: EdgeInsets.all(16),
  shape: CircleBorder(),
)

ingrese la descripción de la imagen aquí

RodolfoSilva
fuente
20

Puede usar InkWell para hacer eso:

Un área rectangular de un material que responde al tacto.

El siguiente ejemplo demuestra cómo usarlo InkWell. Aviso: no es necesario StatefulWidgetque haga eso. Lo usé para cambiar el estado del conteo.

Ejemplo:

import 'package:flutter/material.dart';

class SettingPage extends StatefulWidget {
  @override
  _SettingPageState createState() => new _SettingPageState();
}

class _SettingPageState extends State<SettingPage> {
  int _count = 0;
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      body: new Center(
        child: new InkWell(// this is the one you are looking for..........
        onTap: () => setState(() => _count++),
        child: new Container(
          //width: 50.0,
          //height: 50.0,
          padding: const EdgeInsets.all(20.0),//I used some padding without fixed width and height
          decoration: new BoxDecoration(
            shape: BoxShape.circle,// You can use like this way or like the below line
            //borderRadius: new BorderRadius.circular(30.0),
            color: Colors.green,
          ),
          child: new Text(_count.toString(), style: new TextStyle(color: Colors.white, fontSize: 50.0)),// You can add a Icon instead of text also, like below.
          //child: new Icon(Icons.arrow_forward, size: 50.0, color: Colors.black38)),
        ),//............
      ),
      ),
    );
  }
}

Si desea beneficiarse de splashColor, highlightColorenvuelva el InkWellwidget utilizando un Materialwidget con círculo de tipo de material. Y luego eliminar decorationen Containerwidget.

Salir:

ingrese la descripción de la imagen aquí

Blasanka
fuente
Blassanka, gracias por la información. Terminé usando FloatingActionButton en su lugar. Pero su solución será útil para otros escenarios en el futuro.
Edmand Looi
1
Este código ya no crea un botón de "círculo" (más).
Loolooii
10

Puede hacer lo siguiente fácilmente:

FlatButton(
      onPressed: () {

       },
      child: new Icon(
        Icons.arrow_forward,
        color: Colors.white,
        size: 20.0,
      ),
      shape: new CircleBorder(),
      color: Colors.black12,
    )

El resultado esingrese la descripción de la imagen aquí

Doan Bui
fuente
8
RawMaterialButton(
  onPressed: () {},
  constraints: BoxConstraints(),
  elevation: 2.0,
  fillColor: Colors.white,
  child: Icon(
    Icons.pause,
    size: 35.0,
  ),
  padding: EdgeInsets.all(15.0),
  shape: CircleBorder(),
)

anote constraints: BoxConstraints(), es para no permitir el relleno en la izquierda.

Feliz aleteo !!

Juan
fuente
7

Si necesita una imagen de fondo, puede usar CircleAvatar con IconButton. Establezca la propiedad backgroundImage.

CircleAvatar(
  backgroundImage: NetworkImage(userAvatarUrl),
)

Ejemplo con botón:

        CircleAvatar(
          backgroundColor: Colors.blue,
          radius: 20,
          child: IconButton(
            padding: EdgeInsets.zero,
            icon: Icon(Icons.add),
            color: Colors.white,
            onPressed: () {},
          ),
        ),

ingrese la descripción de la imagen aquí

vive el amor
fuente
4

De hecho, hay un ejemplo de cómo crear un IconButton circular similar al FloatingActionButton.

Ink(
    decoration: const ShapeDecoration(
        color: Colors.lightBlue,
        shape: CircleBorder(),
    ),
    child: IconButton(
        icon: Icon(Icons.home),
        onPressed: () {},
    ),
)

Para crear un proyecto local con este ejemplo de código, ejecute:

flutter create --sample=material.IconButton.2 mysample
Taiyr Begeyev
fuente
2

Mi contribución:

import 'package:flutter/material.dart';

///
/// Create a circle button with an icon.
///
/// The [icon] argument must not be null.
///
class CircleButton extends StatelessWidget {
  const CircleButton({
    Key key,
    @required this.icon,
    this.padding = const EdgeInsets.all(8.0),
    this.color,
    this.onPressed,
    this.splashColor,
  })  : assert(icon != null),
        super(key: key);

  /// The [Icon] contained ny the circle button.
  final Icon icon;

  /// Empty space to inscribe inside the circle button. The [icon] is
  /// placed inside this padding.
  final EdgeInsetsGeometry padding;

  /// The color to fill in the background of the circle button.
  ///
  /// The [color] is drawn under the [icon].
  final Color color;

  /// The callback that is called when the button is tapped or otherwise activated.
  ///
  /// If this callback is null, then the button will be disabled.
  final void Function() onPressed;

  /// The splash color of the button's [InkWell].
  ///
  /// The ink splash indicates that the button has been touched. It
  /// appears on top of the button's child and spreads in an expanding
  /// circle beginning where the touch occurred.
  ///
  /// The default splash color is the current theme's splash color,
  /// [ThemeData.splashColor].
  final Color splashColor;

  @override
  Widget build(BuildContext context) {
    final ThemeData theme = Theme.of(context);

    return ClipOval(
      child: Material(
        type: MaterialType.button,
        color: color ?? theme.buttonColor,
        child: InkWell(
          splashColor: splashColor ?? theme.splashColor,
          child: Padding(
            padding: padding,
            child: icon,
          ),
          onTap: onPressed,
        ),
      ),
    );
  }
}
Carlos Schwarz
fuente
2

Este código lo ayudará a agregar un botón sin ningún relleno no deseado,

RawMaterialButton(
      elevation: 0.0,
      child: Icon(Icons.add),
      onPressed: (){},
      constraints: BoxConstraints.tightFor(
        width: 56.0,
        height: 56.0,
      ),
      shape: CircleBorder(),
      fillColor: Color(0xFF4C4F5E),
    ),
Akhil
fuente
2

Creé una versión con recorte, elevación y borde correctos. No dudes en personalizarlo.

Material(
    elevation: 2.0,
    clipBehavior: Clip.hardEdge,
    borderRadius: BorderRadius.circular(50),
    color: Colors.white,
    child: InkWell(
        onTap: () => null,
        child: Container(
            padding: EdgeInsets.all(9.0),
            decoration: BoxDecoration(
                shape: BoxShape.circle,
                border: Border.all(color: Colors.blue, width: 1.4)),
           child: Icon(
                Icons.menu,
                size: 22,
                color: Colors.red,
            ),
        ),
    ),
)),
Rodrigo Boratto
fuente
1

También puede usar un RaisedButton con una imagen en el interior (por ejemplo, para el inicio de sesión social) como esta (se necesita una caja de tamaño con fittebox para contraer la imagen en el tamaño especificado):

FittedBox(
    fit: BoxFit.scaleDown,
    child: SizedBox(
        height: 60,
        width: 60,
        child: RaisedButton(
             child: Image.asset(
                 'assets/images/google_logo.png'),
                 shape: StadiumBorder(),
                 color: Colors.white,
                     onPressed: () {},
                 ),
             ),
         ),
Daniel Vilela
fuente
1

Usé este porque me gusta la personalización del radio y el tamaño del borde.

  Material( // pause button (round)
    borderRadius: BorderRadius.circular(50), // change radius size
    color: Colors.blue, //button colour
    child: InkWell(
      splashColor: Colors.blue[900], // inkwell onPress colour
      child: SizedBox(
        width: 35,height: 35, //customisable size of 'button'
        child: Icon(Icons.pause,color: Colors.white,size: 16,),
      ),
      onTap: () {}, // or use onPressed: () {}
    ),
  ),

  Material( // eye button (customised radius)
    borderRadius: BorderRadius.only(
        topRight: Radius.circular(10.0),
        bottomLeft: Radius.circular(50.0),),
    color: Colors.blue,
    child: InkWell(
      splashColor: Colors.blue[900], // inkwell onPress colour
      child: SizedBox(
        width: 40, height: 40, //customisable size of 'button'
        child: Icon(Icons.remove_red_eye,color: Colors.white,size: 16,),),
      onTap: () {}, // or use onPressed: () {}
    ),
  ),

ingrese la descripción de la imagen aquí

Puerto pequeño
fuente
1
ClipOval(
      child: MaterialButton( 
      color: Colors.purple,
      padding: EdgeInsets.all(25.0),
      onPressed: () {},
      shape: RoundedRectangleBorder(
      borderRadius: BorderRadius.circular(30.0)),
            child: Text(
                      '1',
                      style: TextStyle(fontSize: 30.0),
                    ),
                  ),
                ),
Manish Upadhyay
fuente
1

Solución no material:

final double floatingButtonSize = 60;
final IconData floatingButtonIcon;

TouchableOpacity(
  onTap: () {
     /// Do something...
  },
  activeOpacity: 0.7,
  child: Container(
    height: floatingButtonSize,
    width: floatingButtonSize,
    decoration: BoxDecoration(
      borderRadius: BorderRadius.circular(floatingButtonSize / 2),
      color: Theme.of(context).primaryColor,
      boxShadow: [
        BoxShadow(
          blurRadius: 25,
          color: Colors.black.withOpacity(0.2),
          offset: Offset(0, 10),
        )
      ],
    ),
    child: Icon(
      floatingButtonIcon ?? Icons.add,
      color: Colors.white,
    ),
  ),
)

Puede usar GestureDetector en lugar de la biblioteca TouchableOpacity.

Ilya Iksent
fuente
0

Prueba esta tarjeta

Card(
    elevation: 10,
    shape: RoundedRectangleBorder(
      borderRadius: BorderRadius.circular(25.0), // half of height and width of Image
      ),
    child: Image.asset(
      "assets/images/home.png",
      width: 50,
      height: 50,
    ),
  )
Harshal Pathak
fuente