IME変換前後のテキストの取得
エディットテキスト内で日本語入力などをするとき、KeyListenerを使うだけでは変換される前のキーボード上での文字列は取得できます。
しかし、IMEなどのソフトウェアで変換された文字列は取得できません。
そこでエディットテキスト内で変換された文字列を受け取るにはTextWatcherというインターフェイスをエディットテキストに次のように実装します。
public class MainActivity extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextEdit editText = findViewById(R.id.editText); //TextWatcherを実装 editText.addTextChangedListener(new TextWatcher(){ public void afterTextChanged(Editable s) { Log.d("MainActivity : ", "変換後のテキスト = " + s.toString()); } public void beforeTextChanged(CharSequence s, int start, int count, int after) { Log.d("MainActivity : ", "変換直前のテキスト = " + s.toString()); } public void onTextChanged(CharSequence s, int start, int before, int count) { Log.d("MainActivity : ", "変換直後のテキスト = " + s.toString()); } }); } }
addTextChnagedListenerメソッドでTextWatcherインターフェイスを実装できます。このインターフェースは次のメソッドを持ちます。
- void afterTextChanged(Editable s)
完全に変換された後の文字列sを受け取ります。
- void beforeTextChanged(CharSequence s, int start, int count, int after)
長さがcountでstartから始まる文字列が長さafterの文字列に変換される直前に呼び出されます。sが変換後の文字列です。
- void onTextChanged(CharSequence s, int start, int before, int count
長さがcountでstartから始まる文字列を長さbeforeの文字列に変換された直後に呼ばれます。sが変換前の文字列です。
この3つのメソッドを使えば、変換前、直前、直後のエディットテキストなどの文字列を取得することが可能になります。
TextWatcherを実装するときの注意点
TextWatcherはエディットテキストなどで変換される文字を監視するためのものなので次のようにエディットテキスト内のテキストを変更するような処理はできません。
final TextEdit editText = findViewById(R.id.editText); //TextWatcherを実装 editText.addTextChangedListener(new TextWatcher() { public void afterTextChanged(Editable s) { editText.setText(s.toString().replace("!", "?")); } public void beforeTextChanged(CharSequence s, int start, int count, int after){} public void onTextChanged(CharSequence s, int start, int before, int count){} });
このコードではafterTextChangedメソッド内で取得したテキストを置換した文字列をエディットテキストに表示しようとしています。
これを実行するとStackOverflowErrorといってメモリのスタック領域を全て使い果たした時に発生するエラーが生じます。
なぜそのようなエラーが出るかというとTextWatcherはプログラム的にエディットテキストの内容を書き換えた時にも呼び出され、afterTextChangedメソッドなどが無限に呼び出されるからです。
なのでTextWatcher内ではテキストの監視のみしか行うことができません。