Skip to content

Updating TextSelectionOverlay causes it to hide and reshow #142763

@justinmc

Description

@justinmc

Steps to reproduce

  1. Run the app below (an app that makes a change to a property of TextField that gets passed to TextSelectionOverlay).
  2. Drag the selection in order to show the magnifier.

Expected results

Changes to the magnifier appear smooth, without flashing or hiding/showing.

Actual results

The magnifier is alternately hidden and shown each frame.

This didn't used to work at all until #142463, but that PR still needs to recreate the overlay on each change, so it leads to stuttering like shown in the video.

This is an egregious example because it's better to animate the magnifier in magnifierBuilder. I'm wondering if anyone will encounter this bug in the real world. If you do, please leave a 👍 reaction to this issue.

Code sample

Code sample
import 'dart:math' as math;

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.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 StatelessWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: const Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            AnimatedWidgetExample(
            ),
          ],
        ),
      ),
    );
  }
}

class AnimatedWidgetExample extends StatefulWidget {
  const AnimatedWidgetExample({super.key});

  @override
  State<AnimatedWidgetExample> createState() => _AnimatedWidgetExampleState();
}

class _AnimatedWidgetExampleState extends State<AnimatedWidgetExample>
    with TickerProviderStateMixin {
  late final AnimationController _controller = AnimationController(
    duration: const Duration(seconds: 10),
    vsync: this,
  )..repeat();

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return TextFieldWithSpinningMagnifier(controller: _controller);
  }
}

class TextFieldWithSpinningMagnifier extends AnimatedWidget {
  const TextFieldWithSpinningMagnifier({
    super.key,
    required AnimationController controller,
  }) : super(listenable: controller);

  Animation<double> get _progress => listenable as Animation<double>;

  @override
  Widget build(BuildContext context) {
    final TextMagnifierConfiguration magnifierConfiguration = TextMagnifierConfiguration(
      magnifierBuilder: (BuildContext context, MagnifierController controller, ValueNotifier<MagnifierInfo>? info) {
        return Transform.rotate(
          angle: _progress.value * 2.0 * math.pi,
          child: Container(width: 200.0, height: 200.0, color: Colors.green),
        );
      },
    );

    return TextField(
      magnifierConfiguration: magnifierConfiguration,
    );
  }
}

Screenshots or Video

Video demonstration
Screen.Recording.2024-02-01.at.4.21.51.PM.mov

Logs

No response

Flutter Doctor output

Doctor output

Using master.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work lista: text inputEntering text in a text field or keyboard related problemsf: selectionSelectableRegion, SelectionArea, SelectionContainer, Selectable, and related APIsfound in release: 3.16Found to occur in 3.16found in release: 3.19Found to occur in 3.19frameworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onteam-frameworkOwned by Framework teamtriaged-frameworkTriaged by Framework team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions