InputFieldを実装したゲームを実行し、日本語を入力しようと
入力文字を変換すると下記の画像のようになります。
画像では見えにくいですが、入力文字が変換中なのか確定済みなのかが判別できません。
変換中の場合は文字に波線または下線を加えることは可能でしょうか。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答1件
0
ベストアンサー
確かに確定済みと変換中の区別がつかないのは気になりますね。調べてみたものの、インスペクタから設定をいじって手軽にできるような方法はないかもしれません。何とかならないかと思い実験してみましたが、ちょっとトリッキー感のあるものになってしまいました。
下記スクリプトを作成し、InputFieldにアタッチして実行してみたところ、
C#
1using System.Collections; 2using System.Reflection; 3using UnityEngine; 4using UnityEngine.UI; 5 6[RequireComponent(typeof(InputField))] 7public class InputFieldCompositionStringColorizer : MonoBehaviour 8{ 9 // 変換中文字列を何色で表示するか? 10 [SerializeField] private Color compositionStringColor = Color.blue; 11 12 private IEnumerator Start() 13 { 14 // 文字列の整形時に位置の手がかりとなる各種フィールドは、アクセシビリティレベルが 15 // protectedなのでむりやり探し出さないといけない 16 var caretPositionField = typeof(InputField).GetField( 17 "m_CaretPosition", 18 BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic); 19 var drawStartField = typeof(InputField).GetField( 20 "m_DrawStart", 21 BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic); 22 var drawEndField = typeof(InputField).GetField( 23 "m_DrawEnd", 24 BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic); 25 26 // 非公開のメンバーはUnityのバージョンアップで予告なしに使えなくなるかもしれないので... 27 if ((caretPositionField == null) || (drawStartField == null) || (drawEndField == null)) 28 { 29 // フィールドの取得に失敗したら、このスクリプトコンポーネントは削除する 30 Debug.LogError("Couldn't find non-public members."); 31 Destroy(this); 32 yield break; 33 } 34 35 // InputFieldに参照されているTextはInputFieldのコントロール下にあるので 36 // リッチテキスト機能が使えないため、Textを複製してそれを表示用に使う 37 var field = this.GetComponent<InputField>(); 38 var text = field.textComponent; 39 var richText = Instantiate(text, text.transform.parent); 40 richText.name = "RichText"; 41 richText.supportRichText = true; 42 43 // 入力用Textは文字色を透明にする 44 text.color = Color.clear; 45 46 // 入力用Textの文字色を変えるとキャレットの色まで変わってしまうので、InputFieldは 47 // カスタムキャレット色を使うようにして、元のテキストの色をセットする 48 field.customCaretColor = true; 49 field.caretColor = richText.color; 50 51 // 前のフレームの入力用Textの内容を覚えておくための変数 52 var previousTextString = text.text; 53 54 // Textの兄弟関係調整(後述)が終わったかどうかを示すフラグ 55 var hierarchyAdjusted = false; 56 57 // 「変換中」から「非変換中」への変わり目を検出するためのフラグ 58 var compositionStringEmptied = false; 59 60 // 「変換中」から「非変換中」へ変わった後、さらにもう1回だけ表示用Textの文字列設定を走らせるためのフラグ 61 var needsReassignTextString = false; 62 63 // 準備が整ったら、あとは毎フレーム文字列を監視して色付け処理を行う 64 while (true) 65 { 66 // 表示用Textが入力用Textよりも手前に来るようにヒエラルキー上の兄弟関係を調整する 67 if (!hierarchyAdjusted) 68 { 69 var textSiblingIndex = text.transform.GetSiblingIndex(); 70 var richTextSiblingIndex = richText.transform.GetSiblingIndex(); 71 if ((textSiblingIndex + 1) != richTextSiblingIndex) 72 { 73 richText.transform.SetSiblingIndex(textSiblingIndex + 1); 74 hierarchyAdjusted = true; 75 } 76 } 77 78 // 変換中の文字列を取得 79 var compositionString = Input.compositionString; 80 var compositionStringLength = compositionString.Length; 81 82 // 入力用Textの表示内容を取得 83 var textString = text.text; 84 85 // 変換中であれば(変換中文字列が空でなければ)... 86 if ((compositionStringLength > 0) || needsReassignTextString) 87 { 88 // まず現在のInputFieldの文字列(まだ変換中文字列が挿入されていない)を取得 89 var fieldText = field.text; 90 var fieldTextLength = fieldText.Length; 91 92 // 変換中文字列を挿入するべき位置を調べる 93 // ※field.caretPositionというプロパティもありますが、それとはちょっと位置が違うようです 94 var insertAt = (int)caretPositionField.GetValue(field); 95 96 // 挿入後文字列から表示用に切り出す範囲を調べる 97 var clipFrom = (int)drawStartField.GetValue(field); 98 var clipTo = Mathf.Min( 99 (int)drawEndField.GetValue(field), 100 fieldTextLength + compositionStringLength); 101 var clipLength = clipTo - clipFrom; 102 103 // 元の文字列に変換中文字列を挿入する 104 var concatenatedString = fieldText.Insert(insertAt, compositionString); 105 106 // 挿入後文字列の中のタグを付けるべき範囲を求める 107 var tagFrom = Mathf.Max(insertAt, clipFrom); 108 var tagTo = Mathf.Min(insertAt + compositionStringLength, clipTo); 109 var tagLength = Mathf.Max(tagTo - tagFrom, 0); 110 111 // 目的の範囲の前後にタグを挿入する 112 var openTagLength = 0; 113 var closeTagLength = 0; 114 if (tagLength > 0) 115 { 116 var openTag = $"<color=#{ColorUtility.ToHtmlStringRGBA(this.compositionStringColor)}>"; 117 const string closeTag = "</color>"; 118 concatenatedString = concatenatedString.Insert(tagTo, closeTag); 119 concatenatedString = concatenatedString.Insert(tagFrom, openTag); 120 openTagLength = openTag.Length; 121 closeTagLength = closeTag.Length; 122 } 123 124 // タグ付きの挿入後文字列から表示範囲を切り出し、表示用Textにセットする 125 var newTextString = concatenatedString.Substring(clipFrom, openTagLength + clipLength + closeTagLength); 126 richText.text = newTextString; 127 128 // 未確定文字を削除することによって「非変換中」に戻った場合に、最後の未確定文字の残骸が残ってしまうようなので 129 // その対策として「非変換中」に戻った後にもう一回だけ表示用Text更新を行わせることにした 130 // 何も特別なスクリプトを付けていないInputFieldでもこの現象が起こるようだが、InputField自体の不具合だろうか...? 131 if (needsReassignTextString) 132 { 133 text.text = newTextString; 134 needsReassignTextString = false; 135 } 136 else 137 { 138 compositionStringEmptied = true; 139 } 140 } 141 else if (compositionStringEmptied) 142 { 143 compositionStringEmptied = false; 144 needsReassignTextString = true; 145 } 146 // 変換中でなくとも、入力用Textの内容に変化(スクロールした、削除した、直接入力したなど)があったら... 147 else if (textString != previousTextString) 148 { 149 // 表示用Textの内容を更新する 150 richText.text = textString; 151 previousTextString = textString; 152 } 153 154 yield return null; 155 } 156 } 157}
下図のように変換中の部分が青色で表示されるようになりました(Unity 2018.3.6f1、Windows 10 Home バージョン1803上でプレイモードで動かし、Microsoft IME 10.0.17134.1で入力)。
protectedフィールドを勝手に覗いていますが、UnityのアップデートでInputFieldの実装が変われば急に動かなくなる可能性があります。また、動きの確認もプレイモードでちょこっとやっただけですので、どの環境でも大丈夫かというと保証しかねます。
また、ご所望の下線ではなく色付けになってしまいすみません。リッチテキストの機能で下線ぐらい付けられるだろう、と思っていたらダメでして(リッチテキスト - Unity マニュアルに使えるタグの一覧がありますが、下線は載っていませんでした)、もしやるとしたら文字の幅やらを勘案して座標を求め、自前で線を引くことになりそうだったため妥協しました...
そして変換中の文字は一律青色です。変換済み文節と未変換文節を塗り分けるのはもっと難しそうです(そもそも可能なのかも未調査です)。
投稿2019/02/22 11:14
総合スコア10811
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/02/28 10:39
2019/02/28 11:49