Repository navigation
Closed
Closed
Copy link
Labels
P1High-priority issues at the top of the work listHigh-priority issues at the top of the work lista: text inputEntering text in a text field or keyboard related problemsEntering text in a text field or keyboard related problemsa: typographyText rendering, possibly libtxtText rendering, possibly libtxtc: regressionIt was better in the past than it is nowIt was better in the past than it is nowteam-text-inputOwned by Text Input teamOwned by Text Input teamtriaged-text-inputTriaged by Text Input teamTriaged by Text Input team
Description
Steps to reproduce
Run the attached example on Flutter 3.35 or 3.38
Expected results
This is how it looks on Flutter 3.27
RenderEditable.getBoxesForSelection for Text Selection from 39 to 51 (second line) only returns coordinates of the 2nd line which gets correctly highlighted/underlined.
Actual results
On Flutter version 3.35 and 3.38, same code returned coordinates for the longest line width, which highlights/underlines more than the actual TextSelection was requested.
Code sample
Code sample
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'RenderEditable Bug Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'RenderEditable Bug Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final GlobalKey customPaintKey = GlobalKey();
final ScrollController scrollController = ScrollController();
final TextEditingController controller = TextEditingController();
final List<TextSelection> errorLines = [const TextSelection(baseOffset: 39, extentOffset: 51)]; // "Highlight me" position
ErrorLinesPainter? painter;
@override
void initState() {
controller.text = '''
Some long lines of text should go here
Highlight me
Doesn't matter
''';
painter = ErrorLinesPainter(
customPaintKey,
const TextStyle(),
controller,
);
painter!.lineErrorPositions = errorLines;
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: DumbVisitor<EditableTextState>(
onFound: (ets) {
painter?.setupEditableTextState(ets);
},
child: CustomPaint(
key: customPaintKey,
foregroundPainter: painter,
child: TextField(
controller: controller,
maxLines: null,
expands: true,
readOnly: true,
decoration: const InputDecoration(
border: OutlineInputBorder(),
),
),
),
),
);
}
}
class ErrorLinesPainter extends CustomPainter {
ErrorLinesPainter(this.customPaintKey, this.textStyle, Listenable listenable) : super(repaint: listenable);
GlobalKey customPaintKey;
RenderEditable? re;
final TextStyle textStyle;
List<TextSelection> lineErrorPositions = [];
@override
void paint(Canvas canvas, Size size) {
if (re case RenderEditable re) {
final ancestor = customPaintKey.currentContext!.findRenderObject();
final offset = re.localToGlobal(Offset.zero, ancestor: ancestor);
for (final e in lineErrorPositions) {
final boxes = re.getBoxesForSelection(e);
if (boxes.isNotEmpty) {
final firstBox = boxes.first.toRect();
final lastBox = boxes.last.toRect();
canvas.drawLine(
Offset(firstBox.left + offset.dx, firstBox.bottom + offset.dy),
Offset(lastBox.right + offset.dx, firstBox.bottom + offset.dy),
Paint()
..strokeWidth = 2
..style = PaintingStyle.stroke
..filterQuality = FilterQuality.low
..strokeCap = StrokeCap.round
..color = Colors.red.shade500);
}
}
}
}
@override
bool shouldRepaint(ErrorLinesPainter oldDelegate) => false;
void setupEditableTextState(EditableTextState ets) {
re = ets.renderEditable;
}
}
class DumbVisitor<T> extends StatelessWidget {
const DumbVisitor({
super.key,
required this.onFound,
required this.child,
});
final void Function(T object) onFound;
final Widget child;
@override
Widget build(BuildContext context) => child;
@override
StatelessElement createElement() => _DumbVisitorElement<T>(this, onFound);
}
class _DumbVisitorElement<T> extends StatelessElement {
_DumbVisitorElement(super.widget, this.onFound);
final void Function(T object) onFound;
Element? oldElement;
@override
Element? updateChild(Element? child, Widget? newWidget, Object? newSlot) {
final element = super.updateChild(child, newWidget, newSlot);
if (oldElement != element) {
oldElement = element;
element?.visitChildren(_visitor);
}
return element;
}
void _visitor(Element child) {
if (child is StatefulElement && child.state is T) {
onFound(child.state as T);
} else if (child.renderObject is T) {
onFound(child.renderObject as T);
}
child.visitChildren(_visitor);
}
}
Screenshots or Video
Screenshots / Video demonstration
[Upload media here]
Logs
Logs
[Paste your logs here]Flutter Doctor output
Doctor output
[!] Flutter (Channel [user-branch], 3.38.5, on macOS 14.7.1 23H222 darwin-arm64, locale en-GB)
! Flutter version 3.38.5 on channel [user-branch] at xxxx
Currently on an unknown channel. Run `flutter channel` to switch to an official channel.
If that doesn't fix the issue, reinstall Flutter by following instructions at https://flutter.dev/setup.
! Upstream repository unknown source is not a standard remote.
Set environment variable "FLUTTER_GIT_URL" to unknown source to dismiss this error.
[!] Android toolchain - develop for Android devices (Android SDK version 36.0.0)
! Some Android licenses not accepted. To resolve this, run: flutter doctor --android-licenses
[✓] Xcode - develop for iOS and macOS (Xcode 16.2)
[✓] Chrome - develop for the web
[✓] Connected device (3 available)
[✓] Network resources
! Doctor found issues in 2 categories.Metadata
Metadata
Assignees
Labels
P1High-priority issues at the top of the work listHigh-priority issues at the top of the work lista: text inputEntering text in a text field or keyboard related problemsEntering text in a text field or keyboard related problemsa: typographyText rendering, possibly libtxtText rendering, possibly libtxtc: regressionIt was better in the past than it is nowIt was better in the past than it is nowteam-text-inputOwned by Text Input teamOwned by Text Input teamtriaged-text-inputTriaged by Text Input teamTriaged by Text Input team


Activity
flutter-triage-bot commentedon May 28, 2026
This issue is assigned to @Renzo-Olivares but has had no recent status updates. Please consider unassigning this issue if it is not going to be addressed in the near future. This allows people to have a clearer picture of what work is actually planned. Thanks!
Renzo-Olivares commentedon Jul 30, 2026
This will be fixed by #185239
Fix multiline EditableText selection highlighting width (flutter#185239)
github-actions commentedon Oct 23, 2026
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of
flutter doctor -vand a minimal reproduction of the issue.Fix multiline EditableText selection highlighting width (flutter#185239)