Додавання та видалення в ArrayAdapter і ListView

Після прив'язки ListView до джерела даних через адаптер, ми можемо працювати з даними — додавати, видаляти, змінювати тільки через адаптер. ListView слугує лише для відображення даних.

Для керування даними ми можемо використовувати методи адаптера або безпосередньо джерело даних. Наприклад, клас ArrayAdapter надає наступні методи для керування даними:

  • void add(T object): додає елемент object в кінець масиву
  • void addAll(T... items): додає всі елементи items в кінець масиву
  • void addAll(Collection<? extends T> collection): додає колекцію елементів collection в кінець масиву
  • void clear(): видаляє всі елементи зі списку
  • void insert(T object, int index): додає елемент object в масив по індексу index
  • void remove(T object): видаляє елемент object з масиву

Однак, після застосування вищезазначених методів, зміни стосуватимуться лише масиву, який є джерелом даних. Щоб синхронізувати зміни з елементом ListView, потрібно викликати у адаптера метод notifyDataSetChanged().

Приклад

Припустимо, у файлі 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">
        
    <EditText
        android:id="@+id/userName"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintHorizontal_weight="4"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/add"
        app:layout_constraintTop_toTopOf="parent" />
        
    <Button
        android:id="@+id/add"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintHorizontal_weight="1"
        android:text="+"
        android:onClick="add"
        app:layout_constraintRight_toLeftOf="@+id/remove"
        app:layout_constraintLeft_toRightOf="@+id/userName"
        app:layout_constraintTop_toTopOf="parent"/>
        
    <Button
        android:id="@+id/remove"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintHorizontal_weight="1"
        android:text="-"
        android:onClick="remove"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toRightOf="@+id/add"
        app:layout_constraintRight_toRightOf="parent" />
        
    <ListView
        android:id="@+id/usersList"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:choiceMode="multipleChoice"
        app:layout_constraintTop_toBottomOf="@+id/userName"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent">
    </ListView>
</androidx.constraintlayout.widget.ConstraintLayout>

Для відображення списку використовується ListView з можливістю множинного вибору елементів. Для додавання та видалення визначено дві кнопки. Для введення нового об'єкта в список призначено поле EditText.

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.EditText;
import android.widget.ListView;
import java.util.ArrayList;
import java.util.Collections;

public class MainActivity extends AppCompatActivity {

    ArrayList<String> users = new ArrayList<String>();
    ArrayList<String> selectedUsers = new ArrayList<String>();
    ArrayAdapter<String> adapter;
    ListView usersList;

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

        // додаємо початкові елементи
        Collections.addAll(users, "Tom", "Bob", "Sam", "Alice");

        // отримуємо елемент ListView
        usersList = findViewById(R.id.usersList);

        // створюємо адаптер
        adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_multiple_choice, users);

        // встановлюємо для списку адаптер
        usersList.setAdapter(adapter);

        // обробка встановлення та зняття позначок в списку
        usersList.setOnItemClickListener(new AdapterView.OnItemClickListener(){
            @Override
            public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
                // отримуємо натиснутий елемент
                String user = adapter.getItem(position);
                if(usersList.isItemChecked(position))
                    selectedUsers.add(user);
                else
                    selectedUsers.remove(user);
            }
        });
    }

    public void add(View view) {
        EditText userName = findViewById(R.id.userName);
        String user = userName.getText().toString();
        if(!user.isEmpty()){
            adapter.add(user);
            userName.setText("");
            adapter.notifyDataSetChanged();
        }
    }

    public void remove(View view) {
        // отримуємо та видаляємо виділені елементи
        for(int i = 0; i < selectedUsers.size(); i++){
            adapter.remove(selectedUsers.get(i));
        }

        // знімаємо всі раніше встановлені позначки
        usersList.clearChoices();

        // очищаємо масив вибраних елементів
        selectedUsers.clear();

        adapter.notifyDataSetChanged();
    }
}

З додаванням все відносно просто: отримуємо введену строку та додаємо її в список за допомогою методу adapter.add(). Щоб оновити ListView після додавання, викликаємо метод adapter.notifyDataSetChanged().

Для видалення створюється додатковий список selectedUsers, який містить виділені елементи. Для отримання виділених елементів та додавання їх у список використовується слухач AdapterView.OnItemClickListener. Метод onItemClick() цього слухача викликається при встановленні або знятті позначки з елемента, тобто при будь-якому натисканні на елемент.

При натисканні на кнопку видалення, ми проходимо по списку виділених елементів і викликаємо для кожного з них метод adapter.remove().