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: Tooltip(
message: widget.toolTip,
child: InkWell(
borderRadius: borderRadius,
onTap: widget.onTap,
onHover: _onHover,
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
horizontal: 8.0, horizontal: 8.0,
vertical: 8.0, vertical: 8.0,
), ),
child: isSelected ? selectedIcon ?? icon : icon, child: widget.isSelected
? widget.selectedIcon ?? widget.icon
: widget.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: onPressed, onTap: widget.onPressed,
onLongPress: onLongPressed, onLongPress: widget.onLongPressed,
child: Opacity( child: Opacity(
opacity: hasPosts ? 1 : 0.4, opacity: widget.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),
Material( AnimatedScale(
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:
BorderRadius.circular(Avatar.defaultSize),
child: Padding(
padding: const EdgeInsets.all(2.0),
child: CircleAvatar(
radius: 30,
backgroundColor:
Theme.of(context).colorScheme.surface,
foregroundColor:
Theme.of(context).textTheme.bodyLarge?.color,
child: Hero(
tag: heroTag,
child: Avatar( child: Avatar(
mxContent: profile.avatarUrl, mxContent: widget.profile.avatarUrl,
name: profile.displayName, name: widget.profile.displayName,
size: 100, size: 72,
fontSize: 24, fontSize: 26,
), ),
), ),
), if (widget.showEditFab)
),
),
if (showEditFab)
Positioned( Positioned(
right: 0, right: 0,
bottom: 0, bottom: 0,
@ -261,14 +264,15 @@ class _StoryButton extends StatelessWidget {
), ),
), ),
), ),
),
Center( Center(
child: Text( child: Text(
profile.displayName ?? '', widget.profile.displayName ?? '',
maxLines: 1, maxLines: 1,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
fontSize: 12, fontSize: 12,
fontWeight: unread ? FontWeight.bold : null, fontWeight: widget.unread ? FontWeight.bold : null,
), ),
), ),
), ),
@ -276,7 +280,6 @@ class _StoryButton extends StatelessWidget {
), ),
), ),
), ),
),
); );
} }
} }