Skip to content

RenderParagraph getOffsetForCaret does not work correct if it has WidgetSpan #98458

@chunhtai

Description

@chunhtai

Steps to Reproduce

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final GlobalKey text = GlobalKey();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Text.rich(TextSpan(
        children: <InlineSpan>[
          TextSpan(text:'a'),
          WidgetSpan(child: Text('b')), // It works if comment out this line.
          TextSpan(text: 'c'),
        ]
      ), key:text,),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          RenderParagraph paragraph = text.currentContext!.findRenderObject()! as RenderParagraph;
          final String string = paragraph.text.toPlainText();
          final Offset offset = paragraph.getOffsetForCaret(TextPosition(offset: string.length, affinity: TextAffinity.upstream), Rect.zero);
          showDialog<void>(
            context: context,
            barrierDismissible: false,
            builder: (BuildContext context) {
              return AlertDialog(
                title: const Text('getOffsetForCaret'),
                content: SingleChildScrollView(
                  child: ListBody(
                    children: <Widget>[
                      Text('string is $string'),
                      Text('string length is ${string.length}'),
                      Text('getOffsetForCaret at location "${string.length}" is $offset'),
                    ],
                  ),
                ),
                actions: <Widget>[
                  TextButton(
                    child: const Text('Approve'),
                    onPressed: () {
                      Navigator.of(context).pop();
                    },
                  ),
                ],
              );
            },
          );
        },
        child: Icon(Icons.ice_skating),
      ),
    );
  }
}

Click the floating button to see the the result in the dialog

expect: the location is at the end of the Text
actual: the location is always (0, 0)

If comment out the widgetspan, things work as expected.

Something may be wrong with the textpainter.

Metadata

Metadata

Assignees

Labels

P2Important issues not at the top of the work lista: typographyText rendering, possibly libtxtframeworkflutter/packages/flutter repository. See also f: labels.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions