Skip to content

Commit d28577b

Browse files
committed
Add onTap and onCandleResize events
1 parent 8a63efd commit d28577b

File tree

3 files changed

+39
-5
lines changed

3 files changed

+39
-5
lines changed

example/lib/main.dart

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,10 @@ class _MyAppState extends State<MyApp> {
5050
body: SafeArea(
5151
minimum: const EdgeInsets.all(24.0),
5252
child: InteractiveChart(
53+
/** Only [candles] is required */
5354
candles: _data,
54-
/** Uncomment the following to see more examples */
55+
/** Uncomment the following for examples on optional parameters */
56+
5557
/** Example styling */
5658
// style: ChartStyle(
5759
// priceGainColor: Colors.teal[200]!,
@@ -76,7 +78,9 @@ class _MyAppState extends State<MyApp> {
7678
// "Hi": "${candle.high?.toStringAsFixed(2)}",
7779
// "Lo": "${candle.low?.toStringAsFixed(2)}",
7880
// },
79-
81+
/** Callbacks */
82+
// onTap: (candle) => print("user tapped on $candle"),
83+
// onCandleResize: (width) => print("each candle is $width wide"),
8084
),
8185
),
8286
),

lib/src/candle_data.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,5 +56,5 @@ class CandleData {
5656
}
5757

5858
@override
59-
String toString() => "$timestamp: $close";
59+
String toString() => "<CandleData ($timestamp: $close)>";
6060
}

lib/src/interactive_chart.dart

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,23 @@ class InteractiveChart extends StatefulWidget {
4545
/// ```
4646
final OverlayInfoGetter? overlayInfo;
4747

48+
/// An optional event, fired when the user clicks on a candlestick.
49+
final ValueChanged<CandleData>? onTap;
50+
51+
/// An optional event, fired when user zooms in/out.
52+
///
53+
/// This provides the width of a candlestick at the current zoom level.
54+
final ValueChanged<double>? onCandleResize;
55+
4856
const InteractiveChart({
4957
Key? key,
5058
required this.candles,
5159
ChartStyle? style,
5260
this.timeLabel,
5361
this.priceLabel,
5462
this.overlayInfo,
63+
this.onTap,
64+
this.onCandleResize,
5565
}) : this.style = style ?? const ChartStyle(),
5666
assert(candles.length >= 3,
5767
"InteractiveChart requires 3 or more CandleData"),
@@ -78,6 +88,7 @@ class _InteractiveChartState extends State<InteractiveChart> {
7888
late double _prevCandleWidth;
7989
late double _prevStartOffset;
8090
late Offset _initialFocalPoint;
91+
PainterParams? _prevParams; // used in onTapUp event
8192

8293
@override
8394
Widget build(BuildContext context) {
@@ -140,7 +151,13 @@ class _InteractiveChartState extends State<InteractiveChart> {
140151
setState(() => _tapPosition = details.localPosition);
141152
},
142153
onTapCancel: () => setState(() => _tapPosition = null),
143-
onTapUp: (_) => setState(() => _tapPosition = null),
154+
onTapUp: (_) {
155+
if (widget.onTap != null) {
156+
_fireOnTapEvent(); // Fire callback event (if needed)
157+
}
158+
setState(() => _tapPosition = null);
159+
},
160+
144161
// Pan and zoom
145162
onScaleStart: (details) {
146163
_prevCandleWidth = _candleWidth;
@@ -166,10 +183,10 @@ class _InteractiveChartState extends State<InteractiveChart> {
166183
trailingTrend: trailingTrend,
167184
),
168185
),
169-
// duration: Duration.zero,
170186
duration: Duration(milliseconds: 300),
171187
curve: Curves.easeOut,
172188
builder: (_, PainterParams params, __) {
189+
_prevParams = params;
173190
return RepaintBoundary(
174191
child: CustomPaint(
175192
size: size,
@@ -204,6 +221,10 @@ class _InteractiveChartState extends State<InteractiveChart> {
204221
final focalPointFactor = details.localFocalPoint.dx / w;
205222
startOffset -= zoomAdjustment * focalPointFactor;
206223
startOffset = startOffset.clamp(0, _getMaxStartOffset(w, candleWidth));
224+
// Fire candle width resize event
225+
if (candleWidth != _candleWidth) {
226+
widget.onCandleResize?.call(candleWidth);
227+
}
207228
// Apply changes
208229
setState(() {
209230
_candleWidth = candleWidth;
@@ -276,6 +297,15 @@ class _InteractiveChartState extends State<InteractiveChart> {
276297
"Volume": candle.volume?.asAbbreviated() ?? "-",
277298
};
278299
}
300+
301+
void _fireOnTapEvent() {
302+
if (_prevParams == null || _tapPosition == null) return;
303+
final params = _prevParams!;
304+
final dx = _tapPosition!.dx;
305+
final selected = params.getCandleIndexFromOffset(dx);
306+
final candle = params.candles[selected];
307+
widget.onTap?.call(candle);
308+
}
279309
}
280310

281311
extension Formatting on double {

0 commit comments

Comments
 (0)