-
Notifications
You must be signed in to change notification settings - Fork 774
Make RadialAxis in SfRadialGauge Draggable #631 #632
Unanswered
Rayyanmaq1
asked this question in
Q&A
-
Is there any way to make RadialAxis in SfRadialGauge draggable in such a way if you tap on the axis and drag it the whole axis as well as both markers should drag with it accordingly.
Minimum sample Code.
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:syncfusion_flutter_gauges/gauges.dart';
class SleepTrackerSample extends StatefulWidget {
/// Creates the gauge sleep tracker sample.
const SleepTrackerSample({Key key}) : super(key: key);
@override
_SleepTrackerSampleState createState() => _SleepTrackerSampleState();
}
class _SleepTrackerSampleState extends State<SleepTrackerSample> {
_SleepTrackerSampleState();
bool isCardView = false;
@override
Widget build(BuildContext context) {
final bool isLandscape =
MediaQuery.of(context).orientation == Orientation.landscape
? true
: false;
final bool isDarkTheme =
Theme.of(context).brightness == Brightness.dark ? true : false;
return Center(
child: SingleChildScrollView(
child: Column(
children: <Widget>[
SizedBox(
child: Stack(
alignment: Alignment.center,
children: [
SfRadialGauge(
axes: <RadialAxis>[
RadialAxis(
canRotateLabels: true,
showFirstLabel: false,
showLastLabel: true,
useRangeColorForAxis: true,
axisLineStyle: AxisLineStyle(
thickness: _tickness,
thicknessUnit: GaugeSizeUnit.factor,
color: Colors.lightBlue[50]),
minorTicksPerInterval: 10,
majorTickStyle: const MajorTickStyle(length: 10),
maximum: 12,
interval: 3,
startAngle: 90,
endAngle: 90,
onAxisTapped: (val) {
print('Axis tapped on $val');
},
onLabelCreated: (AxisLabelCreatedArgs args) {
if (args.text == '6') {
args.text = '12';
} else if (args.text == '9') {
args.text = '3';
} else if (args.text == '12') {
args.text = '6';
} else if (args.text == '3') {
args.text = '9';
}
},
pointers: <GaugePointer>[
WidgetPointer(
enableDragging: true,
value: _wakeupTimeValue,
onValueChanged: _handleWakeupTimeValueChanged,
onValueChanging: _handleWakeupTimeValueChanging,
onValueChangeStart: _handleWakeupTimeValueStart,
onValueChangeEnd: _handleWakeupTimeValueEnd,
child: Container(
decoration: BoxDecoration(
color: Colors.blue,
shape: BoxShape.circle,
border: Border.all(
color: isDarkTheme
? Colors.white.withOpacity(0.1)
: Colors.black.withOpacity(0.1),
width: 0.0,
)),
height: _wakeupTimePointerHeight,
width: _wakeupTimePointerWidth,
child: const Center(
child: Icon(
Icons.bedtime,
size: 15,
color: Colors.white,
)),
)),
WidgetPointer(
enableDragging: true,
value: _bedTimeValue,
onValueChanged: _handleBedTimeValueChanged,
onValueChanging: _handleBedTimeValueChanging,
onValueChangeStart: _handleBedTimeValueStart,
onValueChangeEnd: _handleBedTimeValueEnd,
child: Container(
decoration: BoxDecoration(
color: Colors.blue,
shape: BoxShape.circle,
border: Border.all(
color: isDarkTheme
? Colors.white.withOpacity(0.1)
: Colors.black.withOpacity(0.1),
width: 0.0,
)),
height: _bedTimePointerHeight,
width: _bedTimePointerWidth,
child: const Center(
child: Icon(
Icons.wb_sunny,
color: Colors.white,
size: 15,
)),
),
),
],
ranges: <GaugeRange>[
GaugeRange(
endValue: _bedTimeValue,
sizeUnit: GaugeSizeUnit.factor,
startValue: _wakeupTimeValue,
color: Colors.blue,
startWidth: _tickness,
endWidth: _tickness)
],
annotations: <GaugeAnnotation>[
GaugeAnnotation(
widget: SizedBox(
width: 300,
height: 200,
child: Stack(
alignment: AlignmentDirectional.center,
children: <Widget>[
AnimatedPositioned(
right: (_isWakeupTime && !_isBedTime)
? isWebOrDesktop
? 94
: isCardView
? 110
: 120
: isWebOrDesktop
? 155
: (isLandscape || isCardView)
? 152
: 180,
duration:
const Duration(milliseconds: 300),
curve: Curves.decelerate,
child: AnimatedOpacity(
opacity: _isWakeupTime ? 1.0 : 0.0,
duration:
(_isWakeupTime && _isBedTime)
? const Duration(
milliseconds: 800)
: const Duration(
milliseconds: 200),
child: CustomAnimatedBuilder(
value: !_isBedTime
? (isWebOrDesktop || isCardView)
? 1.1
: 2.0
: (isWebOrDesktop || isCardView)
? 0.6
: 1.3,
curve: Curves.decelerate,
duration: const Duration(
milliseconds: 300),
builder: (BuildContext context,
Widget child,
Animation<dynamic>
animation) =>
Transform.scale(
scale: animation.value,
child: child,
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
'4 Apr',
style: TextStyle(
fontSize: isWebOrDesktop
? 24
: isCardView
? 14
: 10,
color: Colors.blue,
),
),
const SizedBox(height: 4),
Text(
_wakeupTimeAnnotation,
style: TextStyle(
color: Colors.blue,
fontSize: isWebOrDesktop
? 28
: isCardView
? 20
: 16),
),
],
),
),
),
),
AnimatedOpacity(
opacity: (_isBedTime && _isWakeupTime)
? 1.0
: 0.0,
duration: (_isWakeupTime && _isBedTime)
? const Duration(milliseconds: 800)
: const Duration(milliseconds: 200),
child: Container(
margin: (isLandscape || isCardView)
? const EdgeInsets.only(top: 8.0)
: const EdgeInsets.only(
top: 16.0),
child: const Text(
'-',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 25,
color: Colors.blue,
),
),
),
),
AnimatedPositioned(
left: (_isBedTime && !_isWakeupTime)
? isWebOrDesktop
? 94
: isCardView
? 110
: 120
: isWebOrDesktop
? 155
: (isLandscape || isCardView)
? 152
: 180,
duration:
const Duration(milliseconds: 300),
curve: Curves.decelerate,
child: AnimatedOpacity(
opacity: _isBedTime ? 1.0 : 0.0,
duration:
(_isWakeupTime && _isBedTime)
? const Duration(
milliseconds: 800)
: const Duration(
milliseconds: 200),
child: CustomAnimatedBuilder(
value: !_isWakeupTime
? (isWebOrDesktop || isCardView)
? 1.1
: 2.0
: (isWebOrDesktop || isCardView)
? 0.6
: 1.3,
curve: Curves.decelerate,
duration: const Duration(
milliseconds: 300),
builder: (BuildContext context,
Widget child,
Animation<dynamic>
animation) =>
Transform.scale(
scale: animation.value,
child: child,
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
'5 Apr',
style: TextStyle(
fontSize: isWebOrDesktop
? 24
: isCardView
? 14
: 10,
color: Colors.blue,
),
),
const SizedBox(height: 4),
Text(
_bedTimeAnnotation,
style: TextStyle(
color: Colors.blue,
fontSize: isWebOrDesktop
? 28
: isCardView
? 20
: 16),
),
],
),
),
),
),
],
),
),
positionFactor: 0.05,
angle: 0),
])
],
),
],
),
),
if (!isCardView) const SizedBox(height: 15),
if (!isCardView)
Text(
_sleepMinutes == '00'
? '$_sleepHours hrs'
: '$_sleepHours hrs ' '$_sleepMinutes mins',
style: TextStyle(
fontSize: isCardView ? 14 : 20,
fontWeight: FontWeight.w500),
),
if (!isCardView) const SizedBox(height: 4),
if (!isCardView)
Text(
'Sleep time',
style: TextStyle(
fontSize: isCardView ? 10 : 15,
fontWeight: FontWeight.w400),
)
],
),
),
);
}
/// Dragged pointer new value is updated to range.
void _handleWakeupTimeValueChanged(double value) {
print(value);
setState(() {
_wakeupTimeValue = value;
// ignore: no_leading_underscores_for_local_identifiers
final int _value = _wakeupTimeValue.abs().toInt();
// ignore: no_leading_underscores_for_local_identifiers
final int _hourValue = _value;
final List<String> minList =
_wakeupTimeValue.toStringAsFixed(2).split('.');
double currentMinutes = double.parse(minList[1]);
currentMinutes = (currentMinutes * 60) / 100;
final String minutesValue = currentMinutes.toStringAsFixed(0);
final double hour = (_hourValue >= 0 && _hourValue <= 6)
? (_hourValue + 6).toDouble()
: (_hourValue >= 6 && _hourValue <= 12)
? (_hourValue - 6).toDouble()
: 0;
final String hourValue = hour.toString().split('.')[0];
_wakeupTimeAnnotation =
((hour >= 6 && hour < 10) ? '0' + hourValue : hourValue) +
':' +
(minutesValue.length == 1 ? '0' + minutesValue : minutesValue) +
(_hourValue >= 6 ? ' pm' : ' pm');
_wakeupTime = (_hourValue + 6 < 10
? '0' + _hourValue.toString()
: _hourValue.toString()) +
':' +
(minutesValue.length == 1 ? '0' + minutesValue : minutesValue);
final DateFormat dateFormat = DateFormat('HH:mm');
final DateTime wakeup = dateFormat.parse(_wakeupTime);
final DateTime sleep =
dateFormat.parse(_bedTime == '09:00 pm' ? '12:00' : _bedTime);
final String sleepDuration = sleep.difference(wakeup).toString();
_sleepHours = sleepDuration.split(':')[0];
_sleepMinutes = sleepDuration.split(':')[1];
});
}
/// Cancelled the dragging when pointer value reaching the axis end/start value, greater/less than another
/// pointer value
void _handleWakeupTimeValueChanging(ValueChangingArgs args) {
if (args.value >= 6 && args.value < 12) {
args.cancel = true;
}
_wakeupTimePointerWidth = _wakeupTimePointerHeight = 40.0;
}
/// Cancelled the dragging when pointer value reaching the axis end/start value, greater/less than another
/// pointer value
void _handleBedTimeValueChanging(ValueChangingArgs args) {
if (args.value >= 0 && args.value < 6) {
args.cancel = true;
}
_bedTimePointerWidth = _bedTimePointerHeight = 40.0;
}
/// Dragged pointer new value is updated to range.
void _handleBedTimeValueChanged(double value) {
setState(() {
_bedTimeValue = value;
// ignore: no_leading_underscores_for_local_identifiers
final int _value = _bedTimeValue.abs().toInt();
// ignore: no_leading_underscores_for_local_identifiers
final int _hourValue = _value;
final List<String> minList = _bedTimeValue.toStringAsFixed(2).split('.');
double currentMinutes = double.parse(minList[1]);
currentMinutes = (currentMinutes * 60) / 100;
final String minutesValue = currentMinutes.toStringAsFixed(0);
_bedTimeAnnotation = ((_hourValue >= 0 && _hourValue <= 6)
? (_hourValue + 6).toString()
: (_hourValue >= 6 && _hourValue <= 12)
? '0' + (_hourValue - 6).toString()
: '') +
':' +
(minutesValue.length == 1 ? '0' + minutesValue : minutesValue) +
(_value >= 6 ? ' am' : ' pm');
_bedTime = (_hourValue < 10
? '0' + _hourValue.toString()
: _hourValue.toString()) +
':' +
(minutesValue.length == 1 ? '0' + minutesValue : minutesValue);
final DateFormat dateFormat = DateFormat('HH:mm');
final DateTime wakeup =
dateFormat.parse(_wakeupTime == '06:00 am' ? '03:00' : _wakeupTime);
final DateTime sleep = dateFormat.parse(_bedTime);
final String sleepDuration = sleep.difference(wakeup).toString();
_sleepHours = sleepDuration.split(':')[0];
_sleepMinutes = sleepDuration.split(':')[1];
});
}
void _handleWakeupTimeValueStart(double value) {
_isBedTime = false;
}
void _handleWakeupTimeValueEnd(double value) {
setState(() {
_isBedTime = true;
});
_wakeupTimePointerWidth = _wakeupTimePointerHeight = 40.0;
}
void _handleBedTimeValueStart(double value) {
_isWakeupTime = false;
}
void _handleBedTimeValueEnd(double value) {
setState(() {
_isWakeupTime = true;
});
_bedTimePointerWidth = _bedTimePointerHeight = 40.0;
}
/// Renders a given fixed size widget
bool get isWebOrDesktop {
return defaultTargetPlatform == TargetPlatform.windows ||
defaultTargetPlatform == TargetPlatform.linux ||
defaultTargetPlatform == TargetPlatform.macOS ||
kIsWeb;
}
double _wakeupTimeValue = 3;
double _bedTimeValue = 12;
String _wakeupTimeAnnotation = '09:00 pm';
String _bedTimeAnnotation = '06:00 am';
bool _isWakeupTime = true;
bool _isBedTime = true;
String _sleepHours = '9';
String _sleepMinutes = '00';
String _bedTime = '09:00 pm';
String _wakeupTime = '06:00 am';
double _bedTimePointerWidth = 40.0;
double _bedTimePointerHeight = 40.0;
double _wakeupTimePointerWidth = 40.0;
double _wakeupTimePointerHeight = 40.0;
double _tickness = 0.2;
}
/// Widget of custom animated builder.
class CustomAnimatedBuilder extends StatefulWidget {
/// Creates a instance for [CustomAnimatedBuilder].
const CustomAnimatedBuilder({
Key key,
this.value,
this.builder,
this.duration = const Duration(milliseconds: 200),
this.curve = Curves.easeInOut,
this.child,
}) : super(key: key);
/// Specifies the animation duration.
final Duration duration;
/// Specifies the curve of animation.
final Curve curve;
/// Specifies the animation controller value.
final double value;
/// Specifies the child widget.
final Widget child;
/// Specifies the builder function.
final Widget Function(
BuildContext context,
Widget child,
Animation<dynamic> animation,
) builder;
@override
_CustomAnimatedBuilderState createState() => _CustomAnimatedBuilderState();
}
class _CustomAnimatedBuilderState extends State<CustomAnimatedBuilder>
with SingleTickerProviderStateMixin {
AnimationController _animationController;
@override
void initState() {
_animationController = AnimationController(
vsync: this,
value: widget.value,
lowerBound: double.negativeInfinity,
upperBound: double.infinity,
);
super.initState();
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
@override
void didUpdateWidget(CustomAnimatedBuilder oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.value != widget.value) {
_animationController.animateTo(
widget.value,
duration: widget.duration,
curve: widget.curve,
);
}
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _animationController,
builder: (BuildContext context, Widget child) => widget.builder(
context,
widget.child,
_animationController,
),
);
}
}
Beta Was this translation helpful? Give feedback.
All reactions
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment