1

I'm trying to develop a chat application and I'm looking for a way to have my maui Editor accepts the return key pressed as a send command.

Certainly the Editor doesn't have an AcceptsReturn property like WPF Textbox, and I can't use Entry because I absolutely need the multi line.

So is there an Editor attribute or a workaround in order to intercept the Return key and call a function with it?

My target is to have this Editor that once I type Return, it sends the text written inside this Editor, in other terms, it has to have the same functionality as the Send button.

In order to make this more clear, here's my Editor in my MainPage.xaml:

<Editor x:Name="txtPrompt"
        VerticalTextAlignment="Center" FontSize="18"
        Grid.Column="0"
        MaximumHeightRequest="100"
        Background="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource GraphiteDark}}" TextColor="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}"
        Margin="10,0,0,5" Placeholder="Fai una domanda"
        Keyboard="Chat" AutoSize="TextChanges" />
1
  • 1
    You may need to re-think your design. In a multi-line text, Return key means "go to next line". This is true in most UI platforms. Otherwise, there is no way for the user to start a new line. It sounds like you are using Editor to display a conversation; a sequence of lines entered by multiple users. A common solution is to have a separate Entry box, that user types into. Commented Jul 4 at 21:24

2 Answers 2

3

See my comment on question for a work-around that is often done.

If you really want to detect Return key, you can detect it indirectly, using OnTextChanged.

This requires subclassing Editor, then using your subclass in the XAML, instead of Editor. (Search for information elsewhere, about referencing your own class in XAML.)

public class EditorWithReturnHandling : Editor
{

public Action OnReturnKey;

private bool ProgrammaticTextChange = false;

protected override void OnTextChanged(string oldValue, string newValue)
{
    if (ProgrammaticTextChange)
        return;

    if (DidSeeReturnKey(oldValue, newValue))
        OnReturnKey?.Invoke();
}

public static bool DidSeeReturnKey(oldValue, newValue)
{
    if (newValue == null)
        return false;

    if (oldValue == null)
        oldValue == "";

    // Not tested. Might be `\r` or `\n`.
    return ((newValue.Length > oldValue.Length) && newValue.EndsWith("\n"));
}

// Call this to add text to Editor, that is NOT typed by this user.
public void AddTextFromAnotherUser(string text)
{
    ProgrammaticTextChange = true;
    try
    {
        Text += text;
    }
    finally
    {
        ProgrammaticTextChange = false;
    }
}
}

You'll also need to set value of OnReturnKey property of this control in your page's code-behind, to call a method in your page. Approximate details below:

In page's code-behind:

public MyPage()
{
    InitializeComponent();
    // myEditorWithReturnHandling must be an x:Name in XAML.
    myEditorWithReturnHandling.OnReturnKey = DetectedReturnKey();
}

private void DetectedReturnKey()
{
    ...
}
Sign up to request clarification or add additional context in comments.

1 Comment

LIMITATION: If user moves cursor to middle of text (e.g. tap somewhere within text on a mobile device), then hits Return key, this approach won't work as shown. The Return key won't be at end. The editor's text might already contain previously entered lines of text (with Returns), so you'll need to find where the two texts differ: compare strings oldValue newValue character by character until there is a difference. If the "new" character is a Return, then it was added at that spot in text.
2

I couldn't do it with Editor but I was able to add a return key handler to Entry with the help of Plugin.Maui.KeyListener.

    1. Use "Manage NuGet Packages ..." and add Plugin.Maui.KeyListener to your project
    1. Add using Plugin.Maui.KeyListener and .UseKeyListener() to your MauiProgram.cs
    1. Then create a reusable Entry with a return key handler:
public partial class MyEntry : Entry
{
  KeyboardBehavior keyboardBehavior = new();

  public MyEntry()
  {
    keyboardBehavior.KeyDown += OnKeyDown;
    keyboardBehavior.KeyUp += OnKeyUp;
    this.Behaviors.Add(keyboardBehavior);
  }

  void OnKeyUp(object? sender, KeyPressedEventArgs e)
  {
    switch (e.KeyChar)
    {
      case '\r':
        System.Diagnostics.Trace.WriteLine($"OnKeyUp: (handled): {e.Modifiers} {e.Keys} {e.KeyChar}");
        e.Handled = true;
        break;
      default:
        System.Diagnostics.Trace.WriteLine($"OnKeyUp: (pass-thru): {e.Modifiers} {e.Keys} {e.KeyChar}");
        break;
    }
  }

  void OnKeyDown(object? sender, KeyPressedEventArgs e)
  {
    switch (e.KeyChar)
    {
      case '\r':
        System.Diagnostics.Trace.WriteLine($"OnKeyReturn: (handled): {e.Modifiers} {e.Keys} {e.KeyChar}");
        e.Handled = true;
        break;
      default:
        System.Diagnostics.Trace.WriteLine($"OnKeyDown: (pass-thru): {e.Modifiers} {e.Keys} {e.KeyChar}");
        break;
    }
  }
}

4 Comments

Looks like KeyboardBehavior from Plugin.Maui.KeyListener can be attached to any MAUI VisualElement. Anyone wanting to test this with Editor could copy MyEntry.cs source file, change it to class MyEditor : Editor. If that works, this is a cleaner solution than my answer.
I attempted this on the Editor and was able to receive Enter KeyUp events. However, the Enter KeyDown events were still being handled by the Editor itself so the interception failed.
Ok, good to know. Not entirely surprising; Return key is a "normal" key in an Editor, not an event-causing key. For instance in native Android programming, IIRC, the closest one can get in modern APIs is a "text changed" event. Similar to what I show, but at the platform level I think there was more information. Cursor location perhaps.
... maybe is a more "localized" change at Android API level. To support "word replacement" logic. IIRC, Return key becomes "empty substring was replaced by Return key, at position NN". But that is different on each platform, so not exposed in MAUI.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.