Autocompletion for InputField

Demo1 Demo2
The InputFieldWithAutocompletion asset proposes a modified InputField element with a word suggestion system, obviously created with the new unity GUI.
In its simplest form all you have to do is add the element via the GameObject menu and choose a list of word. Aesthetic choices are up to you after that.

Autcompletion Example

How To

Add the Autocompletion element to your object hierarchy:

In the GameObjects menu, in the top banner or in the object Hierarchy "Create" find: GameObject/UI/Autocomplete.

If no root Canvas element exists, one will be created for you (along with an EventSystem object if needed). The autocomplete object will be automatically set as a child of the root canvas or to another GameObject, if said GameObject is selected and contains a CanvasRenderer component.

When created, the focus is automatically given to the WordList element, because this is the only object you will need to configure. Precisely: in the WordListBehaviour component, you have to choose a Text Asset for the "Word List" object reference. By default the InputField created has a height of 30 pixels and is single-lined.

The full UI element is made out of 8 sub-elements:

The InputField itself is the root element, the Autocompletion and InputFieldModified components are attached to it; it contains the Placeholder and the Text (as well as the Caret created at runtime).

To this we added the WordList element. And to that last element is attached the WordListBehaviour component. As children we can see a Container (that will receive the items of the list) and a normal Scrollbar UI element. All of these are created and set for you with each of their own script components attached when you choose to create this asset from the GameObject menu.
Object Hierarchy

WordList

A word list is simply a text file containing words separated by commas. Be sure not to insert any unneeded elements between words, like a space after a comma for example.

The words will be displayed in the same order they are found in the WordList.

I suggest you sort the words alphabetically and use only lowercase. This last part is needed because when a word is chosen from the suggestions, it is inserted into the text as it is found in the list. In all caps if this is how it is in the list.

Options

Force Choose: if true the selected word will be chosen and will be inserted into the InputField's text when a punctuation character is entered. If false, you can only choose a word by pressing Enter/Return or clicking it.
Respect Case: if true, the chosen word will not replace the part of the word that is already input. E.g. typing "AsS" then choosing the word "asset" will result in the word "AsSet".
Activate On BackSpace: if true, the DropList will also activate when deleting letters with the backspace key.
Delay*: this is the delay before the DropList is activated, it starts anew after each new letter typed. This means that this is the delay in second before the DropList appears after the user has stopped writing.
Offset: X and Y offsets applied to the suggestion list relative to the word being typed by the user.
Inspector AutoCompletionBehaviour
Inspector WordListBehaviour Item Prefab: the prefab used as items in the list. One is provided and assigned by default.
Word List: as a TextAsset, a list of word separated only by commas. This is the only thing you need to modify for this UI element to work.
DTime: the speed at which the DropList can be navigated using the Up and Down arrows.
Min Letters To Activate: how many letters are needed before the DropList can activate.
Max Words Displayed: how many words are displayed in one page of the DropList
Max Words Proposed: how many words are displayed in total by the DropList.

*Delay:

Adding a delay before activation will permit the user to write more letters before suggesting words. It will also improve the script performances as the DropList will not be updated or positioned before the user actually needs suggestions. The query and positioning processes are somewhat demanding (more info here), but they will not be triggered too often thanks to the delay. However, note that this delay is only used when the DropList isn't active, if the user is adding letters while the DropList is activated the Delay will be ignored (we don't want the user to wait for a reduced number of possible words).

Features

Tab Key:

The Tabulation key is used to toggle the suggestions. Consequently, the character "\t" is disabled. The DropList will activate only if there are possible words to suggest and if the caret's position is inside a word in the InputField.

Choosing a word suggested:

After navigating to the desired word, click it or press enter. If you have set ForceChoose to true, press any punctuation characters to choose a word.

The DropList will always activate if:

The number of letters in the currently typed word is equal or over MinLettersToActivate's value.

The DropList will always deactivate if:

The following keys are pressed: Tab, Escape, Enter, Return, Right arrow and Left arrow.

Line Type:

The three types of InputField LineTypes can be used with the Autocompletion element to work. If you set it to "Single Line" the DropList can be activated by pressing the DownArrow. Also remember, that if the DropList is activated, the Return/Enter keys will deactivate it but will not deselect the InputField until you press them a second time.

Once activated, you can navigate the DropList with the Down or Up arrows or with the mousewheel.

Choosing a word:

You can choose a word in the suggestion list by clicking it or by pressing Enter/Return with the desired word selected (highlighted in blue). The chosen word will be inserted into the InputField's text immediately.

Borders aware:

The DropList or part of it cannot appear out of the screen. It will be displayed above the word if its placement would put it below out of the screen. Same thing if you are writing close to the right edge of the screen, the DropList will stick to it but never be outside. You can test it easily with the first demo provided.

Editor Integration:

You can (and should) add the present UI asset through the GameObject menu (as explained here). The Autocompletion element is a group of 8 different GameObjects that are set up in a very precise way; for instance, it will not work if the pivot and anchors of the Scrollbar or of the Container panel aren't set correctly. I highly recommend adding the InputFieldWithAutocompletion element in its totality with the GameObjet menu.

FAQ

  • There is no items in my list or it isn't complete.
    • Be sure that there is a comma between all words without any other punctuations or line returns, like in the examples
  • Why are the edges of the scrollbar offset by a pixel to the right or to the top?
    • While running your game in the editor you will notice that in some cases the edges of the Scrollbar are not aligned with those of the WordList panel. This is a graphic bug that will not appear in your build, there is no need to compensate for this in the scripts.
  • How efficient are the scripts?
    • what takes most of the processing time are the method SetInsetAndSizeFromParentEdge and the first instantiations of items stocked thereafter in a pool. We reduced SetInsetAndSizeFromParentEdge calls as much as we could using clever placements of the pivot and the anchors.
    • If you chose to suggest a lot of words (200+), the first time the items are instantiated will take longer (~0.05 to ~0.08 sec), there is a way around it. After this first run, everything will be much faster, you can reduce this by activating only after 2 or 3 letters or after 0.5sec to give the user ample time to write several letters before processing a query.
    • You can instantiate the max number of items at the start by calling the UpdateList method with a single letter as arguments, choose a letter that returns the max number of words.
  • I have some more questions!
    • The source is well-documented but it is very possible I didn't make some things clear enough. If this is the case -or if you have any interrogation- don't hesitate to send me a message through the support mail you've got via the Unity Asset Store.

Miscellaneous

StackOverflowExceptions.

This is due to the fact that the ScrollBar Value is corrected for custom steps, which triggers the Setvalue from the ScrollBar script, which triggers our step correction, etc. This exception should never be raised, but if you modify parts of the program related to the Scrollbar's value, be cautious and keep this in mind.

The DropList will toggle/appear even if there is only one word proposed.

This results in the fact that the DropList ends up suggesting the very same word the user wrote. You can change this behaviour by replacing (WordListBehaviour:410) word.Length <= w.Length with word.Length <w.Length.

InputField deselection.

A click outside of the DropList will only deactivate it, the InputField will stay selected until a second click happens out of it too.

Special Words.

If you want to use words that don't begin with a letter, add the special characters in the string of letters in WordListBehaviour.cs:147.

Processing Time.

In the code you will see lines using the variable DProcessTime. Uncomment them if you want to see the execution time of the query and DropList activation processes.

AddListener.

No need to set methods via the editor for OnValueChanged in the InputFieldModified or Scrollbar script as it is done in the Start methods. This ensures that this autocompletion asset only needs a word list to work, you don't need to do anything else.

What constitutes a word.

The DropList of word suggestions will activate if the caret is anywhere in the word. A word is defined as beginning after the first letter and ending after the last.

You should not change the GameObject's name of items in the DropList.

For simplicity it is the string value retrieved when we want to add a selected word in the InputField's text.

Bool ShowOnBackSpace.

The real use of this field is to stop the modified InputField componenet from sending OnValueChanged when the input is a backspace, thus not activating the DropList.