Flutter Web - Text field scrolls instead of selecting for long text
Asked Answered
B

2

7

I'm having an issue with Flutter Web's TextField. Whenever The text becomes too long, and thus causes the TextField to scroll over to view it all (in single line fields), I am no longer able to click-and-drag to select the text. When the text is shorter, the selection is fine. You can see that with the GIF attached here: visual of the problem

I assume it has something to do with the order of gesture capturing being wrong, but I haven't been able to find a way to fix it.

According to a few people on this github issue, one solution to problems with text selection is to use one of the two following commands:

  1. flutter run -d chrome --release --dart-define=FLUTTER_WEB_USE_SKIA=true
  2. flutter run -d chrome --release --dart-define=FLUTTER_WEB_USE_EXPERIMENTAL_CANVAS_TEXT=true

Although the issue is for multi-line text fields, and unfortunately neither seems to solve my issue.

I've tried using a multi-line text box, though if I set maxLines to a fixed number like 5, I get a similar problem with vertical scrolling and selection.

I've thought about using an html rendering plugin such as flutter_html to just render a text field that way, but I'd like to avoid doing that if it's at all possible.

Bung answered 1/1, 2021 at 1:54 Comment(1)
See github.com/flutter/flutter/issues/59141Interfluent
A
5

I had the same problem and found this solution:

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

class TextFieldScrollTest extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final scrollController = ScrollController();
    final textController = TextEditingController(text: '________a________b_________c________d________e_______f_______g_______h______i_______j_________k__________l__________m________n_________o_______p');
    return Scaffold(
      body: Listener(
        onPointerSignal: (_) {
          if (_ is PointerScrollEvent) {
            _scrollController.jumpTo(
              math.max(
                math.min(
                  _scrollController.position.maxScrollExtent,
                  _scrollController.offset + _.scrollDelta.dx,
                ),
                _scrollController.position.minScrollExtent,
              ),
            );
          }
        },
        child: ConstrainedBox(
          constraints: const BoxConstraints(maxWidth: 500),
          child: TextField(
            controller: textController,
            scrollPhysics: const NeverScrollableScrollPhysics(),
            scrollController: scrollController,
          ),
        ),
      ),
    );
  }
}

The behavior you are experiencing (mouse dragging on text scrolls the text instead of selecting) can be suppressed with the NeverScrollableScrollPhysics. This will however prevent all scrolling. The Listener's onPointerSignal will detect horizontal scrolling using mouse wheel or touchpad's two-fingers swipe.

Avian answered 12/1, 2021 at 10:25 Comment(4)
The strange thing is that I'm also clicking and dragging to scroll, which is the more important thing to stop, since it means that I can't select the text in the textbox. Does this resolve that issue as well?Bung
Did you try the widget I posted? You can juste paste this code into a new file and use TextFieldScrollTest() somewhere in your app, import the file and check. Clicking and dragging inside this widget should select text, not scroll.Avian
Sorry, wasn't able to actually do anything with this at the time. I've just tried it, and it works for selecting text that is already scrolled into view, as well as scrolling with the touch pad on a laptop. However, I cannot scroll with the mouse wheel. Though I suspect that can be solved by detecting if it's a scrollwheel, or if shift is pressed, and using y offset. I also noticed that if you try to select text on the edge, it doesn't scroll the selection into view. Any ideas on how to fix that bit?Bung
This answer doesn't allow scrolling with the cursor, only the pointer.Haematosis
G
0

I had the same issue, so I tried different scroll physics and FixedExtentScrollPhysics seems to fix it, I tested it on Web only so make sure to test on platforms you use first.

TextField(
   controller: textController,
   scrollPhysics: const FixedExtentScrollPhysics(),
),

Note: There's an assertion that fails regarding the parent having to use FixedExtentScrollController, I just ignored it as it's not causing an issue in my case.

Gerontocracy answered 1/8 at 19:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.