¿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?

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(),
)

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í


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í


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í


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í


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 !!


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í


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

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,
        ),
      ),
    );
  }
}

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),
    ),

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,
            ),
        ),
    ),
)),

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: () {},
                 ),
             ),
         ),

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í


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),
                    ),
                  ),
                ),

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.


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,
    ),
  )
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.