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

AndroidのListView内でフォーカス可能なEditTextを実装する方法

はじめに

このチュートリアルでは、AndroidアプリのListView内にフォーカス可能なEditTextを作成する方法を解説します。リストの各行にEditTextを配置し、ユーザーが直接テキストを入力・編集できるようにするには、いくつかの重要な設定が必要です。以下の手順に沿って、サンプルコードとともに実装方法を見ていきましょう。

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

Android Studioを起動し、[File] → [New Project] を選択して新しいプロジェクトを作成します。必要な項目をすべて入力し、プロジェクトのセットアップを完了させてください。

ステップ2:activity_main.xmlの編集

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

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="4dp"
    tools:context=".MainActivity">
    <ListView
        android:id="@+id/listView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:descendantFocusability="beforeDescendants">
    </ListView>
</LinearLayout>

ここで重要なのが android:descendantFocusability="beforeDescendants" の指定です。この属性により、ListView自身が子要素よりも先にフォーカスを処理できるようになり、EditTextへのフォーカス移動がスムーズになります。

ステップ3:リスト項目用レイアウトの作成

新しいレイアウトリソースファイル(listitem.xml)を作成し、以下のコードを記述します。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <EditText
        android:id="@+id/ItemCaption"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="2dip"
        android:singleLine="true">
    </EditText>
</LinearLayout>

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

src/MainActivity.java に以下のコードを追加します。

import androidx.appcompat.app.AppCompatActivity;
import android.annotation.SuppressLint;
import android.app.LauncherActivity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.ListView;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {
    ListView listView;
    MyAdapter myAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        listView = findViewById(R.id.listView);
        listView.setItemsCanFocus(true);
        myAdapter = new MyAdapter();
        listView.setAdapter(myAdapter);
    }

    private class MyAdapter extends BaseAdapter {
        private LayoutInflater layoutInflater;
        ArrayList<LauncherActivity.ListItem> myItems = new ArrayList<>();

        MyAdapter() {
            layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            for (int i = 0; i < 7; i++) {
                LauncherActivity.ListItem listItem = new LauncherActivity.ListItem();
                listItem.className = "Caption" + i;
                myItems.add(listItem);
            }
            notifyDataSetChanged();
        }

        @Override
        public int getCount() {
            return myItems.size();
        }

        @Override
        public Object getItem(int position) {
            return position;
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @SuppressLint("InflateParams")
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder;
            if (convertView == null) {
                holder = new ViewHolder();
                convertView = layoutInflater.inflate(R.layout.listitem, null);
                holder.caption = convertView.findViewById(R.id.ItemCaption);
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }
            holder.caption.setText(myItems.get(position).className);
            holder.caption.setId(position);
            holder.caption.setOnFocusChangeListener(new View.OnFocusChangeListener() {
                public void onFocusChange(View v, boolean hasFocus) {
                    if (!hasFocus) {
                        final int position = v.getId();
                        final EditText Caption = (EditText) v;
                        myItems.get(position).className = Caption.getText().toString();
                    }
                }
            });
            return convertView;
        }
    }

    class ViewHolder {
        EditText caption;
    }
}

このコードのポイントは以下の通りです。

  • setItemsCanFocus(true):ListViewの項目がフォーカスを受け取れるように設定します。この設定がないと、EditTextをタップしてもフォーカスが当たりません。
  • ViewHolderパターン:convertViewを再利用してビューの参照を保持することで、スクロール時のパフォーマンスを向上させます。
  • OnFocusChangeListener:フォーカスが外れたタイミングでEditTextの入力内容をデータソースに書き戻し、編集結果を保持します。
  • setId(position):ビューのIDに行番号を持たせることで、どの項目が編集されたのかを特定できるようにしています。

ステップ5:AndroidManifest.xmlの編集

androidManifest.xml に以下のコードを追加します。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
    package="app.com.sample">
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity" android:windowSoftInputMode="adjustPan">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

android:windowSoftInputMode="adjustPan" を指定することで、ソフトキーボードが表示された際に画面全体が自動的に調整され、編集中のEditTextがキーボードに隠れないようになります。

アプリの実行

それでは、アプリケーションを実行してみましょう。ここでは、実際のAndroidスマートフォンをパソコンに接続しているものとします。

Android Studioからアプリを実行するには、プロジェクト内のアクティビティファイルを開き、ツールバーのRunアイコンをクリックします。実行デバイスとして自分のスマートフォンを選択してください。

アプリが起動すると、EditTextを含む7つのリスト項目が表示されます。各項目をタップするとフォーカスが当たり、テキストを自由に編集できます。別の項目へフォーカスが移動したタイミングで、それまでの入力内容がアダプター内のデータに保存される仕組みです。

  1. 【Android】EditTextにアルファベットのみ入力できるようにする方法

    はじめにこの記事では、AndroidアプリのEditText(テキスト入力欄)に対して、アルファベットのみを入力可能にする方法を解説します。InputFilterと正規表現を組み合わせることで、数字や記号などの入力をブロックし、英字だけを受け付ける入力フィールドを簡単に実装できます。手順1:新規プロジェクトの作成まず、Android Studioで新しいプロジェクトを作成します。メニューから「File」→「New Project」を選択し、必要な項目を入力してプロジェクトを作成してください。手順2:レイアウトファイルの編集次に、res/layout/activity_main.xmlに以下のコ

  2. 【Android】ExpandableListViewでマルチレベル(階層型)リストを作成する方法

    Androidアプリ開発では、カテゴリごとに項目を整理したマルチレベル(階層型)リストを実装したいケースが多くあります。本記事では、ExpandableListViewを使用して、親項目(グループ)をタップすると子項目が展開される2階層リストを作成する方法を、サンプルコードとともにステップごとに解説します。 ExpandableListViewとは? ExpandableListViewは、親項目(グループ)と子項目からなる2階層構造のリストを表示できるAndroid標準ウィジェットです。設定画面やFAQなど、階層的なデータをわかりやすく見せたい場面で活用できます。今回はスポーツ選手の一覧を例