Android の EditText の文字列と、String 変数値を同期させたいケースって結構あると思うんですけど、LostFocus みたいなのでやると、オンフォーカスな状態で Activity が閉じられた時に LostFocus が呼ばれなくてあぼんとなるのは VB6あがりのプログラマ(=私)なら誰もが経験するんじゃないでしょうか?

じゃあ [onTextChanged](http://developer.android.com/reference/android/text/TextWatcher.html#onTextChanged(java.lang.CharSequence, int, int, int) だぜ、って仕込んでみると、Android のこれは IME で変換中の文字列もバンバン飛んで来まして大変使い勝手が悪い。(サジェストなんかする際には必要なんでしょうけども)

例えば、以下で紹介されている方法

を実装しますと、IME確定前の文字列もじゃんじゃん同期してくれちゃいます。

これに起因したであろう Android アプリもありまして(Instagram とか。今は治ってる。)、なんとかならんかなーと思っていました。

そんな時、こちら↓

の記事にめぐり逢いまして、まさに私が求めていたそのもの。

ですが、未確定文字=下線付き(UnderlineSpan)である、という前提がどうにもしっくり来ませんで(未確定文字に下線を付けない IME もそりゃあるだろうなーという意味で)。

もちろん、その前で言及されている内部クラス android.view.inputmethod.ComposingText を文字列比較するのもうーん…。

で、自分でも試行錯誤してみたところ、[Spanned.getSpanFlags](http://developer.android.com/reference/android/text/Spanned.html#getSpanFlags(java.lang.Object) というメソッドがあるのに気づきました。あと、SPAN_COMPOSING というフラグも。

これらを使って、文字列が確定されているかどうか?を識別することができるのではないかと考え、前出の記事のコードを以下のように修正してみました。

```java DetermineComposingText.java
edit1.addTextChangedListener(new TextWatcher()
{
int currentLength = 0;

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {}

@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    currentLength = s.toString().length();
}

@Override
public void afterTextChanged(Editable s) {
    Log.v("", "after:" + s.toString());
    if (s.toString().length() < currentLength) {
        return;
    }
    boolean unfixed = false;
    Object[] spanned = s.getSpans(0, s.length(), Object.class);
    if (spanned != null) {
        for (Object obj : spanned) {
            // UnderlineSpan での判定から getSpanFlags への判定に変更。
            // if (obj instanceof android.text.style.UnderlineSpan) {
            if ((s.getSpanFlags(obj) & Spanned.SPAN_COMPOSING) == Spanned.SPAN_COMPOSING) {
                unfixed = true;
            }
        }
    }
    if (!unfixed) {
        Toast toast = Toast.makeText(getApplicationContext(), "確定", Toast.LENGTH_SHORT);
        toast.show();
    }
} }); ```

s.getSpanFlags(obj) & Spanned.SPAN_COMPOSING) == Spanned.SPAN_COMPOSING) で SPAN_COMPOSING(未確定文字)のフラグが立っているかを判定しています。

とりあえず手持ちの ATOK では修正前と同じように動作しているようです。

IME 側で「未確定文字は SPAN_COMPOSING を必ず設定する」ものかどうかは分かりませんが、個人的には UnderlineSpan を使った手法よりもすっきりしました、というお話でした。

Android

published

Ads

Read more!

amay077

Microsoft MVP(Xamarin). フルリモートワーカー. Geospatial Mobile app developer. Love C#.

amay077 amay077