added press animations to toolbar buttons
This commit is contained in:
parent
e427a85f40
commit
c315d5b970
5 changed files with 155 additions and 37 deletions
|
|
@ -25,6 +25,7 @@ abstract class AppConfig {
|
|||
static const double toolbarMaxHeight = 300.0;
|
||||
static const double toolbarMinHeight = 70.0;
|
||||
static const double toolbarMinWidth = 270.0;
|
||||
static const double toolbarButtonsHeight = 50.0;
|
||||
// #Pangea
|
||||
// static const Color primaryColor = Color(0xFF5625BA);
|
||||
// static const Color primaryColorLight = Color(0xFFCCBDEA);
|
||||
|
|
|
|||
|
|
@ -101,11 +101,7 @@ extension MessageModeExtension on MessageMode {
|
|||
}
|
||||
|
||||
//unlocked and active
|
||||
if (this == currentMode) {
|
||||
return Theme.of(context).brightness == Brightness.dark
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Theme.of(context).colorScheme.primary;
|
||||
}
|
||||
if (this == currentMode) return Theme.of(context).colorScheme.primary;
|
||||
|
||||
//unlocked and inactive
|
||||
return Theme.of(context).colorScheme.primaryContainer;
|
||||
|
|
|
|||
|
|
@ -281,9 +281,9 @@ class MessageOverlayController extends State<MessageSelectionOverlay>
|
|||
return reactionsEvents.where((e) => !e.redacted).isNotEmpty;
|
||||
}
|
||||
|
||||
final double toolbarButtonsHeight = 50;
|
||||
double get reactionsHeight => hasReactions ? 28 : 0;
|
||||
double get belowMessageHeight => toolbarButtonsHeight + reactionsHeight;
|
||||
double get belowMessageHeight =>
|
||||
AppConfig.toolbarButtonsHeight + reactionsHeight;
|
||||
|
||||
void setIsPlayingAudio(bool isPlaying) {
|
||||
if (mounted) {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import 'package:fluffychat/config/themes.dart';
|
|||
import 'package:fluffychat/pangea/enum/message_mode_enum.dart';
|
||||
import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/widgets/chat/message_selection_overlay.dart';
|
||||
import 'package:fluffychat/pangea/widgets/pressable_button.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
|
@ -31,6 +32,7 @@ class ToolbarButtons extends StatelessWidget {
|
|||
MatrixState.pangeaController.languageController.userL2?.langCode;
|
||||
|
||||
static const double iconWidth = 36.0;
|
||||
static const buttonSize = 40.0;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
@ -44,7 +46,7 @@ class ToolbarButtons extends StatelessWidget {
|
|||
|
||||
return SizedBox(
|
||||
width: width,
|
||||
height: 50,
|
||||
height: AppConfig.toolbarButtonsHeight,
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
|
|
@ -75,37 +77,50 @@ class ToolbarButtons extends StatelessWidget {
|
|||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: modes
|
||||
.mapIndexed(
|
||||
(index, mode) => IconButton(
|
||||
iconSize: 20,
|
||||
icon: Icon(mode.icon),
|
||||
tooltip: mode.tooltip(context),
|
||||
color: mode == overlayController.toolbarMode
|
||||
? Colors.white
|
||||
: null,
|
||||
isSelected: mode == overlayController.toolbarMode,
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStateProperty.all(
|
||||
mode.iconButtonColor(
|
||||
context,
|
||||
index,
|
||||
overlayController.toolbarMode,
|
||||
pangeaMessageEvent.numberOfActivitiesCompleted,
|
||||
totallyDone,
|
||||
),
|
||||
),
|
||||
children: modes.mapIndexed((index, mode) {
|
||||
final enabled = mode.isUnlocked(
|
||||
index,
|
||||
pangeaMessageEvent.numberOfActivitiesCompleted,
|
||||
totallyDone,
|
||||
);
|
||||
final color = mode.iconButtonColor(
|
||||
context,
|
||||
index,
|
||||
overlayController.toolbarMode,
|
||||
pangeaMessageEvent.numberOfActivitiesCompleted,
|
||||
totallyDone,
|
||||
);
|
||||
return Tooltip(
|
||||
message: mode.tooltip(context),
|
||||
child: PressableButton(
|
||||
width: buttonSize,
|
||||
height: buttonSize,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
enabled: enabled,
|
||||
depressed: !enabled || mode == overlayController.toolbarMode,
|
||||
color: color,
|
||||
onPressed: enabled
|
||||
? () => overlayController.updateToolbarMode(mode)
|
||||
: null,
|
||||
child: AnimatedContainer(
|
||||
duration: FluffyThemes.animationDuration,
|
||||
height: buttonSize,
|
||||
width: buttonSize,
|
||||
decoration: BoxDecoration(
|
||||
color: color,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: Icon(
|
||||
mode.icon,
|
||||
size: 20,
|
||||
color: mode == overlayController.toolbarMode
|
||||
? Colors.white
|
||||
: null,
|
||||
),
|
||||
onPressed: mode.isUnlocked(
|
||||
index,
|
||||
pangeaMessageEvent.numberOfActivitiesCompleted,
|
||||
totallyDone,
|
||||
)
|
||||
? () => overlayController.updateToolbarMode(mode)
|
||||
: null,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
|||
106
lib/pangea/widgets/pressable_button.dart
Normal file
106
lib/pangea/widgets/pressable_button.dart
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
class PressableButton extends StatefulWidget {
|
||||
final double width;
|
||||
final double height;
|
||||
final BorderRadius borderRadius;
|
||||
|
||||
final bool enabled;
|
||||
final bool depressed;
|
||||
|
||||
final Color color;
|
||||
final Widget child;
|
||||
final void Function()? onPressed;
|
||||
|
||||
const PressableButton({
|
||||
required this.width,
|
||||
required this.height,
|
||||
required this.borderRadius,
|
||||
required this.child,
|
||||
required this.onPressed,
|
||||
required this.color,
|
||||
this.enabled = true,
|
||||
this.depressed = false,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
PressableButtonState createState() => PressableButtonState();
|
||||
}
|
||||
|
||||
class PressableButtonState extends State<PressableButton>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late AnimationController _controller;
|
||||
late Animation<double> _tweenAnimation;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_controller = AnimationController(
|
||||
duration: const Duration(milliseconds: 100),
|
||||
vsync: this,
|
||||
);
|
||||
_tweenAnimation = Tween<double>(begin: 5, end: 0).animate(_controller);
|
||||
}
|
||||
|
||||
void _onTapDown(TapDownDetails details) {
|
||||
if (!widget.enabled) return;
|
||||
_controller.forward();
|
||||
}
|
||||
|
||||
void _onTapUp(TapUpDetails details) {
|
||||
if (!widget.enabled) return;
|
||||
_controller.reverse();
|
||||
widget.onPressed?.call();
|
||||
HapticFeedback.mediumImpact();
|
||||
}
|
||||
|
||||
void _onTapCancel() {
|
||||
if (!widget.enabled) return;
|
||||
_controller.reverse();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTapDown: _onTapDown,
|
||||
onTapUp: _onTapUp,
|
||||
onTapCancel: _onTapCancel,
|
||||
child: SizedBox(
|
||||
height: 45,
|
||||
child: Stack(
|
||||
alignment: Alignment.bottomCenter,
|
||||
children: [
|
||||
Container(
|
||||
width: widget.width,
|
||||
height: widget.height,
|
||||
decoration: BoxDecoration(
|
||||
color: Color.alphaBlend(
|
||||
Colors.black.withOpacity(0.25),
|
||||
widget.color,
|
||||
),
|
||||
borderRadius: widget.borderRadius,
|
||||
),
|
||||
),
|
||||
AnimatedBuilder(
|
||||
animation: _tweenAnimation,
|
||||
builder: (context, _) {
|
||||
return Positioned(
|
||||
bottom: widget.depressed ? 0 : _tweenAnimation.value,
|
||||
child: widget.child,
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue