[Android]ドロップダウンリストSpinnerクラスの使い方

投稿者:

ユーザーに決まった項目を選択させるUIとしてドロップダウンリストがある。
Androidでドロップダウンリストを使うときはSpinnerクラスを使用する。

SpinnerはListViewと同じく描画とUIを担当するSpinnerクラスとデータを管理するアダプタとセットで運用する。リストを閉じた状態と展開した状態それぞれに別のレイアウトを適用することもできる。

次の例ではテキスト1行だけのSpinnerを作成し、選択した項目をToastで表示している

レイアウトファイル【activity_main.xml】
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <TextView
    android:text="項目を選択 : "
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

    <Spinner
    android:id="@+id/spinner"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:spinnerMode="dropdown"/>
</LinearLayout>

JAVAファイル【MainActivity.java】
public class MainActivity extends AppCompatActivity {

    String[] dropdownItems = {
            "TOYOTA",
            "MAZDA",
            "HONDA",
            "NISSAN"
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item, dropdownItems);
        Spinner spinner = findViewById(R.id.spinner);
        spinner.setAdapter(adapter);
        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                String text = (String) parent.getAdapter().getItem(position);
                Toast.makeText(parent.getContext(), text, Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });
    }
}

項目が選択されたときのコールバックAdapterView.OnItemSelectedListenerはonItemSelectedとonNothingSelectedの二つのメソッドが必要で、前者は項目が選択されたとき、後者はバックボタンで戻ったりして選択されなかったときの処理を書いておく(例では非選択時はなにもしていない)。

実行結果はこんな感じ

 

ドロップダウンリストにカスタムレイアウトを使う

Spinnerにカスタムレイアウトを使うときはArrayAdapterクラスを継承した独自クラスを作成する。

public class MainActivity extends AppCompatActivity {

    CarMaker[] dropdownItems = {
            new CarMaker("TOYOTA", R.mipmap.ic_toyota),
            new CarMaker("MAZDA", R.mipmap.ic_mazda),
            new CarMaker("HONDA", R.mipmap.ic_honda),
            new CarMaker("NISSAN", R.mipmap.ic_nissan)
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        SpinnerAdapter adapter = new SpinnerAdapter(this, dropdownItems);
        Spinner spinner = findViewById(R.id.spinner);
        spinner.setAdapter(adapter);
        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                String text = ((CarMaker)parent.getAdapter().getItem(position)).getName();
                Toast.makeText(parent.getContext(), text, Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });
    }

    class CarMaker {
        private String name;
        private int iconResourceId;

        public CarMaker(String name, int iconResourceId) {
            this.name = name;
            this.iconResourceId = iconResourceId;
        }
        public void setName(String name) { this.name = name; }
        public void setIconResourceId(int iconResourceId) { this.iconResourceId = iconResourceId; }
        public String getName() { return name; }
        public int getIconResourceId() { return iconResourceId; }
    }


    class SpinnerAdapter extends ArrayAdapter<CarMaker>{
        //コンストラクタ
        public SpinnerAdapter(@NonNull Context context, @NonNull CarMaker[] objects) {
            super(context, 0, objects);
        }

        @NonNull
        @Override
        public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
            //getView()ではリストを展開していな状態のレイアウトを作成する
            //ここではテキスト1行だけのレイアウトを適用している

            if (convertView == null) {
                LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                convertView = inflater.inflate(android.R.layout.simple_spinner_item, parent, false);
            }
            TextView textView = (TextView) convertView.findViewById(android.R.id.text1);
            textView.setText(getItem(position).getName());

            return  convertView;
        }

        @Override
        public View getDropDownView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
            //getDropDownView()では展開したリストのレイアウトを作成する
            //ここではアイコンとテキストを並べたカスタムレイアウトを適用している

            if (convertView == null) {
                LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                convertView = inflater.inflate(R.layout.spinneritem_dropdown, parent, false);
            }

            CarMaker item = getItem(position);

            TextView textView = (TextView) convertView.findViewById(R.id.spinner_text1);
            textView.setText(item.getName());

            ImageView imageView = (ImageView)convertView.findViewById(R.id.spinner_icon);
            imageView.setImageResource(item.getIconResourceId());

            return convertView;
        }
    }
}

ListViewにカスタムレイアウトを適用するときはgetView()をオーバーライドしたが、SpinnerではgetView()のほかにもgetDropDownView()もオーバーライドする。

  • getView()
    選択中の項目の表示レイアウトを生成
  • getDropDownView()
    リストのレイアウトを生成

それぞれで別のレイアウトを適用すれば、リストと選択中アイテムとでデザインを変えることもできる。
上の例では通常時はテキスト1行だけだが、リストにはアイコンも表示される。

 

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください