В прошлых темах было рассмотрено, как можно загружать данные в ListView, связывать его с источником данных. Но кроме простого вывода списка элементов ListView позволяет выбирать элемент и обрабатывать его выбор. Рассмотрим, как это сделать. Определим следующую разметку в файле 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" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/selection" android:layout_width="0dp" android:layout_height="wrap_content" android:textSize="22sp" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> <ListView android:id="@+id/countriesList" android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintTop_toBottomOf="@+id/selection" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent"> </ListView> </androidx.constraintlayout.widget.ConstraintLayout>
Теперь свяжем список ListView с источником данных и закрепим за ним слушатель нажатия на элемент списка:
package com.example.listapp; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.TextView; public class MainActivity extends AppCompatActivity { String[] countries = { "Бразилия", "Аргентина", "Колумбия", "Чили", "Уругвай"}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // получаем элемент TextView TextView selection = findViewById(R.id.selection); // получаем элемент ListView ListView countriesList = findViewById(R.id.countriesList); // создаем адаптер ArrayAdapter<String> adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, countries); // устанавливаем для списка адаптер countriesList.setAdapter(adapter); // добавляем для списка слушатель countriesList.setOnItemClickListener(new AdapterView.OnItemClickListener(){ @Override public void onItemClick(AdapterView<?> parent, View v, int position, long id) { // по позиции получаем выбранный элемент String selectedItem = countries[position]; // установка текста элемента TextView selection.setText(selectedItem); } }); } }
Итак, метод setAdapter
связывает элемент ListView с определенным адаптером. Далее для обработки выбора элемента списка
устанавливается слушатель OnItemClickListener. Этот слушатель имеет один метод onItemClick, через параметры которого
мы можем получить выделенный элемент и сопутствующие данные. Так, он принимает следующие параметры:
parent : нажатый элемент AdapterView (в роли которого в данном случае выступает наш элемент ListView)
view : нажатый виджет внутри AdapterView
position : индекс нажатого виждета внутри AdapterView
id : идентификатор строки нажатого элемента
Используя эти параметры, мы можем разными способами получить выделенный элемент.
Например, в данном случае получая индекс нажатого виджета, который соответствует индексу элемента в массиве строк, мы можем устанавить соответствующий элемент в массиве строк и таким образом получить его текст:
countriesList.setOnItemClickListener(new AdapterView.OnItemClickListener(){ @Override public void onItemClick(AdapterView<?> parent, View v, int position, long id) { // по позиции получаем выбранный элемент String selectedItem = countries[position]; // установка текста элемента TextView selection.setText(selectedItem); } });
Также мы можем получить выделенный элемент из AdapterView, который передается в качестве первого параметра - AdapterView<?> parent
.
Так, в данном случае мы знаем, что каждый элемент в AdapterView фактически представляет строку или объект String, поэтому в данном случае можно
получить выделенный элемент так:
countriesList.setOnItemClickListener(new AdapterView.OnItemClickListener(){ @Override public void onItemClick(AdapterView<?> parent, View v, int position, long id) { // получаем выбранный элемент String selectedItem = (String)parent.getItemAtPosition(position); // установка текста элемента TextView selection.setText(selectedItem); } });
Метод getItemAtPosition
возвращает выделенный элемент по индексу. Это может актуально, если мы используем в качестве источника данных не массив строк, созданный в коде Java,
а, например, ресурс <string-array>
, заданный в файле xml.
В-третьих, мы можем использовать выделенный элемент, который передается в качестве второго параметра - View v
. Так, в данном случае
адаптер использует в качестве типа разметки ресурс - android.R.layout.simple_list_item_1, а это значит, что выделенный элемент
представляет элемент TextView, в котором выводится данный текст. Поэтому в данном случае мы также могли бы получить выделенный
элемент так:
countriesList.setOnItemClickListener(new AdapterView.OnItemClickListener(){ @Override public void onItemClick(AdapterView<?> parent, View v, int position, long id) { // получаем выбранный элемент TextView textView = (TextView) v; String selectedItem = (String)textView.getText(); // установка текста элемента TextView selection.setText(selectedItem); // или так // selection.setText(textView.getText()); } });
Иногда требуется выбрать не один элемент, как по умолчанию, а несколько. Для этого, во-первых, в разметке списка надо установить
атрибут android:choiceMode="multipleChoice"
:
<?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" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/selection" android:layout_width="0dp" android:layout_height="wrap_content" android:textSize="22sp" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> <ListView android:id="@+id/countriesList" android:choiceMode="multipleChoice" android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintTop_toBottomOf="@+id/selection" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent"> </ListView> </androidx.constraintlayout.widget.ConstraintLayout>
Теперь определим в коде MainActivity обработку выбора элементов списка:
package com.example.listapp; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.util.SparseBooleanArray; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.TextView; public class MainActivity extends AppCompatActivity { String[] countries = { "Бразилия", "Аргентина", "Колумбия", "Чили", "Уругвай"}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // получаем элемент TextView TextView selection = findViewById(R.id.selection); // получаем элемент ListView ListView countriesList = findViewById(R.id.countriesList); // создаем адаптер // создаем адаптер ArrayAdapter<String> adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_multiple_choice, countries); // устанавливаем для списка адаптер countriesList.setAdapter(adapter); // добавляем для списка слушатель countriesList.setOnItemClickListener(new AdapterView.OnItemClickListener(){ @Override public void onItemClick(AdapterView<?> parent, View v, int position, long id) { SparseBooleanArray selected=countriesList.getCheckedItemPositions(); String selectedItems=""; for(int i=0;i < countries.length;i++) { if(selected.get(i)) selectedItems+=countries[i]+","; } // установка текста элемента TextView selection.setText("Выбрано: " + selectedItems); } }); } }
Ресурс android.R.layout.simple_list_item_multiple_choice
представляет стандартную разметку, предоставляемую фреймворком,
для создания списка с множественным выбором.
А при выборе элементов мы получаем все выбранные позиции в объект SparseBooleanArray, затем пробегаемся по всему массиву, и если позиция элемента в массиве есть в SparseBooleanArray, то есть она отмечена, то добавляем отмеченный элемент в строку.