How to achive drop cap letter of a text paragraph in Flutter.
As below:
Asked
Active
Viewed 933 times
1

Tiziano Munegato
- 869
- 1
- 7
- 21
-
Did you try [`RichText`](https://docs.flutter.io/flutter/widgets/RichText-class.html)? – Lucas Feb 07 '19 at 20:47
-
RichText does not "shift" second and third line of text to right, you can only have a bigger char (going upward) – Tiziano Munegato Feb 08 '19 at 08:57
-
A few links where measuring text size is mentioned that might help https://stackoverflow.com/questions/52659759/how-can-i-get-the-size-of-the-text-widget-in-flutter/52991124#52991124 https://github.com/flutter/flutter/issues/18431#issuecomment-396990020 https://github.com/flutter/flutter/issues/19264 https://github.com/flutter/flutter/issues/21822 – Günter Zöchbauer Feb 10 '19 at 12:17
1 Answers
3
I managed to hack this together, it looks like it should work but doesn't break at the right spot for some reason. getPositionForOffset
seems to give an index that is too large. Might be better than nothing though, and it demonstrates how we can use TextPainter
to get the size of a text.
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main() => runApp(MaterialApp(title: 'Demo', home: MyApp()));
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) => MaterialApp(
home: Scaffold(
body: Container(
width: 200.0,
decoration: BoxDecoration(border: Border.all()),
child: DropCapText(
dropCap: "L",
dropCapStyle: Theme.of(context).textTheme.display3,
text: "orem ipsum dolor sit amet, consectetur 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 aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
textStyle: Theme.of(context).textTheme.body1,
),
),
),
);
}
class DropCapText extends StatelessWidget {
final String dropCap;
final TextStyle dropCapStyle;
final String text;
final TextStyle textStyle;
final EdgeInsets dropCapPadding;
DropCapText({this.dropCap, this.dropCapStyle, this.text, this.textStyle, this.dropCapPadding = EdgeInsets.zero});
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
//get the drop cap size
final dropCapSpan = TextSpan(text: dropCap, style: dropCapStyle);
final dropCapPainter = TextPainter(text: dropCapSpan, textDirection: Directionality.of(context));
dropCapPainter.layout(maxWidth: constraints.maxWidth);
final dropCapSize = dropCapPainter.size;
//get the position of the last bit of text next to the dropcap
final textSpan = TextSpan(text: text, style: textStyle);
final textPainter = TextPainter(text: textSpan, textDirection: Directionality.of(context));
textPainter.layout(maxWidth: max(constraints.minWidth, constraints.maxWidth - dropCapPadding.horizontal - dropCapSize.width));
final lastPosition = textPainter.getPositionForOffset(Offset(textPainter.width, dropCapSize.height + dropCapPadding.vertical));
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: dropCapPadding,
child: Text(dropCap, style: dropCapStyle),
),
Expanded(
child: Text(text.substring(0, lastPosition.offset), style: textStyle, softWrap: true,),
),
],
),
Text(text.substring(lastPosition.offset), style: textStyle),
],
);
}
);
}
}

Lucas
- 2,472
- 2
- 18
- 33
-
Very Helpful! I've been working on this last days and solved in a trickier way, but I will play around "getPositionForOffset" – Tiziano Munegato Feb 10 '19 at 23:32
-
I've published a package https://github.com/numez/drop_cap_text, feel free to open a PR with improvements – Tiziano Munegato Mar 04 '19 at 20:28