RippleRevealButton class
Botón animado con efecto ripple/circular reveal que alterna entre dos estados.
Genera un círculo que se expande desde el punto del toque hasta cubrir el área del botón, creando una transición suave entre dos contenidos y dos esquemas de color.
Ideal para: toggles, switches personalizados, botones de favorito/like, modo claro/oscuro, y cualquier control que requiera feedback visual claro.
Cómo funciona
- El fondo alterna entre
selectedBackgroundColoryunselectedBackgroundColor. - El ripple dibuja un círculo del color correspondiente al estado destino.
- El contenido alterna entre
selectedChild(seleccionado) yunselectedChild(no seleccionado).
Anatomía del efecto
Estado inicial: NO SELECCIONADO
┌─────────────────────┐
│ unselectedChild │ ← Fondo: unselectedBackgroundColor
└─────────────────────┘
Al tocar:
┌─────────────────────┐
│ ●──────────── │ ← Círculo expandiéndose (selectedRippleColor)
└─────────────────────┘
Estado final: SELECCIONADO
┌─────────────────────┐
│ selectedChild │ ← Fondo: selectedBackgroundColor
└─────────────────────┘
Buenas prácticas
- Usa colores contrastantes entre fondo y ripple para maximizar el impacto visual.
- Asegúrate de que
selectedChildyunselectedChildsean visualmente distintos. - Para esquinas suaves, incrementa
borderRadius(mínimo 2.0). - Si controlas el estado externamente, usa
isSelectedy actualízalo consetState.
Ejemplos
Ejemplo básico (toggle ON/OFF)
RippleRevealButton(
selectedChild: const Text(
'ON',
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
),
unselectedChild: const Text(
'OFF',
style: TextStyle(color: Colors.black, fontWeight: FontWeight.bold),
),
selectedBackgroundColor: Colors.black,
unselectedBackgroundColor: Colors.white,
selectedRippleColor: Colors.black,
unselectedRippleColor: Colors.white,
onPressed: () => debugPrint('¡Alternado!'),
)
Ejemplo con iconos (favorito)
RippleRevealButton(
selectedChild: const Icon(Icons.favorite, color: Colors.white),
unselectedChild: const Icon(Icons.favorite_border, color: Colors.red),
selectedBackgroundColor: Colors.red,
unselectedBackgroundColor: Colors.grey.shade100,
selectedRippleColor: Colors.red,
unselectedRippleColor: Colors.grey.shade300,
height: 56,
width: 56,
borderRadius: 28,
onPressed: () => print('Favorito alternado'),
)
Ejemplo con control externo
class MyToggle extends StatefulWidget {
const MyToggle({super.key});
@override
State<MyToggle> createState() => _MyToggleState();
}
class _MyToggleState extends State<MyToggle> {
bool _isActive = false;
@override
Widget build(BuildContext context) {
return RippleRevealButton(
isSelected: _isActive,
selectedChild: const Text('Activo'),
unselectedChild: const Text('Inactivo'),
selectedBackgroundColor: Colors.blue,
unselectedBackgroundColor: Colors.grey.shade200,
selectedRippleColor: Colors.blue,
unselectedRippleColor: Colors.grey,
onPressed: () => setState(() => _isActive = !_isActive),
);
}
}
Ejemplo con borde decorativo
RippleRevealButton(
selectedChild: const Text(
'Premium',
style: TextStyle(color: Colors.amber, fontWeight: FontWeight.bold),
),
unselectedChild: const Text('Básico'),
selectedBackgroundColor: Colors.black,
unselectedBackgroundColor: Colors.white,
selectedRippleColor: Colors.amber,
unselectedRippleColor: Colors.black,
border: Border.all(color: Colors.amber, width: 2),
borderRadius: 16,
height: 56,
onPressed: () => print('Plan cambiado'),
)
Notas técnicas
- El cursor se establece automáticamente a
clicken plataformas desktop. - El ripple se origina en las coordenadas exactas del tap.
animationDurationcontrola la velocidad de la expansión circular.- El widget es completamente responsivo y se adapta al tamaño disponible.
- Inheritance
-
- Object
- DiagnosticableTree
- Widget
- StatefulWidget
- RippleRevealButton
Constructors
- RippleRevealButton({Key? key, required Widget selectedChild, Widget? unselectedChild, required VoidCallback onPressed, Color? selectedBackgroundColor, Color? unselectedBackgroundColor, Color? selectedRippleColor, Color? unselectedRippleColor, double width = double.infinity, double height = 48, double? borderRadius, Duration? animationDuration, bool? isSelected, BoxBorder? border, EdgeInsetsGeometry padding = const EdgeInsets.symmetric(horizontal: 16), AlignmentGeometry alignment = Alignment.center, @Deprecated('Use selectedChild instead. Will be removed in v2.0.0') Widget? widgetA, @Deprecated('Use unselectedChild instead. Will be removed in v2.0.0') Widget? widgetB, @Deprecated('Use selectedBackgroundColor instead. Will be removed in v2.0.0') Color? backgroundColorA, @Deprecated('Use unselectedBackgroundColor instead. Will be removed in v2.0.0') Color? backgroundColorB, @Deprecated('Use selectedRippleColor instead. Will be removed in v2.0.0') Color? rippleColorA, @Deprecated('Use unselectedRippleColor instead. Will be removed in v2.0.0') Color? rippleColorB, @Deprecated('Use borderRadius instead. Will be removed in v2.0.0') double? radius, @Deprecated('Use animationDuration instead. Will be removed in v2.0.0') Duration? duration, @Deprecated('Use isSelected instead. Will be removed in v2.0.0') bool? selected})
-
Crea un RippleRevealButton con efecto de ripple circular.
const
Properties
- alignment → AlignmentGeometry
-
Alineación del contenido dentro del botón.
final
- animationDuration → Duration
-
Duración de la animación del efecto ripple.
final
- border → BoxBorder?
-
Borde decorativo opcional aplicado al contorno del botón.
final
- borderRadius → double
-
Radio de redondeo de las esquinas del botón.
final
- hashCode → int
-
The hash code for this object.
no setterinherited
- height → double
-
Alto del botón en píxeles lógicos.
final
- isSelected → bool?
-
Controla el estado del botón externamente (opcional).
final
- key → Key?
-
Controls how one widget replaces another widget in the tree.
finalinherited
- onPressed → VoidCallback
-
Callback ejecutado al presionar el botón, antes de cambiar el estado.
final
- padding → EdgeInsetsGeometry
-
Espaciado interno entre el borde del botón y su contenido.
final
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
- selectedBackgroundColor → Color
-
Color de fondo cuando el botón está seleccionado.
final
- selectedChild → Widget
-
Widget mostrado cuando el botón está en estado seleccionado.
final
- selectedRippleColor → Color
-
Color del círculo de ripple al transicionar hacia el estado seleccionado.
final
- unselectedBackgroundColor → Color
-
Color de fondo cuando el botón está no seleccionado.
final
- unselectedChild → Widget?
-
Widget mostrado cuando el botón está en estado no seleccionado.
final
- unselectedRippleColor → Color
-
Color del círculo de ripple al transicionar hacia el estado no seleccionado.
final
- width → double
-
Ancho del botón en píxeles lógicos.
final
Methods
-
createElement(
) → StatefulElement -
Creates a StatefulElement to manage this widget's location in the tree.
inherited
-
createState(
) → State< RippleRevealButton> -
Creates the mutable state for this widget at a given location in the tree.
override
-
debugDescribeChildren(
) → List< DiagnosticsNode> -
Returns a list of DiagnosticsNode objects describing this node's
children.
inherited
-
debugFillProperties(
DiagnosticPropertiesBuilder properties) → void -
Add additional properties associated with the node.
inherited
-
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
toDiagnosticsNode(
{String? name, DiagnosticsTreeStyle? style}) → DiagnosticsNode -
Returns a debug representation of the object that is used by debugging
tools and by DiagnosticsNode.toStringDeep.
inherited
-
toString(
{DiagnosticLevel minLevel = DiagnosticLevel.info}) → String -
A string representation of this object.
inherited
-
toStringDeep(
{String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug, int wrapWidth = 65}) → String -
Returns a string representation of this node and its descendants.
inherited
-
toStringShallow(
{String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) → String -
Returns a one-line detailed description of the object.
inherited
-
toStringShort(
) → String -
A short, textual description of this widget.
inherited
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited