ゴマちゃんフロンティア

アザラシが大好きなエンジニアの開発日記です

【Unity】InputFieldにフォーカスした際の全選択を無効化する方法

time 2017/03/04

というわけで、今回は UI の InputField に関するお話です!
InputField にフォーカスした際、全選択状態になってしまうのを何とかする方法について調査してみました!

20170304_01

Unity5.5 では、ActiveInputField() でフォーカスすると起こるようです。
プレイヤーにクリックさせる想定ならともかく、キーボード入力時に全選択状態でフォーカスされても面倒です。
当然ですが、全選択状態のまま入力すると、入力されいた文字が上書きされてしまいます。

結論から言うと、以下のどちらかの方法でいけるようです。
・InputField を継承したクラスで LateUpdate() をオーバーライドし、MoveTextEnd() を実行する
・コルーチン等でフォーカス後のフレームで MoveTextEnd() を実行する

後述しますが、ActiveInputField() 後に MoveTextEnd() を呼んでも上手くいきません。
何れも「フォーカス後に間を置いてから実行する」のがキモのようです。

原因

BitBucket の下記URL に InputField クラスの中身が載っています。

https://bitbucket.org/Unity-Technologies/ui/src/0155c39e05ca5d7dcc97d9974256ef83bc122586/UnityEngine.UI/UI/Core/InputField.cs

それによると、onFocus() 時に SelectAll() が呼ばれているようです。
条件分岐もしていないようなので、設定でどうにか出来るものでもなさそうです。

また上でも触れましたが、以下のようなコードでは解除されません。

input_field = this.GetComponent<InputField>();
input_field.ActivateInputField();
input_field.MoveTextEnd(false);

どうやら同一フレームではラベルのアップデートの関係(?)で動作しないようです。
さくっとスクリプトで制御できるかと思いきや、思わぬ苦戦を強いられることになりました。

解決法

解除自体は MoveTextEnd() を実行するだけで良いので、その実行タイミングの問題のようです。
海外のフォーラムで同じような質問がいくつかありましたが、方法としては「InputFieldを継承したクラスでオーバーライドして実行」か「コルーチン等でフォーカス後のフレームに実行する」のどちらかが多かったです。
自分は前者の「継承してオーバーライド」でやってみました!

using UnityEngine.UI;

public class InputFieldCustom : InputField {
    protected override void LateUpdate() {
        base.LateUpdate();

        MoveTextEnd(false);
    }
}

LateUpdate() をオーバーライドし、スーパークラスを呼び出した後に MoveTextEnd() を実行すれば良いらしいです。
あれこれ処理した後に MoveTextEnd() で選択状態を解除するイメージでしょうか。

その他、コードを見る限りでは OnFocas() をオーバーライドし、SelectAll() が呼ばれないようにしても上手くいきそうな気がします。
試していないので分かりませんが、何れも継承するやり方なら簡単に解決できます。

まとめ

そんなわけで、今回は InputField のフォーカス時の挙動について調査してみました!
UnityEngine のクラスを継承したことはなかったので、今後も選択肢の1つとして覚えておきたいです。

毎回書いたスクリプトを全部載せていましたが、今回からポイントを絞って紹介しようかと思います。
面白みのないコードを載せても記事が長くなってしまうだけなので・・・。
そろそろブログのデザインも作り直そうかと考えているので、しばらく試行錯誤しながら書いてみます。

down

コメントする