Как переопределить поведение кнопки завершения по умолчанию во входном поле в Unity?

#c# #unity3d #input-field

#c# #unity-игровой движок #поле ввода

Вопрос:

Я пытаюсь создать простой текстовый редактор в Unity.

Прямо сейчас я пытаюсь переопределить стандартную End функциональность клавиш клавиатуры.

Я использую «новую» систему пользовательского интерфейса и InputField в качестве текстового редактора. В нем включена многострочность. Обычно, когда вы нажимаете End (на обычной физической клавиатуре), когда фокус находится на InputField , курсор переходит в конец всего TextField . Я хочу, чтобы оно доходило только до конца текущей строки. В принципе, я хочу ту же функциональность, что и в обычных текстовых редакторах, таких как Notepad .

На данный момент у меня есть скрипт на InputField , который выглядит следующим образом:

 public InputField editor; // This is the InputField

void Update() 
{
    if (Input.GetKeyDown(KeyCode.End))
    {
        string code = editor.text;
        int caretPos = editor.caretPosition;

        int newLineIndex = FindEndOfLine(code, caretPos);
        editor.caretPosition = newLineIndex;
    }
}

int FindEndOfLine(string text, int startIndex)
{
    for (int i = startIndex; i < text.Length; i  )
    {
        Debug.Log(text[i]);

        if (text[i] == 'n')
        {
            Debug.Log("FOUND IT: "   i);
            return i;
        }
    }

    return text.Length;
}
  

Если я использую это для другого ключа, например KeyCode.Y , то это работает довольно хорошо. Он находит правильное положение курсора и перемещает курсор в это место. Однако затем он также печатает символ Y .

Когда я использую KeyCode.End и нажимаю End клавишу, она просто переходит к концу всего TextField . Итак, я думаю, что мой код работает, но он выполняет обычную End функциональность ключа после выполнения моего скрипта.

Как мне предотвратить это поведение по умолчанию? Я гуглил в течение 25 минут.

Ответ №1:

Пожалуйста, попробуйте следующее решение. Вы должны унаследовать InputField класс, переопределить Rebuild метод, чтобы сохранить CaretPosition и переопределить LateUpdate метод, чтобы изменить поведение End ключа. Когда вы закончите, замените InputField компонент на вашем GameObject на ваш CustomInputField скрипт.

 using UnityEngine;
using UnityEngine.UI;

public class CustomInputField : InputField
{
    private int oldCaretPosition;

    public override void Rebuild(CanvasUpdate update)
    {
        base.Rebuild(update);
        oldCaretPosition = caretPosition;
    }

    protected override void LateUpdate()
    {
        base.LateUpdate();
        if (Input.GetKeyDown(KeyCode.End))
        {
            int newLineIndex = FindEndOfLine(oldCaretPosition);
            caretPosition = newLineIndex;
        }
    }

    private int FindEndOfLine(int startIndex)
    {
        for (int i = startIndex; i < text.Length; i  )
        {
            if (text[i] == 'n')
            {
                return i;
            }
        }
        return text.Length;
    }
}
  

Комментарии:

1. Сработало как по волшебству. Я собираюсь погуглить это, но не могли бы вы вкратце объяснить, что делают методы LateUpdate и Rebuild и почему мне нужно поместить обработчик KeyDown сюда, а не как отдельный скрипт?

2. Итак, логика следующая. Прежде всего, нам нужно сохранить положение курсора, прежде чем он будет перемещен в конец текста. Я попытался найти метод, который можно было бы переопределить и сохранить положение курсора. Оказалось, что Rebuild метод подходит для этой цели. Я выбрал этот метод только по моему предположению. Как говорится в документации, Rebuild метод перестраивает геометрию полей ввода. (курсор и выделение). LateUpdate вызывается после того, как были вызваны все Update функции. Таким образом, это дает мне возможность переместить курсор в конец строки после того, как он был перемещен в конец текста.