mirror of
https://github.com/DefinedNet/mobile_nebula.git
synced 2025-01-18 19:27:05 +00:00
64d45f66c7
This updates flutter to 3.24.1, the latest stable version, and also updates our flutter dependencies to latest. It targets the latest android sdk, 34, which is required if we want to publish a new version to the Google Play store. I also needed to make a few adjustments to handle deprecations. The biggest change is that I needed to wrap the main widget in MaterialApp to avoid problems with AdaptiveSwitch in iOS.
144 lines
3.8 KiB
Dart
144 lines
3.8 KiB
Dart
import 'dart:io';
|
|
|
|
import 'package:flutter/cupertino.dart';
|
|
import 'package:flutter/material.dart';
|
|
|
|
// This is a button that pushes the bare minimum onto you, it doesn't even respect button themes - unless you tell it to
|
|
class SpecialButton extends StatefulWidget {
|
|
const SpecialButton({Key? key, this.child, this.color, this.onPressed, this.useButtonTheme = false, this.decoration})
|
|
: super(key: key);
|
|
|
|
final Widget? child;
|
|
final Color? color;
|
|
final bool useButtonTheme;
|
|
final BoxDecoration? decoration;
|
|
|
|
final GestureTapCallback? onPressed;
|
|
|
|
@override
|
|
_SpecialButtonState createState() => _SpecialButtonState();
|
|
}
|
|
|
|
class _SpecialButtonState extends State<SpecialButton> with SingleTickerProviderStateMixin {
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Platform.isAndroid ? _buildAndroid() : _buildGeneric();
|
|
}
|
|
|
|
Widget _buildAndroid() {
|
|
var textStyle;
|
|
if (widget.useButtonTheme) {
|
|
textStyle = Theme.of(context).textTheme.labelLarge;
|
|
}
|
|
|
|
return Material(
|
|
textStyle: textStyle,
|
|
child: Ink(
|
|
decoration: widget.decoration,
|
|
color: widget.color,
|
|
child: InkWell(
|
|
child: widget.child,
|
|
onTap: widget.onPressed,
|
|
)));
|
|
}
|
|
|
|
Widget _buildGeneric() {
|
|
var textStyle = CupertinoTheme.of(context).textTheme.textStyle;
|
|
if (widget.useButtonTheme) {
|
|
textStyle = CupertinoTheme.of(context).textTheme.actionTextStyle;
|
|
}
|
|
|
|
return Container(
|
|
decoration: widget.decoration,
|
|
child: GestureDetector(
|
|
behavior: HitTestBehavior.opaque,
|
|
onTapDown: _handleTapDown,
|
|
onTapUp: _handleTapUp,
|
|
onTapCancel: _handleTapCancel,
|
|
onTap: widget.onPressed,
|
|
child: Semantics(
|
|
button: true,
|
|
child: FadeTransition(
|
|
opacity: _opacityAnimation!,
|
|
child: DefaultTextStyle(style: textStyle, child: Container(child: widget.child, color: widget.color)),
|
|
),
|
|
),
|
|
));
|
|
}
|
|
|
|
// Eyeballed values. Feel free to tweak.
|
|
static const Duration kFadeOutDuration = Duration(milliseconds: 10);
|
|
static const Duration kFadeInDuration = Duration(milliseconds: 100);
|
|
final Tween<double> _opacityTween = Tween<double>(begin: 1.0);
|
|
|
|
AnimationController? _animationController;
|
|
Animation<double>? _opacityAnimation;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_animationController = AnimationController(
|
|
duration: const Duration(milliseconds: 200),
|
|
value: 0.0,
|
|
vsync: this,
|
|
);
|
|
_opacityAnimation = _animationController!.drive(CurveTween(curve: Curves.decelerate)).drive(_opacityTween);
|
|
_setTween();
|
|
}
|
|
|
|
@override
|
|
void didUpdateWidget(SpecialButton old) {
|
|
super.didUpdateWidget(old);
|
|
_setTween();
|
|
}
|
|
|
|
void _setTween() {
|
|
_opacityTween.end = 0.4;
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_animationController?.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
bool _buttonHeldDown = false;
|
|
|
|
void _handleTapDown(TapDownDetails event) {
|
|
if (!_buttonHeldDown) {
|
|
_buttonHeldDown = true;
|
|
_animate();
|
|
}
|
|
}
|
|
|
|
void _handleTapUp(TapUpDetails event) {
|
|
if (_buttonHeldDown) {
|
|
_buttonHeldDown = false;
|
|
_animate();
|
|
}
|
|
}
|
|
|
|
void _handleTapCancel() {
|
|
if (_buttonHeldDown) {
|
|
_buttonHeldDown = false;
|
|
_animate();
|
|
}
|
|
}
|
|
|
|
void _animate() {
|
|
if (_animationController == null || _animationController!.isAnimating) {
|
|
return;
|
|
}
|
|
|
|
final bool wasHeldDown = _buttonHeldDown;
|
|
final TickerFuture ticker = _buttonHeldDown
|
|
? _animationController!.animateTo(1.0, duration: kFadeOutDuration)
|
|
: _animationController!.animateTo(0.0, duration: kFadeInDuration);
|
|
|
|
ticker.then<void>((void value) {
|
|
if (mounted && wasHeldDown != _buttonHeldDown) {
|
|
_animate();
|
|
}
|
|
});
|
|
}
|
|
}
|