TF-248 Change floating button compose email

This commit is contained in:
dab246
2022-02-09 10:49:27 +07:00
committed by Dat H. Pham
parent c0f0b5875b
commit 879692aa54
6 changed files with 200 additions and 4 deletions
+1
View File
@@ -41,6 +41,7 @@ export 'presentation/views/dialog/loading_dialog_builder.dart';
export 'presentation/views/dialog/downloading_file_dialog_builder.dart';
export 'presentation/views/background/background_widget_builder.dart';
export 'presentation/views/html_viewer/html_content_viewer_widget.dart';
export 'presentation/views/floating_button/scrolling_floating_button_animated.dart';
// Resources
export 'presentation/resources/assets_paths.dart';
@@ -50,6 +50,7 @@ class ImagePaths {
String get icChevronDown => _getImagePath('ic_chevron_down.svg');
String get icFilter => _getImagePath('ic_filter.svg');
String get icSearchBar => _getImagePath('ic_search_bar.svg');
String get icCompose => _getImagePath('ic_compose.svg');
String _getImagePath(String imageName) {
return AssetsPaths.images + imageName;
@@ -0,0 +1,176 @@
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'dart:math' as math;
/// Widget to animate the button when scroll down
class ScrollingFloatingButtonAnimated extends StatefulWidget {
/// Function to use when press the button
final GestureTapCallback? onPress;
/// Double value to set the button elevation
final double? elevation;
/// Double value to set the button width
final double? width;
/// Double value to set the button height
final double? height;
/// Value to set the duration for animation
final Duration? duration;
/// Widget to use as button icon
final Widget? icon;
/// Widget to use as button text when button is expanded
final Widget? text;
/// Value to set the curve for animation
final Curve? curve;
/// ScrollController to use to determine when user is on top or not
final ScrollController? scrollController;
/// Double value to set the boundary value when scroll animation is triggered
final double? limitIndicator;
/// Color to set the button background color
final Color? color;
/// Value to indicate if animate or not the icon
final bool? animateIcon;
ScrollingFloatingButtonAnimated(
{Key? key,
required this.icon,
required this.text,
required this.onPress,
required this.scrollController,
this.elevation = 5.0,
this.width = 120.0,
this.height = 60.0,
this.duration = const Duration(milliseconds: 250),
this.curve,
this.limitIndicator = 10.0,
this.color = Colors.blueAccent,
this.animateIcon = true})
: super(key: key);
@override
_ScrollingFloatingButtonAnimatedState createState() =>
_ScrollingFloatingButtonAnimatedState();
}
class _ScrollingFloatingButtonAnimatedState
extends State<ScrollingFloatingButtonAnimated>
with SingleTickerProviderStateMixin {
/// Boolean value to indicate when scroll view is on top
bool _onTop = true;
/// Value to indicate when to show the child widget
bool _visibleText = false;
/// Controller for icon animation
late AnimationController _animationController;
@override
void initState() {
_animationController = new AnimationController(
vsync: this,
duration: Duration(milliseconds: 250),
reverseDuration: Duration(milliseconds: 250),
animationBehavior: AnimationBehavior.normal,
lowerBound: 0,
upperBound: 120,
);
super.initState();
_handleScroll();
}
@override
void dispose() {
widget.scrollController!.removeListener(() {});
_animationController.dispose();
super.dispose();
}
/// Function to add listener for scroll
void _handleScroll() {
ScrollController _scrollController = widget.scrollController!;
_scrollController.addListener(() {
print(_scrollController.position.userScrollDirection);
if (_scrollController.position.pixels > widget.limitIndicator! &&
_scrollController.position.userScrollDirection ==
ScrollDirection.reverse) {
if (widget.animateIcon!) _animationController.forward();
setState(() {
_onTop = false;
});
} else if (_scrollController.position.pixels <= widget.limitIndicator! &&
_scrollController.position.userScrollDirection ==
ScrollDirection.forward) {
if (widget.animateIcon!) _animationController.reverse();
setState(() {
_onTop = true;
});
}
});
}
@override
Widget build(BuildContext context) {
return Card(
elevation: widget.elevation,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(widget.height! / 2))),
child: AnimatedContainer(
curve: widget.curve ?? Curves.easeInOut,
duration: widget.duration!,
height: widget.height,
width: _onTop ? widget.width : widget.height,
onEnd: () {
setState(() {
_visibleText = !_visibleText;
});
},
decoration: BoxDecoration(borderRadius: BorderRadius.all(Radius.circular(widget.height! / 2))),
child: InkWell(
borderRadius: BorderRadius.all(Radius.circular(widget.height! / 2)),
onTap: widget.onPress,
child: Ink(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(widget.height! / 2)),
color: widget.color),
child: Row(
mainAxisAlignment: _onTop ? MainAxisAlignment.spaceEvenly : MainAxisAlignment.center,
children: [
Container(
padding: EdgeInsets.only(left: 16, right: _onTop ? 10 : 16),
child: AnimatedBuilder(
child: widget.icon!,
animation: _animationController,
builder: (BuildContext context, Widget? _widget) {
return Transform.rotate(
angle: (_animationController.value * 3 * math.pi) / 180,
child: _widget!,
);
}),
),
...(_onTop
? [
Expanded(
child: AnimatedOpacity(
opacity: !_visibleText ? 1 : 0,
duration: const Duration(milliseconds: 100),
child: widget.text!,
),
)
]
: []),
],
),
),
),
),
);
}
}