Skip to content

Instantly share code, notes, and snippets.

@domhel
Created November 10, 2024 22:14
Show Gist options
  • Select an option

  • Save domhel/2d21dd95206983ed56b6d6796929dc82 to your computer and use it in GitHub Desktop.

Select an option

Save domhel/2d21dd95206983ed56b6d6796929dc82 to your computer and use it in GitHub Desktop.
Flutter Opacity Button
// Demo video: https://x.com/dominik_hstein/status/1854972653100233132
enum OpacityButtonState {
idle(opacity: 1.0),
hovering(opacity: 0.75),
tapDown(opacity: 0.5, scale: 0.95),
;
final double opacity;
final double scale;
const OpacityButtonState({
required this.opacity,
this.scale = 1.0,
});
}
class OpacityButton extends StatefulWidget {
final String text;
const OpacityButton({
required this.text,
super.key,
});
@override
State<OpacityButton> createState() => _OpacityButtonState();
}
class _OpacityButtonState extends State<OpacityButton> {
OpacityButtonState _state = OpacityButtonState.idle;
@override
Widget build(BuildContext context) {
return MouseRegion(
cursor: SystemMouseCursors.click,
onExit: (event) => _transitionState(OpacityButtonState.idle),
onHover: (event) => _transitionState(OpacityButtonState.hovering),
child: GestureDetector(
onTapDown: (details) => _transitionState(OpacityButtonState.tapDown),
onTapUp: (details) => _transitionState(OpacityButtonState.hovering),
onTapCancel: () => _transitionState(OpacityButtonState.idle),
child: Opacity(
opacity: 1.0,
child: Transform.scale(
scale: _state.scale,
child: Container(
width: 80,
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
color: Colors.black.withOpacity(_state.opacity),
child: Text(
textAlign: TextAlign.center,
widget.text,
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
color: Colors.white,
),
),
),
),
),
),
);
}
void _transitionState(OpacityButtonState state) {
if (_state != state) {
setState(() {
_state = state;
});
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment