Skip to content

Instantly share code, notes, and snippets.

@imaNNeo
Created May 5, 2025 10:58
Show Gist options
  • Save imaNNeo/bdbe17754835bf97038efafbde412ee0 to your computer and use it in GitHub Desktop.
Save imaNNeo/bdbe17754835bf97038efafbde412ee0 to your computer and use it in GitHub Desktop.
Tap up callback
import 'package:fl_chart_app/presentation/resources/app_resources.dart';
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
class PieChartSample3 extends StatefulWidget {
const PieChartSample3({super.key});
@override
State<StatefulWidget> createState() => PieChartSample3State();
}
class PieChartSample3State extends State {
int touchedIndex = 0;
@override
Widget build(BuildContext context) {
return AspectRatio(
aspectRatio: 1.3,
child: AspectRatio(
aspectRatio: 1,
child: PieChart(
PieChartData(
pieTouchData: PieTouchData(
touchCallback: (FlTouchEvent event, pieTouchResponse) {
setState(() {
if (event is FlTapUpEvent) {
if (pieTouchResponse != null &&
pieTouchResponse.touchedSection != null) {
touchedIndex =
pieTouchResponse.touchedSection!.touchedSectionIndex;
} else {
touchedIndex = -1;
}
}
});
},
),
borderData: FlBorderData(
show: false,
),
sectionsSpace: 0,
centerSpaceRadius: 0,
sections: showingSections(),
),
),
),
);
}
List<PieChartSectionData> showingSections() {
return List.generate(4, (i) {
final isTouched = i == touchedIndex;
final fontSize = isTouched ? 20.0 : 16.0;
final radius = isTouched ? 110.0 : 100.0;
final widgetSize = isTouched ? 55.0 : 40.0;
const shadows = [Shadow(color: Colors.black, blurRadius: 2)];
switch (i) {
case 0:
return PieChartSectionData(
color: AppColors.contentColorBlue,
value: 40,
title: '40%',
radius: radius,
titleStyle: TextStyle(
fontSize: fontSize,
fontWeight: FontWeight.bold,
color: const Color(0xffffffff),
shadows: shadows,
),
badgeWidget: _Badge(
'assets/icons/ophthalmology-svgrepo-com.svg',
size: widgetSize,
borderColor: AppColors.contentColorBlack,
),
badgePositionPercentageOffset: .98,
);
case 1:
return PieChartSectionData(
color: AppColors.contentColorYellow,
value: 30,
title: '30%',
radius: radius,
titleStyle: TextStyle(
fontSize: fontSize,
fontWeight: FontWeight.bold,
color: const Color(0xffffffff),
shadows: shadows,
),
badgeWidget: _Badge(
'assets/icons/librarian-svgrepo-com.svg',
size: widgetSize,
borderColor: AppColors.contentColorBlack,
),
badgePositionPercentageOffset: .98,
);
case 2:
return PieChartSectionData(
color: AppColors.contentColorPurple,
value: 16,
title: '16%',
radius: radius,
titleStyle: TextStyle(
fontSize: fontSize,
fontWeight: FontWeight.bold,
color: const Color(0xffffffff),
shadows: shadows,
),
badgeWidget: _Badge(
'assets/icons/fitness-svgrepo-com.svg',
size: widgetSize,
borderColor: AppColors.contentColorBlack,
),
badgePositionPercentageOffset: .98,
);
case 3:
return PieChartSectionData(
color: AppColors.contentColorGreen,
value: 15,
title: '15%',
radius: radius,
titleStyle: TextStyle(
fontSize: fontSize,
fontWeight: FontWeight.bold,
color: const Color(0xffffffff),
shadows: shadows,
),
badgeWidget: _Badge(
'assets/icons/worker-svgrepo-com.svg',
size: widgetSize,
borderColor: AppColors.contentColorBlack,
),
badgePositionPercentageOffset: .98,
);
default:
throw Exception('Oh no');
}
});
}
}
class _Badge extends StatelessWidget {
const _Badge(
this.svgAsset, {
required this.size,
required this.borderColor,
});
final String svgAsset;
final double size;
final Color borderColor;
@override
Widget build(BuildContext context) {
return AnimatedContainer(
duration: PieChart.defaultDuration,
width: size,
height: size,
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
border: Border.all(
color: borderColor,
width: 2,
),
boxShadow: <BoxShadow>[
BoxShadow(
color: Colors.black.withValues(alpha: .5),
offset: const Offset(3, 3),
blurRadius: 3,
),
],
),
padding: EdgeInsets.all(size * .15),
child: Center(
child: SvgPicture.asset(
svgAsset,
),
),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment