1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[Unity]iosでキーボードから文字入力をする&キャンセル処理

Posted at

概要

環境
Unity 2019.4.5f1
Xcode 11.6
ios 13.5.1

InputField公式リファレンス
https://docs.unity3d.com/2019.1/Documentation/ScriptReference/UI.InputField.html

InputField

InputFieldはPCだとキーボードから入力可能だが、スマホへBuildするとスマホのキーボードが出てきて入力が可能になる。

実装は簡単で、Create/UIから選択するだけでいろいろ整えてくれたオブジェクトを出してくれる。
こちらでやるべき部分は下のコード部分。

InputFieldManager.cs
using UnityEngine.UI;

public class InputFieldManager : MonoBehaviour {

  private InputField inputField;
  public string resultText;   // 入力されたテキストを格納

  void Start(){
    inputField = this.gameObject.GetComponent<InputField>();
    InitInputField ();
  }

  // フィールドの初期化
  private void InitInputField () {
    inputField.text = "";
    inputText = "";
  }

  // OnValueCangeで呼び出す関数
  public void ChangeText(){
    // 入力したテキストをstringに格納する
    resultText = inputField.text;
  }

  // OnEndEditで呼び出す関数
  public void FinishEditText(){
    // 入力が終わった後にどこかに渡すとか
    
    // 入力が終わったので初期化
    InitInputField ();
  }
}

スクリプトを書いたら、適当なオブジェクト(InputFieldやInputPanelなど)にアタッチして、インスペクターからOnValueChangedとOnEndEditのそれぞれにどの関数を呼び出すか指定する。

ちなみに呼び出される順番はOnValueChanged(inputField.textが変わるたびに) → OnEndEdit

キャンセル処理

LINEなどを使ってる時を想像して欲しい。
何かを入力していたが、あれ?と思って一旦中断してキーボードを消し、確認した後で再入力ということがあると思う。

CPと挙動が異なる点として、PCはOnEndEditが呼ばれたりinputField.isFocused == falseの場合でも、InputFieldにあるテキストは消えないが、
iosの場合、InputFieldではキーボードを消してしまうとInputFieldにあるテキストも消えてしまう。

そこで入力をキャンセルした時にInputFieldにあるテキストを保持したい。
テキストの保持は以下のコードでできる。
注意点として、TouchScreenKeyboard.isSupported=true(Unity Editorは=false)環境のみでTouchScreenKeyboard.Statusは動作する。#if UNITY_IOSなどで囲んでおくといいかも。

InputFieldManager.cs
bool isCancel = false;

// OnValueCangeで呼び出す関数
public void ChangeText(){
  if (inputField.touchScreenKeyboard.status == TouchScreenKeyboard.Status.Canceled) {
    // Cancleを押した時
    isCancel = true;
  } else if (inputField.isFocused && !isCancel){
    // 他のところをタップした時
    inputText = inputField.text;
    Debug.Log ("inputText: " + inputText);
   }
}

// OnEndEditで呼び出す関数
public void FinishEditText(){
  if (inputField.touchScreenKeyboard.status == TouchScreenKeyboard.Status.Done) {
    // 入力完了時何かに渡す

    // フィールドの初期化
    InitInputField ();
    Debug.Log ("Done");
  } else if (inputField.touchScreenKeyboard.status == TouchScreenKeyboard.Status.Canceled || inputField.touchScreenKeyboard.status == TouchScreenKeyboard.Status.LostFocus) {
    // 入力キャンセル時もしくは
    inputField.text = inputText;
    isCancel = false;
    Debug.Log ("Canseled");
  } else { 
    // 他の部分をタップした場合
    inputField.text = inputText;
    isCancel = false;
    Debug.Log ("Canseled");
  }
}

キーボードとInputField以外の部分をタップするとinputField.isFocused == falseとなり、キーボードが消えてしまう。なぜか、

inputField.touchScreenKeyboard.status == TouchScreenKeyboard.Status.LostFocus 

は呼ばれないようなのでFinishEditTextではelseにもキャンセルされたと認識して同じ処理をしている。
また、inputField.isFocused == falseを利用して他のところがタップされた時はテキストは更新されないようにしている。

他にはまった点としては元々はChangeTextでもresultText = inputField.textという処理を行っていたが、入力した後にCancelボタンを押すとなぜかinputField.text = ""という挙動になった。どうやらデフォルトっぽい挙動だが、邪魔だったのでChangeTextでキャンセルが押された場合にはフラグを変更させるだけにさせた。

フラグを作った理由としてはCancelを押してキーボードを閉じた場合、inputField.isFocused == trueとなりつつinputField.text = ""が入ってしまうので、他の部分をタップした時と区別するために行っている。

位置調整

下からキーボードが出てくるため何もしなければキーボードで見えなくなる部分が出てくる。
今回はゴリ押しでキーボードの高さを調べて、重なってしまうUIの位置を上にずらすことで対応した。

動かすUIは一括りのGameObjectに入れてlocalPositionで変更するのが楽。今回の場合は、InputPanelの上にさらにまとめるGameObjectがあったのでそれを移動させている。

InputFieldのみの移動で大丈夫なら、InputPanelをlocalPosition.y変更すればいい。

Start時に初期位置を保存しておき、inputField.isFocusedの時一回だけ移動させるようにしてる。
キャンセルか何かでキーボードが消えた時に初期位置を代入してやると元に戻る。

private void StartInputText () {
  if (inputField.isFocused && isOnceInput) {
    isOnceInput = false;
    // y軸をいい感じの値にする
    parentRect.localPosition += new Vector3 (0, 940f, 0);
  }
}

最終的なコード

InputFieldManager.cs
using UnityEngine;
using UnityEngine.UI;

public class InputFieldManager : MonoBehaviour {
  private InputField inputField;
  public string resultText;   // 入力されたテキストを格納

  private RectTransform parentRect;
  private Vector3 defaultParentPos;  // 初期位置
  private bool isOnceInput = true; // 入力時のfooter・bodyの位置移動フラグ
  
  private bool isCancel = false;  // cancelボタンが押されたか


  void Start(){
    inputField = this.gameObject.GetComponent<InputField>();
    parentRect = this.transform.parent.GetComponent<RectTransform> ();
    defaultParentPos = parentRect.localPosition;
    InitInputField ();
  }

  void Update(){
    StartInputText ()
  }

  // 入力開始時
  private void StartInputText () {
    if (inputField.isFocused && isOnceInput) {
      isOnceInput = false;
      // y軸をいい感じの値にする
      parentRect.localPosition += new Vector3 (0, 940f, 0);
    }
  }

  // キーボードによって上にずれたUIの位置を戻す
  public void ResetKeybord () {
    isOnceInput = true;
    parentRect.localPosition = defaultParentPos;
    isCancel = false;
  }

  // フィールドの初期化
  private void InitInputField () {
    inputField.text = "";
    inputText = "";
    ResetKeybord ();
  }

  // OnValueCangeで呼び出す関数
  public void ChangeText(){
    if (inputField.touchScreenKeyboard.status == TouchScreenKeyboard.Status.Canceled) {
      // Cancleを押した時
      isCancel = true;
    } else if (inputField.isFocused && !isCancel){
      // 他のところをタップした時
      inputText = inputField.text;
      Debug.Log ("inputText: " + inputText);
     }
  }

  // OnEndEditで呼び出す関数
  public void FinishEditText(){
    if (inputField.touchScreenKeyboard.status == TouchScreenKeyboard.Status.Done) {
      // 入力完了時何かに渡す

      // フィールドの初期化
      InitInputField ();
      Debug.Log ("Done");
    } else if (inputField.touchScreenKeyboard.status == TouchScreenKeyboard.Status.Canceled || inputField.touchScreenKeyboard.status == TouchScreenKeyboard.Status.LostFocus) {
      // 入力キャンセル時もしくは
      inputField.text = inputText;
      ResetKeybord ();
      Debug.Log ("Canseled");
    } else { 
      // 他の部分をタップした場合
      inputField.text = inputText;
      ResetKeybord ();
      Debug.Log ("Canseled");
    }
  }
}

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?