You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
107 lines
2.8 KiB
Dart
107 lines
2.8 KiB
Dart
import 'dart:async';
|
|
import 'dart:math' as math;
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
class ButtonToProgress extends StatefulWidget {
|
|
final double height;
|
|
final double progressHeight;
|
|
final String loadingText;
|
|
final Duration duration;
|
|
final TextStyle loadingTextStyle;
|
|
final VoidCallback onPressed;
|
|
final Stream<bool> onLoading;
|
|
final Widget child;
|
|
|
|
const ButtonToProgress({
|
|
Key key,
|
|
this.height = 40.0,
|
|
this.progressHeight = 5.0,
|
|
this.loadingText,
|
|
this.duration = const Duration(milliseconds: 300),
|
|
this.loadingTextStyle,
|
|
this.onPressed,
|
|
this.onLoading,
|
|
@required this.child,
|
|
}) : assert(child != null),
|
|
assert(height != null && height > 0),
|
|
assert(progressHeight != null && progressHeight > 0 && progressHeight <= height),
|
|
super(key: key);
|
|
|
|
@override
|
|
_ButtonToProgressState createState() => _ButtonToProgressState();
|
|
}
|
|
|
|
class _ButtonToProgressState extends State<ButtonToProgress> {
|
|
double _height;
|
|
double _opacity = 0;
|
|
bool _isLoading = false;
|
|
|
|
StreamSubscription<bool> _subscription;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_height = widget.height;
|
|
if (widget.onLoading != null) {
|
|
_subscription = widget.onLoading.listen((bool isLoading) {
|
|
setState(() {
|
|
_isLoading = isLoading;
|
|
_height = isLoading ? widget.progressHeight : widget.height;
|
|
_opacity = isLoading ? 1 : 0;
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
if (_subscription != null) {
|
|
_subscription.cancel();
|
|
}
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Container(
|
|
height: widget.height,
|
|
child: Stack(
|
|
children: [
|
|
if (widget.loadingText == null)
|
|
Container()
|
|
else
|
|
Padding(
|
|
padding: EdgeInsets.only(bottom: widget.progressHeight),
|
|
child: AnimatedOpacity(
|
|
child: Center(
|
|
child: FittedBox(
|
|
child: Text(
|
|
widget.loadingText,
|
|
style: widget.loadingTextStyle,
|
|
),
|
|
),
|
|
),
|
|
opacity: _opacity,
|
|
duration: Duration(milliseconds: widget.duration.inMilliseconds + 200),
|
|
curve: Curves.easeInCubic,
|
|
),
|
|
),
|
|
AnimatedPadding(
|
|
duration: widget.duration,
|
|
padding: EdgeInsets.only(
|
|
top: math.max(widget.height - _height, 0),
|
|
),
|
|
child: AnimatedContainer(
|
|
duration: widget.duration,
|
|
height: _height,
|
|
width: double.infinity,
|
|
child: _isLoading ? const LinearProgressIndicator() : widget.child,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|