How to call a function when user taps on a TextSpan:
Pass a TapGestureRecognizer to recognizer property, for example:
TextSpan(
text: "hello world",
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
color: Colors.blue,
height: 2.5,
letterSpacing: 0.7,
),
recognizer: TapGestureRecognizer()
..onTap = () {
print("TextSpan is clicked.");
// callMyFunction();
},
);
Edit:
Based on your newest edits in the question, the best way to approach this task is to lift up the function that determines color based on the genetic code (I'm just calling it getColorFromCode, you can call it checkdominant or whatever). This way, you can calculate "proportion" when needed.
I've made a small demo project for you to see how to call the helper function in two different widgets: one displays the proportion and the other one displays the 16 codes in various colors.
This is how it looks like:

To run the demo, create a new Flutter project and replace its entire main.dart file with the code below:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
final data = [
'AAPP', 'AApP', 'aAPP', 'aApP',
'AAPp', 'AApp', 'aAPp', 'aApp',
'AaPP', 'AapP', 'aaPP', 'aapP',
'AaPp', 'Aapp', 'aaPp', 'aapp',
];
@override
Widget build(BuildContext context) {
final colors = data.map(getColorFromCode);
final browns = colors.where((color) => color == Colors.brown).length;
final blacks = colors.where((color) => color == Colors.black).length;
final whites = colors.where((color) => color == Colors.white).length;
return Scaffold(
appBar: AppBar(title: Text('Flutter Demo')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Proportion: $browns:$blacks:$whites'),
Container(
width: 200,
decoration: BoxDecoration(
border: Border.all(color: Colors.blue, width: 4.0),
borderRadius: BorderRadius.circular(16),
color: Colors.lightGreen,
),
padding: EdgeInsets.all(16),
child: RichText(
text: TextSpan(
children: [
for (final code in data)
TextSpan(
text: '$code ',
style: TextStyle(
color: getColorFromCode(code),
fontFamily: 'courier',
),
),
],
)),
),
],
),
),
);
}
}
Color getColorFromCode(String code) {
if (code.contains('A') && code.contains('P')) return Colors.brown;
if (code.contains('A') && code.contains('pp')) return Colors.black;
if (code.contains('aa')) return Colors.white;
return Colors.red; // not covered in the question description
}
Edit again:
If you have more than a few data, you can also refactor the business logic into a standalone widget, so you can reuse the code easily.
For example, we can pass in 3 sets of data and build something like this:

Full source code:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
final data1 = ['AAPP', 'AApP', 'aAPP', 'aApP', 'AAPp', 'AApp', 'aAPp'];
final data2 = ['AaPP', 'AapP', 'aaPP', 'aapP', 'AaPp', 'Aapp', 'aaPp'];
final data3 = ['aaPp', 'AapP', 'aAPP', 'aApP', 'AaPp', 'aaPP'];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Flutter Demo')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(MyWidget.getProportion(data1)),
MyWidget(data: data1),
Divider(),
Text(MyWidget.getProportion(data2)),
MyWidget(data: data2),
Divider(),
Text(MyWidget.getProportion(data3)),
MyWidget(data: data3),
],
),
),
);
}
}
class MyWidget extends StatelessWidget {
final List<String> data;
const MyWidget({Key? key, required this.data}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
width: 200,
decoration: BoxDecoration(
border: Border.all(color: Colors.blue, width: 4.0),
borderRadius: BorderRadius.circular(16),
color: Colors.lightGreen,
),
padding: EdgeInsets.all(16),
child: RichText(
text: TextSpan(
children: [
for (final code in data)
TextSpan(
text: '$code ',
style: TextStyle(
color: getColorFromCode(code),
fontFamily: 'courier',
),
),
],
)),
);
}
static String getProportion(List<String> data) {
final colors = data.map(getColorFromCode);
final browns = colors.where((color) => color == Colors.brown).length;
final blacks = colors.where((color) => color == Colors.black).length;
final whites = colors.where((color) => color == Colors.white).length;
return 'Proportion: $browns:$blacks:$whites';
}
static Color getColorFromCode(String code) {
if (code.contains('A') && code.contains('P')) return Colors.brown;
if (code.contains('A') && code.contains('pp')) return Colors.black;
if (code.contains('aa')) return Colors.white;
return Colors.red; // not covered in the question description
}
}