5. Удаление пункта списка

Теперь необходимо добавить обработку нажатия на кнопку "Х" в пункте списка.

Добавим интерфейс для слушателя нажатия на кнопку удаления пункта списка. В метод передается позиция пункта списка для того, чтобы определить - какой элемент коллекции с контактами нужно удалить.

ContactsAdapter.java
public class ContactsAdapter extends RecyclerView.Adapter<ContactsAdapter.ContactHolder> {

    public interface DeleteItemListener {
        void onDeleteItem(int position);
    }
    
    ...
}

Добавим поле для объекта DeleteItemListener, добавим еще один параметр конструктора

ContactsAdapter.java
public class ContactsAdapter extends RecyclerView.Adapter<ContactsAdapter.ContactHolder> {

    public interface DeleteItemListener {
        void onDeleteItem(int position);
    }

    private final LayoutInflater inflater;
    private final List<Contact> list;
    private DeleteItemListener listener;

    private static final int EMPTY_LIST_TYPE = 0;
    private static final int NON_EMPTY_LIST_TYPE = 1;


    public ContactsAdapter(Context context, List<Contact> users, DeleteItemListener listener) {
        this.inflater = LayoutInflater.from(context);
        this.list = users;
        this.listener = listener;
    }

    ...
    
}

Вернемся в MainActivity.java. Добавим реализацию интерфейса, напишем логику метода onClick(), а также исправим код для создания объекта адаптера.

MainActivity.java
public class MainActivity extends AppCompatActivity implements ContactsAdapter.DeleteItemListener {

    private List<Contact> list = new ArrayList<>();
    private ContactsAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        ...

        mRecyclerView = findViewById(R.id.list);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        adapter = new ContactsAdapter(getApplicationContext(), list, this);
        mRecyclerView.setAdapter(adapter);
    }

    @Override
    public void onDeleteItem(int position) {
        list.remove(position);
        adapter.notifyDataSetChanged();
    }
}

Изменим код для ContactHolder. Добавим ссылки на кнопку удаления, добавим поле для объекта DeleteItemListener. При создании ContactHolder будем получать ссылку на объета DeleteItemListener. Далее, создаем слушатель нажатия на кнопку "X", в котором мы будем вызывать метод onDeleteItem() у объекта MainActivity.

ContactsAdapter.java
public class ContactsAdapter extends RecyclerView.Adapter<ContactsAdapter.ContactHolder> {

    ...

    static class ContactHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        ImageView image;
        TextView name;
        TextView email;
        TextView phone;

        ImageButton deleteButton;
        DeleteItemListener listener;

        public ContactHolder(@NonNull View itemView, DeleteItemListener listener) {
            super(itemView);

            image = itemView.findViewById(R.id.contact_image);
            name = itemView.findViewById(R.id.name);
            email = itemView.findViewById(R.id.email);
            phone = itemView.findViewById(R.id.phone);

            deleteButton = itemView.findViewById(R.id.clearButton);
            this.listener = listener;

            if ((int) itemView.getTag() == NON_EMPTY_LIST_TYPE) {
                deleteButton.setOnClickListener(this);
            }
        }

        @Override
        public void onClick(View v) {
            listener.onDeleteItem(getAdapterPosition());
        }
    }
}

Изменим код метода onCreateViewHolder(), при создании объекта ContactHolder, передадим ссылку на объект слушателя. В нашем случае - ссылку на объект MainActyivity, который реализует слушатель удаления пункта списка.

ContactsAdapter.java
public class ContactsAdapter extends RecyclerView.Adapter<ContactsAdapter.ContactHolder> {

    @NonNull
    @Override
    public ContactHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view;

        if (viewType == EMPTY_LIST_TYPE) {
            view = inflater.inflate(R.layout.list_no_items, parent, false);
            view.setTag(EMPTY_LIST_TYPE);
        } else {
            view = inflater.inflate(R.layout.list_contact, parent, false);
            view.setTag(NON_EMPTY_LIST_TYPE);
        }

        return new ContactHolder(view, listener);
    }

}

Ниже приведены итоговые листинги классов.

public class MainActivity extends AppCompatActivity implements ContactsAdapter.DeleteItemListener {

    private static final int ADD_CONTACT_REQUEST_CODE = 5556;
    private RecyclerView mRecyclerView;
    private FloatingActionButton mAddContactButton;

    private List<Contact> list = new ArrayList<>();
    private ContactsAdapter adapter;

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

        mRecyclerView = findViewById(R.id.list);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        adapter = new ContactsAdapter(getApplicationContext(), list, this);
        mRecyclerView.setAdapter(adapter);

        mAddContactButton = findViewById(R.id.fab);
        mAddContactButton.setOnClickListener(v -> {
            Intent i = new Intent(this, AddContactActivity.class);
            startActivityForResult(i, ADD_CONTACT_REQUEST_CODE);
        });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == ADD_CONTACT_REQUEST_CODE && resultCode == RESULT_OK && data != null) {
            String name = data.getStringExtra(Intent.EXTRA_USER);
            String email = data.getStringExtra(Intent.EXTRA_EMAIL);
            String phone = data.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
            Uri uri = Uri.parse(data.getStringExtra(Intent.EXTRA_ORIGINATING_URI));

            list.add(new Contact(name, email, phone, uri));
            adapter.notifyDataSetChanged();
        }
    }

    private void setWindow() {
        // Метод устанавливает StatusBar в цвет фона
        Window window = this.getWindow();
        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
        window.setStatusBarColor(getColor(R.color.activity_background));

        View decor = getWindow().getDecorView();
        decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
    }

    private static final int REQUEST_EXTERNAL_STORAGE = 1;
    private static final String[] PERMISSIONS_STORAGE = {
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE
    };

    public void verifyStoragePermissions() {
        // Проверяем наличие разрешения на запись во внешнее хранилище
        int permission = ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);

        if (permission != PackageManager.PERMISSION_GRANTED) {
            // Запрашиваем разрешение у пользователя
            ActivityCompat.requestPermissions(
                    this,
                    PERMISSIONS_STORAGE,
                    REQUEST_EXTERNAL_STORAGE
            );
        }
    }

    @Override
    protected void onStart() {
        super.onStart();

        verifyStoragePermissions();
    }

    @Override
    public void onDeleteItem(int position) {
        list.remove(position);
        adapter.notifyDataSetChanged();
    }
}

Last updated