Android の Spinner は、一般的にはコンボボックスと言われるものと同様で、何も指定しなければ以下のような動作をします。
Spinner には、spinnerMode というプロパティがあり、デフォルトでは MODE_DROPDOWN として動作しています。( XML で定義せずに、インスタンスを作成する場合は、コンストラクタで指定できます )
この部分を MODE_DIALOG に変更すると、以下のように動作します
リスト部分の実装について
リスト部分は、一般的なリストビューと同じです。ArrayAdapter を使用します。単純に一つの TextView を持つ、Android で定義済みの simple_spinner_dropdown_item を使って実装しています。( simple_spinner_dropdown_item である必要はありません )
package lightbox.may.combobox;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
// ******************************
// 文字列配列 Spinner
// ******************************
private ArrayAdapter<String> adapter;
private Spinner spinner;
private String[] list_data = {"大阪","東京","愛知","岡山"};
private String[] list_value = {"27","13","23","33"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 配列を格納して Android のリストを表示する ArrayAdapter クラス
// レイアウトは Android で定義されたもの。
// TextView を継承したクラスであれば自前のレイアウトで OK
adapter = new ArrayAdapter(
MainActivity.this,
android.R.layout.simple_spinner_dropdown_item);
// Spinner のインスタンスを取得
spinner = (Spinner) MainActivity.this.findViewById(R.id.spinner);
// ArrayAdapter に配列を格納
adapter.addAll(list_data);
// Spinner に ArrayAdapter をセット
spinner.setAdapter(adapter);
// ボタンの インスタンスを取得
Button button = (Button) MainActivity.this.findViewById(R.id.button);
// アルファベットの小文字を反映できるようにする
button.setAllCaps(false);
// ボタンのイベントの定義
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// ******************************************
// Spinner より選択されているテキストを取得
// ******************************************
// simple_spinner_dropdown_item に定義されている id から
String text = ((TextView)(MainActivity.this.findViewById(android.R.id.text1))).getText().toString();
Log.i("lightbox", text);
// sppiner から
text = (String) spinner.getSelectedItem();
Log.i("lightbox", text);
// ポジション番号から、用意しておいた配列を使用して取り出す
int pos = spinner.getSelectedItemPosition();
Log.i("lightbox", list_data[pos]);
}
});
}
}
Spinner とは関係ありませんが、setAllCaps でボタンの文字が全て大文字にならないようにしています。
Spinner の情報の取り出し
ここでは、Spinner に表示されるテキストを取り出しています。しかし、実際は Spinner の選択 されたインデックスより、テキストの元となるコードを list_value より取り出すのが正解です。ですが、これは最も簡単なサンプルとして、ArrayAdapter に 文字列の配列を引き渡しているからそうなるのであって、本来は専用クラスを作成し、その配列を最初に渡しておいて、その中の値を直接取り出すのが汎用的になります。
Spinner 用のクラスを作成して利用する
package lightbox.may.combobox;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
public class MainActivity extends AppCompatActivity {
// ******************************
// MyData 配列 Spinner
// ******************************
private ArrayAdapter<MyData> adapter;
// セットする情報の配列
private MyData[] my_data = {
new MyData("大阪","27"),
new MyData("東京","13"),
new MyData("愛知","23"),
new MyData("岡山","33")} ;
// Spinner のインスタンス
private Spinner spinner;
// 情報格納用のクラス
private class MyData {
// 表示される文字列用
private String myString = null;
// 内部コード
private String myValue = null;
// コンストラクタ
public MyData(String myString,String myValue) {
this.myString = myString;
this.myValue = myValue;
}
// 値取得用
String getValue() {
return myValue;
}
// ArrayAdapter の仕様に合わせて toString を 上書きしておく
@Override
public String toString() {
return myString;
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 配列を格納して Android のリストを表示する ArrayAdapter クラス
// レイアウトは Android で定義されたもの。
// TextView を継承したクラスであれば自前のレイアウトで OK
adapter = new ArrayAdapter(
MainActivity.this,
android.R.layout.simple_spinner_dropdown_item);
// Spinner のインスタンスを取得
spinner = (Spinner) MainActivity.this.findViewById(R.id.spinner);
// ArrayAdapter に MyData 配列を格納
adapter.addAll(my_data);
// Spinner に ArrayAdapter をセット
spinner.setAdapter(adapter);
// ボタンの インスタンスを取得
Button button = (Button) MainActivity.this.findViewById(R.id.button);
// アルファベットの小文字を反映できるようにする
button.setAllCaps(false);
// ボタンのイベントの定義
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// ******************************************
// Spinner より選択されている情報を取得
// ******************************************
// sppiner から MyData を取得
MyData md = (MyData) spinner.getSelectedItem();
// 内部コードの取得
Log.i("lightbox", md.getValue());
// テキストの取得
Log.i("lightbox", md.toString());
}
});
}
}
データをセットするのに、addAll を使用しているのは、インターネット経由で JSON を使用して読み込む事が通常想定されるので、一括となっています。
リストの行の表示のカスタマイズ
これらのサンプルでは、画面定義は simple_spinner_dropdown_item を使用していますが、単純に TextView のみの画面定義をして利用可能です。
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="40dp"
android:padding="10dp">
</TextView>
完全にカスタマイズするには
Spinner の見え方は、閉じた一つの View と リストで表示されるビューと二つあります。また、二つ以上のコントロールのある View を作った場合は ArrayAdapter を継承したクラスを作成して利用する必要があります。それらの機能を汎用的に実装したのが以下の SpinnerArrayAdapter です。
package lightbox.may.combobox;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
/**
* Created by lightbox on 2016/05/21.
*/
public class SpinnerArrayAdapter<T> extends ArrayAdapter<T> {
public interface OnGetViewListener {
abstract public View onGetViewListener(int position, View convertView, ViewGroup parent);
}
private OnGetViewListener listener = null;
private OnGetViewListener listener_drop_down = null;
public SpinnerArrayAdapter(Context context, int resource, OnGetViewListener listener, OnGetViewListener listener_drop_down) {
super(context, resource);
this.listener = listener;
this.listener_drop_down = listener_drop_down;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if ( listener != null ) {
return listener.onGetViewListener(position, convertView, parent);
}
return super.getView(position, convertView, parent);
}
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
if ( listener != null ) {
return listener_drop_down.onGetViewListener(position, convertView, parent);
}
return super.getDropDownView(position, convertView, parent);
}
}
画面定義 / my_spinner_custom
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/textView"
android:textSize="40dp"
android:padding="10dp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/textView2"
android:textSize="20dp"
android:padding="5dp"/>
</LinearLayout>
使用方法
package lightbox.may.combobox;
import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
// ******************************
// MyData 配列 Spinner
// ******************************
private SpinnerArrayAdapter <MyData> adapter;
// セットする情報の配列
private MyData[] my_data = {
new MyData("大阪","27"),
new MyData("東京","13"),
new MyData("愛知","23"),
new MyData("岡山","33")} ;
// Spinner のインスタンス
private Spinner spinner;
// 情報格納用のクラス
private class MyData {
// 表示される文字列用
private String myString = null;
// 内部コード
private String myValue = null;
// コンストラクタ
public MyData(String myString,String myValue) {
this.myString = myString;
this.myValue = myValue;
}
// 値取得用
String getValue() {
return myValue;
}
// ArrayAdapter の仕様に合わせて toString を 上書きしておく
@Override
public String toString() {
return myString;
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// my_spinner_custom を使用したカスタマイズ
adapter = new SpinnerArrayAdapter<MyData>(
MainActivity.this,
R.layout.my_spinner_custom,
// リストでは無い表示部分
new SpinnerArrayAdapter.OnGetViewListener() {
@Override
public View onGetViewListener(int position, View convertView, ViewGroup parent) {
View rowView = convertView;
if (rowView == null) {
// 現在の View の取得
LayoutInflater inflater = (LayoutInflater) MainActivity.this.getSystemService
(Context.LAYOUT_INFLATER_SERVICE);
rowView = inflater.inflate(R.layout.my_spinner_custom, null);
}
// Adapter にセットされているこのポジションの MyData を取得
MyData md = adapter.getItem(position);
// my_spinner_custom 内の TextView にデータをセット
TextView tv1 = (TextView) rowView.findViewById(R.id.textView);
tv1.setText(md.toString());
TextView tv2 = (TextView) rowView.findViewById(R.id.textView2);
tv2.setText(md.getValue());
return rowView;
}
},
// リストの表示部分
new SpinnerArrayAdapter.OnGetViewListener() {
@Override
public View onGetViewListener(int position, View convertView, ViewGroup parent) {
View rowView = convertView;
if (rowView == null) {
// 現在の View の取得
LayoutInflater inflater = (LayoutInflater) MainActivity.this.getSystemService
(Context.LAYOUT_INFLATER_SERVICE);
rowView = inflater.inflate(R.layout.my_spinner_custom, null);
}
// Adapter にセットされているこのポジションの MyData を取得
MyData md = adapter.getItem(position);
// my_spinner_custom 内の TextView にデータをセット
TextView tv1 = (TextView) rowView.findViewById(R.id.textView);
tv1.setText(md.toString());
TextView tv2 = (TextView) rowView.findViewById(R.id.textView2);
tv2.setText(md.getValue());
return rowView;
}
});
// Spinner のインスタンスを取得
spinner = (Spinner) MainActivity.this.findViewById(R.id.spinner);
// ArrayAdapter に MyData 配列を格納
adapter.addAll(my_data);
// Spinner に ArrayAdapter をセット
spinner.setAdapter(adapter);
// ボタンの インスタンスを取得
Button button = (Button) MainActivity.this.findViewById(R.id.button);
// アルファベットの小文字を反映できるようにする
button.setAllCaps(false);
// ボタンのイベントの定義
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// ******************************************
// Spinner より選択されている情報を取得
// ******************************************
// sppiner から MyData を取得
MyData md = (MyData) spinner.getSelectedItem();
// 内部コードの取得
Log.i("lightbox", md.getValue());
// テキストの取得
Log.i("lightbox", md.toString());
}
});
}
}
関連するソースコード
ArrayAdapter
simple_spinner_dropdown_item.xml