Android
 Computer >> コンピューター >  >> プログラミング >> Android

【Android開発】EditTextがフォーカスを失ったことを検知する方法を実例付きで解説

この記事では、Androidアプリ開発においてEditTextがフォーカスを失ったタイミングを検知する方法を、実際に動作するサンプルコードとともに解説します。フォーム入力のバリデーションや入力完了時の処理など、フォーカス状態の変化を扱いたい場面は多く、setOnFocusChangeListenerを使えば簡単に実装できます。

実装の全体像

今回作成するサンプルアプリは以下の構成です。

  • EditText(フォーカスの対象)× 1つ
  • 「フォーカスを外す」ボタン × 1つ
  • 「フォーカスを取得する」ボタン × 1つ

ボタンをタップすることでEditTextのフォーカスを切り替え、その変化をリスナーで検知してToastメッセージで表示します。

ステップ1:プロジェクトの作成

まず、Android Studioで新しいプロジェクトを作成します。メニューから「File → New Project」を選択し、必要な項目を入力してプロジェクトを作成してください。

ステップ2:レイアウトファイルの作成

次に、res/layout/activity_main.xmlに以下のコードを追加します。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    android:id="@+id/parent"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:gravity="center"
    android:orientation="vertical">

    <EditText
        android:id="@+id/editText"
        android:hint="Loosing focus example"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/removeFocus"
        android:text="Remove Focus"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/gainFocus"
        android:text="Gain Focus"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

このレイアウトでは、EditTextを1つとボタンを2つ配置しています。「Remove Focus」ボタンでEditTextからフォーカスを外し、「Gain Focus」ボタンで再びフォーカスを取得できるようにします。

ステップ3:MainActivity.javaの実装

続いて、src/MainActivity.javaに以下のコードを記述します。

package com.example.andy.myapplication;

import android.os.Build;
import android.os.Bundle;
import android.support.annotation.RequiresApi;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    int view = R.layout.activity_main;
    EditText editText;
    Button removeFocus, gainFocus;

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(view);

        editText = findViewById(R.id.editText);
        removeFocus = findViewById(R.id.removeFocus);
        gainFocus = findViewById(R.id.gainFocus);

        // フォーカスを取得するボタン
        gainFocus.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                editText.setFocusableInTouchMode(true);
                editText.setFocusable(true);
            }
        });

        // フォーカスを外すボタン
        removeFocus.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                editText.setFocusableInTouchMode(false);
                editText.setFocusable(false);
            }
        });

        // フォーカス状態の変化を検知するリスナー
        editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                if (!hasFocus) {
                    Toast.makeText(MainActivity.this,
                            "focus loosed", Toast.LENGTH_LONG).show();
                } else {
                    Toast.makeText(MainActivity.this,
                            "focused", Toast.LENGTH_LONG).show();
                }
            }
        });
    }
}

ポイント解説:フォーカス制御のキーとなるコード

フォーカスを外す方法

「Remove Focus」ボタンが押されたときには、以下のコードでEditTextをフォーカス不可の状態にしています。

editText.setFocusableInTouchMode(false);
editText.setFocusable(false);

setFocusable(false)だけでも十分な場合が多いですが、タッチ操作でのフォーカス取得も無効化するためにsetFocusableInTouchMode(false)も併せて設定するのが確実です。

フォーカスを取得する方法

逆にフォーカスを再度受け付けたい場合は、以下のように両方のフラグをtrueに戻します。

editText.setFocusableInTouchMode(true);
editText.setFocusable(true);

フォーカスの変化を検知する方法

本題である「フォーカスを失ったことを知る」処理は、setOnFocusChangeListener()で実現します。

editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (!hasFocus) {
            // フォーカスが外れたときの処理
            Toast.makeText(MainActivity.this,
                    "focus loosed", Toast.LENGTH_LONG).show();
        } else {
            // フォーカスを得たときの処理
            Toast.makeText(MainActivity.this,
                    "focused", Toast.LENGTH_LONG).show();
        }
    }
});

コールバックの引数hasFocustrueならフォーカス取得中、falseならフォーカス喪失を意味します。!hasFocusの分岐内に、入力値のチェックや保存などの処理を書けば、実用的なフォーム制御が可能になります。

アプリの実行と動作確認

それではアプリを実行してみましょう。実機のAndroidスマートフォンをPCに接続している場合は、Android Studioでプロジェクト内のアクティビティファイルを開き、ツールバーの「Run」アイコンをクリックします。デバイスを選択して実行すると、以下のような初期画面が表示されます。

【Android開発】EditTextがフォーカスを失ったことを検知する方法を実例付きで解説

上記の実行結果では「Remove Focus」ボタンをタップした直後の状態です。画面下部に「focus loosed」というToastメッセージが表示され、フォーカスが外れたことが検知できています(カーソル位置にも注目してください)。続いて「Gain Focus」ボタンをタップすると、今度は「focused」と表示され、フォーカスが再び取得されたことが確認できます。

【Android開発】EditTextがフォーカスを失ったことを検知する方法を実例付きで解説

まとめ

EditTextのフォーカス状態の変化は、setOnFocusChangeListener()とコールバック引数hasFocusの組み合わせで簡単に検知できます。また、setFocusable()setFocusableInTouchMode()を組み合わせれば、フォーカスの可否自体もプログラムから制御可能です。入力フォームのバリデーションや、他ビューへのフォーカス移動など、さまざまなUI実装に応用してみてください。

  1. 【Android開発】Switchウィジェットのスタイルをカスタマイズする方法を徹底解説

    Android Switchウィジェットのスタイルをカスタマイズする方法 このチュートリアルでは、AndroidアプリのSwitch(スイッチ)ウィジェットの見た目を自由にカスタマイズする方法を紹介します。thumb(つまみ)とtrack(レール)に独自のDrawableを指定することで、ON/OFFの状態に応じてデザインが切り替わるオリジナルスイッチを作成できます。 ステップ1:新規プロジェクトを作成する Android Studioを起動し、メニューから「File」→「New Project」を選択します。必要な項目を入力して、新しいプロジェクトを作成しましょう。 ステップ2:レイアウトフ

  2. Androidのフォーカスモードの使い方|SNSなど気を散らすアプリを制限する設定手順

    SNSの使いすぎを防ぎたいのに、どのアプリを選べばいいのか迷っていませんか?実は、Androidには標準搭載された「フォーカスモード(Focus Mode)」という便利な機能があり、追加アプリを探す必要はありません。フォーカスモードはAndroid 10の登場とともに導入され、ベータ版を卒業した現在では、多くのAndroidユーザーが利用できるようになっています。 ユーザーの健康に焦点を当てた「デジタルウェルビーイング」は、これまでのAndroidの大きな変化の中でも特に好評を得ている機能です。InstagramやFacebookなどの大手SNSプラットフォームの多くも、すでにアクティビティト