design: Add scale animation hover effects on navrail and story buttons

This commit is contained in:
Krille 2023-08-16 07:18:59 +02:00
parent bc74167bc7
commit f051fc1851
No known key found for this signature in database
2 changed files with 94 additions and 65 deletions

View file

@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/config/app_config.dart';
import '../../config/themes.dart'; import '../../config/themes.dart';
class NaviRailItem extends StatelessWidget { class NaviRailItem extends StatefulWidget {
final String toolTip; final String toolTip;
final bool isSelected; final bool isSelected;
final void Function() onTap; final void Function() onTap;
@ -19,8 +19,23 @@ class NaviRailItem extends StatelessWidget {
Key? key, Key? key,
}) : super(key: key); }) : super(key: key);
@override
State<NaviRailItem> createState() => _NaviRailItemState();
}
class _NaviRailItemState extends State<NaviRailItem> {
bool _hovered = false;
void _onHover(bool hover) {
if (hover == _hovered) return;
setState(() {
_hovered = hover;
});
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final borderRadius = BorderRadius.circular(AppConfig.borderRadius);
return SizedBox( return SizedBox(
height: 64, height: 64,
width: 64, width: 64,
@ -31,7 +46,7 @@ class NaviRailItem extends StatelessWidget {
bottom: 16, bottom: 16,
left: 0, left: 0,
child: AnimatedContainer( child: AnimatedContainer(
width: isSelected ? 4 : 0, width: widget.isSelected ? 4 : 0,
duration: FluffyThemes.animationDuration, duration: FluffyThemes.animationDuration,
curve: FluffyThemes.animationCurve, curve: FluffyThemes.animationCurve,
decoration: BoxDecoration( decoration: BoxDecoration(
@ -44,20 +59,31 @@ class NaviRailItem extends StatelessWidget {
), ),
), ),
Center( Center(
child: IconButton( child: AnimatedScale(
onPressed: onTap, scale: _hovered ? 1.2 : 1.0,
tooltip: toolTip, duration: FluffyThemes.animationDuration,
icon: Material( curve: FluffyThemes.animationCurve,
borderRadius: BorderRadius.circular(AppConfig.borderRadius), child: Material(
color: isSelected borderRadius: borderRadius,
color: widget.isSelected
? Theme.of(context).colorScheme.primaryContainer ? Theme.of(context).colorScheme.primaryContainer
: Theme.of(context).colorScheme.background, : Theme.of(context).colorScheme.background,
child: Padding( child: Tooltip(
padding: const EdgeInsets.symmetric( message: widget.toolTip,
horizontal: 8.0, child: InkWell(
vertical: 8.0, borderRadius: borderRadius,
onTap: widget.onTap,
onHover: _onHover,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 8.0,
vertical: 8.0,
),
child: widget.isSelected
? widget.selectedIcon ?? widget.icon
: widget.icon,
),
), ),
child: isSelected ? selectedIcon ?? icon : icon,
), ),
), ),
), ),

View file

@ -10,6 +10,7 @@ import 'package:matrix/matrix.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/client_stories_extension.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/client_stories_extension.dart';
import 'package:fluffychat/widgets/avatar.dart'; import 'package:fluffychat/widgets/avatar.dart';
import 'package:fluffychat/widgets/matrix.dart'; import 'package:fluffychat/widgets/matrix.dart';
import '../../config/themes.dart';
enum ContextualRoomAction { enum ContextualRoomAction {
mute, mute,
@ -108,7 +109,7 @@ class StoriesHeader extends StatelessWidget {
...client.storiesRooms..remove(ownStoryRoom), ...client.storiesRooms..remove(ownStoryRoom),
]; ];
return SizedBox( return SizedBox(
height: 96, height: 104,
child: ListView.builder( child: ListView.builder(
padding: const EdgeInsets.symmetric(horizontal: 12), padding: const EdgeInsets.symmetric(horizontal: 12),
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
@ -157,7 +158,7 @@ extension on Room {
} }
} }
class _StoryButton extends StatelessWidget { class _StoryButton extends StatefulWidget {
final Profile profile; final Profile profile;
final bool showEditFab; final bool showEditFab;
final bool unread; final bool unread;
@ -177,27 +178,44 @@ class _StoryButton extends StatelessWidget {
Key? key, Key? key,
}) : super(key: key); }) : super(key: key);
@override
State<_StoryButton> createState() => _StoryButtonState();
}
class _StoryButtonState extends State<_StoryButton> {
bool _hovered = false;
void _onHover(bool hover) {
if (hover == _hovered) return;
setState(() {
_hovered = hover;
});
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return SizedBox( return InkWell(
width: 78, onHover: _onHover,
child: InkWell( borderRadius: BorderRadius.circular(7),
borderRadius: BorderRadius.circular(7), onTap: widget.onPressed,
onTap: onPressed, onLongPress: widget.onLongPressed,
onLongPress: onLongPressed, child: Opacity(
child: Opacity( opacity: widget.hasPosts ? 1 : 0.4,
opacity: hasPosts ? 1 : 0.4, child: Padding(
child: Padding( padding: const EdgeInsets.symmetric(horizontal: 4),
padding: const EdgeInsets.symmetric(horizontal: 4), child: Column(
child: Column( children: [
children: [ const SizedBox(height: 8),
const SizedBox(height: 8), AnimatedScale(
Material( scale: _hovered ? 1.15 : 1.0,
duration: FluffyThemes.animationDuration,
curve: FluffyThemes.animationCurve,
child: Material(
borderRadius: BorderRadius.circular(Avatar.defaultSize), borderRadius: BorderRadius.circular(Avatar.defaultSize),
child: Container( child: Container(
padding: const EdgeInsets.all(3), padding: const EdgeInsets.all(3),
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: unread gradient: widget.unread
? const LinearGradient( ? const LinearGradient(
colors: [ colors: [
Colors.red, Colors.red,
@ -208,38 +226,23 @@ class _StoryButton extends StatelessWidget {
end: Alignment.bottomRight, end: Alignment.bottomRight,
) )
: null, : null,
color: unread color: widget.unread
? null ? null
: Theme.of(context).colorScheme.surfaceVariant, : Theme.of(context).colorScheme.surfaceVariant,
borderRadius: BorderRadius.circular(Avatar.defaultSize), borderRadius: BorderRadius.circular(Avatar.defaultSize),
), ),
child: Stack( child: Stack(
children: [ children: [
Material( Hero(
color: Theme.of(context).colorScheme.surface, tag: widget.heroTag,
borderRadius: child: Avatar(
BorderRadius.circular(Avatar.defaultSize), mxContent: widget.profile.avatarUrl,
child: Padding( name: widget.profile.displayName,
padding: const EdgeInsets.all(2.0), size: 72,
child: CircleAvatar( fontSize: 26,
radius: 30,
backgroundColor:
Theme.of(context).colorScheme.surface,
foregroundColor:
Theme.of(context).textTheme.bodyLarge?.color,
child: Hero(
tag: heroTag,
child: Avatar(
mxContent: profile.avatarUrl,
name: profile.displayName,
size: 100,
fontSize: 24,
),
),
),
), ),
), ),
if (showEditFab) if (widget.showEditFab)
Positioned( Positioned(
right: 0, right: 0,
bottom: 0, bottom: 0,
@ -261,19 +264,19 @@ class _StoryButton extends StatelessWidget {
), ),
), ),
), ),
Center( ),
child: Text( Center(
profile.displayName ?? '', child: Text(
maxLines: 1, widget.profile.displayName ?? '',
textAlign: TextAlign.center, maxLines: 1,
style: TextStyle( textAlign: TextAlign.center,
fontSize: 12, style: TextStyle(
fontWeight: unread ? FontWeight.bold : null, fontSize: 12,
), fontWeight: widget.unread ? FontWeight.bold : null,
), ),
), ),
], ),
), ],
), ),
), ),
), ),