Reputation: 25
Using Flutter, I have a long text that has citations inline, that I would like displayed to the side of the text, but kept on the same line where the original citation was, even when the text is resized. As well as avoiding line breaks. For example the original text might be:
Lorem ipsum dolor sit amet, consectetur *132a* adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris nisi ut *133c* aliquip ex ea commodo consequat. Duis
And I would like it displayed as:
132a Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
133c quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
While allowing the citations to stay inline with the original location when the text is resized. And avoiding line breaks.
I've tried using the RichText
widget, using TextSpan
for the text and WidgetSpan
for the citations and with other widgets such as Stack
, Position
and OverflowBox
Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
RichText(
text: TextSpan(
children: [
TextSpan(text: textA),
WidgetSpan(child: Text('132a')), // I've tried many widgets here
TextSpan(text: textB),
])),
],
),
),
With CSS I could use float: left
to get a similar effect, but I've been unable to figure out a way to do this with the Flutter UI.
Upvotes: 1
Views: 1115
Reputation: 261
I'm a little late with an answer, but it is possible to layout your data like you want, allowing citations to stay inline with the original location when the text is resized, for example:
Here's what the code would look like:
import 'package:float_column/float_column.dart';
class InlineFloats extends StatelessWidget {
const InlineFloats({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return DefaultTextStyle(
style: const TextStyle(fontSize: 18, color: Colors.black, height: 1.5),
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(8),
child: FloatColumn(
children: [
WrappableText(
text: _process(_str),
margin: const EdgeInsetsDirectional.only(start: 60),
),
],
),
),
),
);
}
}
TextSpan _process(String str) {
return TextSpan(
children: str.split(' *').expand(
(str) {
final s = str.split('* ');
if (s.length == 2) {
final cit = s.first;
return [
TextSpan(text: ' (${cit.substring(cit.length - 1)})'),
WidgetSpan(
child: Floatable(
float: FCFloat.left, clear: FCClear.both, child: Text(cit)),
),
TextSpan(text: ' ${s.last}'),
];
} else {
return [TextSpan(text: str)];
}
},
).toList(),
);
}
// cspell: disable
const _str = '''
Lorem ipsum dolor sit amet, consectetur *132a* adipiscing elit, sed do eiusmod...
It uses a new flutter package I recently wrote called float_column, which provides a new FloatColumn widget where text can wrap around floated inline widgets, similar to how CSS float works.
You can try it out here: https://ronjb.github.io/float_column, and in it, switch to the 'Inline' tab to see an example similar to your question.
Upvotes: 1
Reputation: 1411
Here is the full example on dartpad
To make the problem easier, I would definitely convert the text (using regex, especially if the text is long) into a map.
Your map should look like this:
final Map<String, String> myMap = {
'132a':
"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type",
'132b':
"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type",
'132c':
"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type",
'132d':
"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type",
};
Then,
return ListView.builder(
itemCount: myMap.entries.length,
itemBuilder: (context, index) {
return Padding(
padding: EdgeInsets.all(8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(myMap.keys.elementAt(index)),
SizedBox(width: 20),
Expanded(
child: Text(
myMap.values.elementAt(index),
),
),
],
),
);
},
);
Upvotes: 0
Reputation: 957
My solution, but with Rows and Expanded:
Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'132a',
),
Expanded(child: Text(textA, overflow: TextOverflow.clip))
],
),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('133c'),
Expanded(child: Text(textB, overflow: TextOverflow.clip)),
],
),
],
),
),
Upvotes: 1