Руководство Android Spinner
View more Tutorials:
В Android, Spinner это ViewGroup позволяющий пользователю выбрать значение из списка значений. В режиме по умолчанию, Android Spinner работает как Dropdown List (Выпадающий список) или Combox в других языках программирования.

Когда пользователь нажимает на Android Spinner, выпадает список, содержащий все значения, и пользователь может выбрать одно значение.
Android Spinner имеет 2 режима (mode) с абсолютно разными интерфейсами:
- android:spinnerMode="dropdown"
- android:spinnerMode="dialog"

android:spinnerMode="dropdown"
Когда пользователь кликает (click) на Spinner отображается Dropdown List (выпадающий список), чтобы пользователь смог выбрать одно значение. Это режим по умолчанию у Spinner.

android:spinnerMode="dropdown"
android:spinnerMode="dialog"
Когда пользователь кликает (click) на Spinner отображается Dialog содержащий список значений, чтобы пользователь выбрал одно значение.

android:spinnerMode="dialog"
OK, теперь мы начнем с простым примером, используя Spinner и ArrayAdapter. В данном примере, Spinner будет содержать список объектов Employee:


Adapter помогает вам сочетать Spinner-Item Layout Resource и данные, чтобы создать Spinner.

ArrayAdapter это готовый класс в библиотеке Android. он является простым Adapter, принимающий простой Spinner-Item Layout Resource, включая TextView, и может добавить CheckBox, ImageView,..
Например: Простой Spinner-Item Layout Resource с ID это android.R.layout.simple_spinner_item уже определенный в Android SDK и вы можете его использовать. Android Studio разрешает вам смотреть содержание данных файлов, нужно только держать клавишу CONTROL и кликнуть на него, как в изображении ниже:

На Android Studio создайте новый project:
- File > New > New Project > Empty Activity
- Name: SpinnerExample
- Package name: org.o7planning.spinnerexample
- Language: Java

activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginLeft="16dp" android:layout_marginTop="16dp" android:layout_marginEnd="16dp" android:layout_marginRight="16dp" android:orientation="horizontal" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="0" android:text="Select Employee:" /> <Space android:layout_width="10dp" android:layout_height="wrap_content" android:layout_weight="0" /> <Spinner android:id="@+id/spinner_employee" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" /> </LinearLayout> </androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.java
package org.o7planning.spinnerexample; import android.os.Bundle; import android.view.View; import android.widget.Adapter; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Spinner; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { private Spinner spinnerEmployee; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); this.spinnerEmployee = (Spinner) findViewById(R.id.spinner_employee); Employee[] employees = EmployeeDataUtils.getEmployees(); // (@resource) android.R.layout.simple_spinner_item: // The resource ID for a layout file containing a TextView to use when instantiating views. // (Layout for one ROW of Spinner) ArrayAdapter<Employee> adapter = new ArrayAdapter<Employee>(this, android.R.layout.simple_spinner_item, employees); // Layout for All ROWs of Spinner. (Optional for ArrayAdapter). adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); this.spinnerEmployee.setAdapter(adapter); // When user select a List-Item. this.spinnerEmployee.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { onItemSelectedHandler(parent, view, position, id); } @Override public void onNothingSelected(AdapterView<?> parent) { } }); } private void onItemSelectedHandler(AdapterView<?> adapterView, View view, int position, long id) { Adapter adapter = adapterView.getAdapter(); Employee employee = (Employee) adapter.getItem(position); Toast.makeText(getApplicationContext(), "Selected Employee: " + employee.getFullName() ,Toast.LENGTH_SHORT).show(); } }
Employee.java
package org.o7planning.spinnerexample; public class Employee { private String firstName; private String lastName; private String position; private int salary; public Employee(String firstName, String lastName, String position, int salary) { this.firstName = firstName; this.lastName = lastName; this.position = position; this.salary = salary; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getPosition() { return position; } public void setPosition(String position) { this.position = position; } public int getSalary() { return salary; } public void setSalary(int salary) { this.salary = salary; } public String getFullName() { return this.firstName + " " + this.lastName; } // Text show in Spinner @Override public String toString() { return this.getFullName() + " - (" + this.position+")"; } }
EmployeeDataUtils.java
package org.o7planning.spinnerexample; public class EmployeeDataUtils { public static Employee[] getEmployees() { Employee emp1 = new Employee("James", "Smith", "Receptionist", 1000); Employee emp2 = new Employee("Michael", "Garcia", "CEO", 50000); Employee emp3 = new Employee("Robert", "Johnson", "Professional staff", 2000); return new Employee[] {emp1, emp2, emp3}; } }
Кастомизирование Adapter помогает вам получить Spinner посложнее и красивее. Ниже является изображение иллюстрирующее Spinner который содержить объекты Language, и так же является нашим следующим примером, который мы выполним:

В данном примере мы создадим "Spinner Item Layout Resource File", чтобы определить Layout строки (row) у Spinner. CustomAdapter скомбинирукт данные и "Spinner Item Layout Resource", чтобы создать Spinner, который сможет увидеть пользователь.

OK. на Android Studio создайте новый project:
- File > New > New Project > Empty Activity
- Name: CustomSpinnerAdapterExample
- Package name: org.o7planning.customspinneradapterexample
- Language: Java
Во-первых, нам нужно создать Layout Resource File, чтобы определить Layout для Spinner Item:
На Android Studio, выберите файл "layout", и выберите:
- File > New > Layout Resource File

- File Name: spinner_item_layout_resource.xml
- Root element: LinearLayout

Дизайн интерфейса для spinner_item_layout_resource:

spinner_item_layout_resource.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" android:padding="10dp"> <TextView android:id="@+id/textView_item_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="Language Name" /> <TextView android:id="@+id/textView_item_percent" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="0" android:text="Percent" /> </LinearLayout>
Главный интерфейс приложения:

activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <TextView android:id="@+id/textView" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginLeft="16dp" android:layout_marginTop="32dp" android:layout_marginEnd="16dp" android:layout_marginRight="16dp" android:text="Select Language:" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="1.0" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <Spinner android:id="@+id/spinner_language" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginLeft="16dp" android:layout_marginTop="16dp" android:spinnerMode="dialog" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/textView" /> </androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.java
package org.o7planning.customspinneradapterexample; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.widget.Spinner; import java.util.List; public class MainActivity extends AppCompatActivity { private Spinner spinner; private List<Language> languages; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Data: this.languages = LanguageDataUtils.getLanguages(); this.spinner = (Spinner) this.findViewById(R.id.spinner_language); // Adapter" CustomAdapter adapter = new CustomAdapter(MainActivity.this, R.layout.spinner_item_layout_resource, R.id.textView_item_name, R.id.textView_item_percent, this.languages); this.spinner.setAdapter(adapter); } }
CustomAdapter.java
package org.o7planning.customspinneradapterexample; import android.app.Activity; import android.view.View; import android.view.ViewGroup; import android.view.LayoutInflater; import android.widget.BaseAdapter; import android.widget.TextView; import java.util.List; public class CustomAdapter extends BaseAdapter { private LayoutInflater flater; private List<Language> list; private int listItemLayoutResource; private int textViewItemNameId; private int textViewItemPercentId; // Arguments example: // @listItemLayoutResource: R.layout.spinner_item_layout_resource // (File: layout/spinner_item_layout_resource.xmll) // @textViewItemNameId: R.id.textView_item_name // (A TextVew in file layout/spinner_item_layout_resource.xmlxml) // @textViewItemPercentId: R.id.textView_item_percent // (A TextVew in file layout/spinner_item_layout_resource.xmll) public CustomAdapter(Activity context, int listItemLayoutResource, int textViewItemNameId, int textViewItemPercentId, List<Language> list) { this.listItemLayoutResource = listItemLayoutResource; this.textViewItemNameId = textViewItemNameId; this.textViewItemPercentId = textViewItemPercentId; this.list = list; this.flater = context.getLayoutInflater(); } @Override public int getCount() { if(this.list == null) { return 0; } return this.list.size(); } @Override public Object getItem(int position) { return this.list.get(position); } @Override public long getItemId(int position) { Language language = (Language) this.getItem(position); return language.getId(); // return position; (Return position if you need). } @Override public View getView(int position, View convertView, ViewGroup parent) { Language language = (Language) getItem(position); // Example: @listItemLayoutResource: R.layout.spinner_item_layout_resource // (File: layout/spinner_item_layout_resourcerce.xml) View rowView = this.flater.inflate(this.listItemLayoutResource, null,true); // Example: @textViewItemNameId: R.id.textView_item_name // (A TextView in file layout/spinner_item_layout_resourcerce.xml) TextView textViewItemName = (TextView) rowView.findViewById(this.textViewItemNameId); textViewItemName.setText(language.getName()); // Example: @textViewItemPercentId: R.id.textView_item_percent // (A TextView in file layout/spinner_item_layout_resource.xmlxml) TextView textViewItemPercent = (TextView) rowView.findViewById(textViewItemPercentId); textViewItemPercent.setText(language.getPercent() + "%"); return rowView; } }
Language.java
package org.o7planning.customspinneradapterexample; public class Language { private long id; private String name; private float percent; public Language(long id, String name, float percent) { this.id = id; this.name = name; this.percent = percent; } public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public float getPercent() { return percent; } public void setPercent(float percent) { this.percent = percent; } }
LanguageDataUtils.java
package org.o7planning.customspinneradapterexample; import java.util.ArrayList; import java.util.List; public class LanguageDataUtils { public static List<Language> getLanguages( ) { Language javascript = new Language(1,"Javascript", 67.7f); Language htmlCss = new Language(2,"HTML/CSS", 63.1f); Language sql = new Language(3,"SQL", 54.7f); Language python = new Language(4,"Python", 44.1f); Language java = new Language(5, "Java", 40.2f); List<Language> list = new ArrayList<Language>(); list.add(javascript); list.add(htmlCss); list.add(sql); list.add(python); list.add(java); return list; } }