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.
104 lines
2.7 KiB
Dart
104 lines
2.7 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:native_device_orientation/native_device_orientation.dart';
|
|
|
|
class CircleButton extends StatefulWidget {
|
|
final VoidCallback onLongPress;
|
|
final VoidCallback onPressed;
|
|
final GestureTapDownCallback onTapDown;
|
|
final VoidCallback onTapCancel;
|
|
final Widget child;
|
|
final Color color;
|
|
final double radius;
|
|
|
|
const CircleButton({
|
|
Key key,
|
|
this.onLongPress,
|
|
this.onPressed,
|
|
this.child,
|
|
this.color,
|
|
this.radius = 25.0,
|
|
this.onTapCancel,
|
|
this.onTapDown,
|
|
}) : assert(radius != null),
|
|
super(key: key);
|
|
|
|
@override
|
|
_CircleButtonState createState() => _CircleButtonState();
|
|
}
|
|
|
|
class _CircleButtonState extends State<CircleButton> {
|
|
double _rotationAngle = 0.0;
|
|
|
|
final Stream<NativeDeviceOrientation> _orientationStream = NativeDeviceOrientationCommunicator().onOrientationChanged(useSensor: true);
|
|
StreamSubscription<NativeDeviceOrientation> _orientationSubscription;
|
|
|
|
void _handleOrientationChange(NativeDeviceOrientation orientation) {
|
|
var targetAngle = 0.0;
|
|
switch (orientation) {
|
|
case NativeDeviceOrientation.unknown:
|
|
case NativeDeviceOrientation.portraitUp:
|
|
targetAngle = 0.0;
|
|
break;
|
|
case NativeDeviceOrientation.portraitDown:
|
|
targetAngle = 180.0;
|
|
break;
|
|
case NativeDeviceOrientation.landscapeLeft:
|
|
targetAngle = 90.0;
|
|
break;
|
|
case NativeDeviceOrientation.landscapeRight:
|
|
targetAngle = 270.0;
|
|
break;
|
|
}
|
|
setState(() {
|
|
_rotationAngle = targetAngle;
|
|
});
|
|
}
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_orientationSubscription = _orientationStream.listen(
|
|
_handleOrientationChange,
|
|
onError: (dynamic err) => print(err),
|
|
);
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
super.dispose();
|
|
_orientationSubscription.cancel();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final size = 2 * widget.radius;
|
|
|
|
return Container(
|
|
width: size,
|
|
height: size,
|
|
decoration: BoxDecoration(
|
|
color: (widget.color ?? Colors.blue).withAlpha(200),
|
|
borderRadius: BorderRadius.all(
|
|
Radius.circular(widget.radius),
|
|
),
|
|
),
|
|
child: GestureDetector(
|
|
onLongPress: widget.onLongPress,
|
|
onTapDown: widget.onTapDown,
|
|
onTapCancel: widget.onTapCancel,
|
|
child: RawMaterialButton(
|
|
onPressed: widget.onPressed,
|
|
child: RotationTransition(
|
|
child: widget.child,
|
|
turns: AlwaysStoppedAnimation<double>(_rotationAngle / 360),
|
|
),
|
|
elevation: 0,
|
|
shape: const CircleBorder(),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|