9

I'm looking for the best way to stop tap/click events from being propagated up the view hierarchy. Suppose we have a simple scenario with a TextField decorated with a an 'X' clear text button.

When I click the "X" button the click event is propagated up to TextField's onPressed().

final _textEditingController = TextEditingController(text: "");

@override
Widget build(BuildContext context) {
  return TextFormField(
    controller: _textEditingController,
    onTap: onEditTextTapped,
    decoration: InputDecoration(
      suffixIcon: IconButton(
        onPressed: onClearTextClick,
        icon: Icon(
          Icons.clear,
          size: 20.0,
        ),
      ),
    ),
    style: TextStyle(fontWeight: FontWeight.normal, fontSize: 18),
  );
}

void onEditTextTapped() {
  print('TextField tapped');
}

void onClearTextClick() {
  print('clear text clicked');
}

enter image description here

The result is:

flutter: clear text clicked
flutter: TextField tapped

I need something similar to Android's android:clickable="true" or Flutter's AbsorbPointer that would trap all click events and stop them from being passed through to the view beneath BUT only when I click 'clear text' button. Click event from TextFormField should still trigger onEditTextTapped()

Flutter (Channel stable, v1.9.1+hotfix.2, on Mac OS X 10.14.5 18F132)

2 Answers2

3

Use pointer_interceptor widget, especially if you target Web with complex layouts involving maps, Stack, drawers, Positionned widgets, etc. So in your case it would be something like:

import 'package:pointer_interceptor/pointer_interceptor.dart';
...
return TextFormField(
    controller: _textEditingController,
    onTap: onEditTextTapped,
    decoration: InputDecoration(
      suffixIcon: PointerInterceptor(
        child: IconButton(
          onPressed: onClearTextClick,
          icon: Icon(
            Icons.clear,
            size: 20.0,
          ),
        ),
      ),
    ),
    style: TextStyle(fontWeight: FontWeight.normal, fontSize: 18),
  );
Pavel
  • 565
  • 6
  • 19
1

use Stack as an option :D

  @override
  Widget build(BuildContext context) {
    return Stack(
      alignment: Alignment.centerRight,
      children: <Widget>[
        TextFormField(
          controller: _textEditingController,
          onTap: onEditTextTapped,
          decoration: InputDecoration(
            suffixIcon: IconButton(
              onPressed: onClearTextClick,
              icon: Icon(Icons.clear, size: 20.0),
            ),
          ),
          style: TextStyle(fontWeight: FontWeight.normal, fontSize: 18),
        ),
        IconButton(
          onPressed: onClearTextClick,
          icon: Icon(Icons.clear, size: 20.0),
        ),
      ],
    );
  }