memspace / zefyr

Soft and gentle rich text editing for Flutter applications.
https://zefyr-editor.gitbook.io
2.22k stars 550 forks source link

Chinese input method with word candidate box the wrong place and typing characters recognized the wrong way. #584

Open taojoe opened 2 years ago

taojoe commented 2 years ago

Steps to Reproduce

  1. clone the repo
  2. run example
  3. switch to "Decorated Field"
  4. click "title" field, and switch to Chinese Input Method, type in "zhongwen", we can see screenshot "default TextField", this is the right interaction between input and Chinese input method.
  5. click "Description", and type enter key several times, then switch to Chinese Input Method, type in "zhongwen",we can see the word candidate box in wrong place, and the typing characters without underline.

input Chinese characters is different from english word, We first input the phonics of the chinese characters, then the input method will show chinese character candidate, then use number key to select the chinese character.

for example the chinese character "中", its phonics is "zhong"; chinese character "文", its phonics is "wen".

normally, the characters typed as phonics, they will show as characters with underline, after chinese character selection, it will replaced with chinese characters without underline. but in zefyr, characters are without underline, I think the interation between input method and zefyr need improve.

default TextField image

Zefyr Field image

Logs

JalorOo commented 2 years ago

I found this bug too

JalorOo commented 2 years ago

have you found a solution?

taojoe commented 2 years ago

have you found a solution?

I have no solution for this. I think it's related to the keyboard event. TextField has no problem, so the difference of handling keyboard event between TextField and Zefyr is the key.

jing-pei commented 2 years ago

need to call _textInputConnection!.setComposingRect update IME toolbar location

  // Sends the current composing rect to the iOS text input plugin via the text
  // input channel. We need to keep sending the information even if no text is
  // currently marked, as the information usually lags behind. The text input
  // plugin needs to estimate the composing rect based on the latest caret rect,
  // when the composing rect info didn't arrive in time.
  void _updateComposingRectIfNeeded() {
    final composingRange = textEditingValue.composing;
    if (hasConnection) {
      if (!mounted) {
        return;
      }
      var composingRect = renderEditor.getRectForComposingRange(composingRange);
      // Send the caret location instead if there's no marked text yet.
      if (composingRect == null) {
        assert(!composingRange.isValid || composingRange.isCollapsed);
        final offset = composingRange.isValid ? composingRange.start : 0;
        composingRect =
            renderEditor.getLocalRectForCaret(TextPosition(offset: offset));
      }
      _textInputConnection!.setComposingRect(composingRect);

      SchedulerBinding.instance!
          .addPostFrameCallback((_) => _updateComposingRectIfNeeded());
    }
  }

  void _updateCaretRectIfNeeded() {
    if (hasConnection) {
      if (!mounted) {
        return;
      }
      if (renderEditor.selection.isValid &&
          renderEditor.selection.isCollapsed) {
        final currentTextPosition =
            TextPosition(offset: renderEditor.selection.baseOffset);
        final caretRect =
            renderEditor.getLocalRectForCaret(currentTextPosition);
        _textInputConnection!.setCaretRect(caretRect);
      }

      SchedulerBinding.instance!
          .addPostFrameCallback((_) => _updateCaretRectIfNeeded());
    }
  }
JalorOo commented 2 years ago

@jing-pei hi, thanks for your share, but i had any question, can you tell me which file to put these code, and which Zefyr version you fix, it priveledge for me to hearing from you.