Рубрики
Без рубрики

Добавление OnClickListener в RecyclerView в Android

Вступление Эта серия будет посвящена основам разработки Android…. Помечено как java, android, новички, тристан.

Android (Серия из 20 частей)

  • Эта серия будет посвящена основам разработки Android. Присоединяйтесь ко мне, и давайте попробуем создать и понять несколько интересных вещей. Все ресурсы, которые я использовал для создания этого поста, можно найти в примечании к билету или ЗДЕСЬ .

  • Я также хочу упомянуть еще одну последнюю вещь, которую я хочу услышать от вас, читатель. Прежде чем читать это, вы должны иметь четкое представление об Android Fragments и RecyclerView. Я упоминаю об этом, потому что я не буду обсуждать транзакции фрагментов или то, как реализовать RecyclerView. Проверять ЗДЕСЬ для моего учебника по фрагментам и ЗДЕСЬ для моего учебника по RecyclerView. Если вы не понимаете этих основ, то вам может быть трудно следовать этому руководству.

Абстрактный взгляд на то, что мы делаем

  • В основном то, что мы делаем, – это определение метода, передающего метод нашему экземпляру пользовательского адаптера, затем методу createViewHolder() и, наконец, экземпляру ViewHolder. Этот метод будет вызываться при нажатии на каждый отдельный объект ViewHolder. Мы, конечно, обеспечим гораздо более техническую реализацию, но, вообще говоря, это то, что мы делаем.

Методы фрагментации, которые мы используем.

  • Теперь, прежде чем мы приступим к фактической реализации метода, я хочу поговорить о методах фрагментов, которые мы собираемся использовать в нашей реализации. Примеры кода нашего фрагмента приведены ниже:
public class ExampleFragment extends Fragment implements CustomAdapter.OnNoteListener{
    private List data;

    public ExampleFragment(){
        super(R.layout.example_fragment);
    }

    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        //This is where we initialize the data. Normally this would be from a remote server
        dataCall();

    }

    @Override
    public void onViewCreated(View view,Bundle savedInstanceState){
        // this is where we are going to set the RecyclerView
        RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.example_view);
       recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
       recyclerView.setAdapter(new CustomAdapter(this.data,this));

    }

    public void dataCall(){
        ArrayList data = new ArrayList<>();
        for(int i = 0; i< 49; i ++){
            data.add("NAME # " +i);
        }
        this.data = data;

    }

    @Override
    public void onNoteClick(int position) {
        Toast toast = Toast.makeText(getActivity(),"CLICKED",Toast.LENGTH_SHORT);
        toast.show();

    }
}
  • Это может показаться большим количеством кода, но пока сосредоточьтесь только на методах onCreate(), onViewCreated() и конструкторе класса.
  • Кроме того, если вы не знакомы с жизненным циклом фрагмента, я настоятельно рекомендую вам прочитать об этом ЗДЕСЬ . С этого момента я буду считать, что у вас есть четкое представление о фрагментах, жизненный цикл фрагмента и просмотр вторичной переработки

onCreate(пакет,сохраненное состояние установки)

  • Когда фрагмент добавляется в Менеджер фрагментов (менеджер фрагментов отвечает за организацию и вызов методов во фрагментах) он входит в СОЗДАННОЕ состояние своего жизненного цикла. Этот переход в состояние запускает метод onCreate(). Метод получает Пакет , который содержит любое ранее сохраненное состояние, но изначально значение равно нулю. Этот метод также вызывается перед onCreateView() (которого у нас нет, подробнее об этом позже) и вызывается перед onViewCreated()
  • Теперь я не уверен на 100%, почему, но в примере документации ЗДЕСЬ нам говорят инициализировать наборы данных в этом методе. Это означает, что это метод, к которому мы обычно обращаемся к серверу, или в нашем случае настраиваем список массивов.

onCreateView(LayoutInflater, группа просмотра, пакет)

  • Этот метод вызывается, когда представление будет увеличено (создано). Документация рекомендует использовать этот метод только для расширения представления, а затем переместить логику в onViewCreated().
  • Вопрос, который вы, вероятно, задаете себе: “Если этот метод используется для увеличения представления, то почему у нас его нет?”. У нас действительно есть этот метод, он просто вызывается автоматически для нас. Доказательство этого находится в конструкторе:
public ExampleFragment(){
        super(R.layout.example_fragment);
    }

  • Когда мы выполняем супер-вызов super(R.layout.example_fragment) , мы вызываем альтернативный конструктор в классе Fragment, который примет представление, которое мы ему предоставили, и автоматически вызовет onCreateView() для нас.

onViewCreated(Просмотр, пакет)

  @Override
    public void onViewCreated(View view,Bundle savedInstanceState){
        // this is where we are going to set the RecyclerView
        RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.example_view);
       recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
       recyclerView.setAdapter(new CustomAdapter(this.data,this));

    }
  • Этот метод вызывается сразу после возврата onCreateView() и получает от него расширенное представление. Мы можем использовать это раздутое представление для настройки нашего RecyclerView.

  • Теперь мы можем перейти к созданию метода, который будет передан нашему адаптеру и, в конечном итоге, объекту ViewHolder.

Создание нашего метода.

  • Сначала я собираюсь вставить код, а затем рассказать о части, относящейся к созданию нашего метода.
public class CustomAdapter extends RecyclerView.Adapter {
    private List data;
    private OnNoteListener onNoteListener;

    public CustomAdapter(List data,OnNoteListener onNoteListener){
        this.data = data;
        this.onNoteListener = onNoteListener;
    }

    public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
        private final TextView textView;
        OnNoteListener onNoteListener;

        public ViewHolder(View view,OnNoteListener onNoteListener){
            super(view);
            this.textView = (TextView) view.findViewById(R.id.text_view_id);
            view.setOnClickListener(this);
            this.onNoteListener = onNoteListener;
        }

        @Override
        public void onClick(View v) {
            this.onNoteListener.onNoteClick(getAdapterPosition());
        }
    }


    @Override
    public CustomAdapter.ViewHolder onCreateViewHolder( ViewGroup parent, int viewType) {
        //inflate the indiv item
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.indiv_viewholder_item,parent,false);

        return new ViewHolder(view, this.onNoteListener);
    }

    @Override
    public void onBindViewHolder( CustomAdapter.ViewHolder holder, int position) {
        holder.textView.setText(this.data.get(position));

    }

    @Override
    public int getItemCount() {
        return this.data.size();
    }

    public interface OnNoteListener{
        void onNoteClick(int position);
    }
}

  • Это весь наш пользовательский адаптер, но нас волнует только интерфейс |/На Заметку Слушателю :
public interface OnNoteListener{
        void onNoteClick(int position);
    }
  • Увидев этот интерфейс, у вас, вероятно, возникнет 2 вопроса: 1) почему он вложен в пользовательский класс адаптера и 2) почему мы используем интерфейс?

1) Почему он вложен в класс CustomAdapter?

  • Как правило, в Java мы помещаем что-то внутри класса, потому что оно и класс имеют тесную связь. Это относится к нам, потому что интерфейс действительно бесполезен вне контекста нашего пользовательского класса адаптера. Это подводит нас к нашему следующему вопросу

2) почему мы используем интерфейс?

  • Прежде чем мы сможем ответить на этот вопрос, мы сначала должны определить, что такое интерфейс. Интерфейс позволяет классу быть более формальным в отношении поведения, предоставляемого классом. Интерфейсы формируют контракт между классом и внешним миром. Этот контракт выполняется компилятором во время сборки. По сути, когда мы используем интерфейс в классе, мы формально объявляем, какие методы он сможет использовать, и каждый класс, реализующий интерфейс, также будет иметь эти методы. Итак, теперь, когда мы знаем, что такое интерфейс, мы должны понять, почему мы хотели бы использовать интерфейс. Как правило, это была бы одна из трех причин.

1) Несвязанные классы должны иметь схожие реализации.

2) Вы хотите указать поведение определенного типа данных, но вас не волнует, кто реализует это поведение.

3) Вы хотите воспользоваться преимуществами множественного наследования типа.

  • Для нашего случая это 2 , мы хотим указать поведение но нас не волнует, кто реализует это поведение. Кроме того, я хочу отметить, что интерфейсы также могут использоваться в качестве справочных типов данных. То же, что и в классе.

Реализация интерфейса

  • Теперь, если мы оглянемся на наш класс фрагментов, вы должны заметить, что мы реализуем интерфейс:
public class ExampleFragment extends Fragment implements CustomAdapter.OnNoteListener
  • Когда мы реализуем интерфейс, мы должны использовать Пользовательский адаптер.onNoteListener потому что наш интерфейс вложен в наш класс customadapter. Как только у нас будет реализация нашего интерфейса, мы должны реализовать все методы интерфейсов, для нас это щелчок по заметке.
public void onNoteClick(int position) {
        Toast toast = Toast.makeText(getActivity(),"CLICKED",Toast.LENGTH_SHORT);
        toast.show();

    }
  • Этот метод и есть тот метод, о котором мы говорили. Это метод, который мы будем передавать до тех пор, пока он не будет передан объекту ViewHolder. Этот метод вызывается, когда мы нажимаем на отдельные объекты ViewHolder. Мы передаем ему значение int, чтобы показать, что каждый метод может вызывать его со своими собственными значениями. Однако мы используем его только для создания и отображения тоста при нажатии. Toast.makeText() используется для создания тоста, он принимает 3 параметра: контекст, текст, который будет отображаться, и продолжительность просмотра тоста. toast.show() должен быть вызван для отображения тоста.

  • Теперь помните, что наша цель – просто передать метод нашему объекту Viewholder, чтобы он вызывался при каждом клике. Для этого мы должны передать доступ к нашему методу объекту пользовательского адаптера, а затем методу onCreateViewHolder() и, наконец, самому объекту ViewHolder.

Передача доступа к нашему пользовательскому адаптеру

recyclerView.setAdapter(new CustomAdapter(this.data,this));
  • Это просто мы устанавливаем наш адаптер, вот так.данные – это то, что мы используем переменную экземпляра, называемую data, в качестве аргумента для пользовательского адаптера. Итак, что же такое это ? Ну, каждый раз, когда “это” используется внутри метода экземпляра или конструктора, оно ссылается на текущий объект. Поэтому при использовании этого мы ссылаемся на публичный класс Пример фрагмента расширяет фрагмент, реализующий пользовательский адаптер. На Заметку Слушателю .
  • Краткое напоминание о том, что мы также можем использовать интерфейс классов в качестве его типа при обращении к нему. Я упоминаю об этом, потому что внутри вашего конструктора customadapter мы используем тип OnNoteListener и установка глобальной переменной экземпляра внутри или в нашем пользовательском классе адаптера, см. Ниже:
private OnNoteListener onNoteListener;

    public CustomAdapter(List data,OnNoteListener onNoteListener){
        this.data = data;
        this.onNoteListener = onNoteListener;
    }
  • Однако я хочу отметить, что только потому, что мы ссылаемся на него как на тип onNoteListener, технически он все еще является нашим классом ExampleFragment.

Передача прослушивателя заметок onCreateViewHolder()

  • Теперь внутри метода onCreateViewHolder() мы вызываем конструктор объекта ViewHolder.
public CustomAdapter.ViewHolder onCreateViewHolder( ViewGroup parent, int viewType) {
        //inflate the indiv item
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.indiv_viewholder_item,parent,false);

        return new ViewHolder(view, this.onNoteListener);
    }
  • Это все еще обычный метод onCreateViewHolder(). Однако обратите внимание, что мы передаем глобальную переменную экземпляра this.на прослушивателе заметок новому объекту ViewHolder(). Экземпляр ViewHolder теперь получит расширенное представление, а также доступ к нашему методу щелчка по заметке. Наш объект ViewHolder теперь имеет доступ к методу, который мы определили ранее:
public void onNoteClick(int position) {
        Toast toast = Toast.makeText(getActivity(),"CLICKED",Toast.LENGTH_SHORT);
        toast.show();

    }

Подключение объекта ViewHolder.

  • Для того, чтобы мы могли определить OnClickListener для нашего объекта ViewHolder, нам нужно реализовать Представление. Включенный список:
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
        private final TextView textView;
        OnNoteListener onNoteListener;

        public ViewHolder(View view,OnNoteListener onNoteListener){
            super(view);
            this.textView = (TextView) view.findViewById(R.id.text_view_id);
            view.setOnClickListener(this);
            this.onNoteListener = onNoteListener;
        }

        @Override
        public void onClick(View v) {
            this.onNoteListener.onNoteClick(getAdapterPosition());
        }
    }

  • Обратите внимание на конструктор и на то, что у нас есть экземпляр прослушивателя заметок, и мы присваиваем его глобальной ссылочной переменной внутри класса ViewHolder: this.onNoteListener; . Это позволит нам ссылаться на него позже.

  • Наиболее важной частью этого является view.setOnClickListener(this) , без этого метода ваши объекты ViewHolder не будут доступны для просмотра. это относится к фактическому объекту ViewHolder. По сути, мы говорим, что при нажатии на отдельный вид мы хотим, чтобы вызывался метод onClick .

public void onClick(View v) {
            this.onNoteListener.onNoteClick(getAdapterPosition());
        }
  • Приведенный выше код – это последняя часть головоломки. onClick() будет вызываться всякий раз, когда вызывается объект ViewHolder, и с его помощью мы вызываем наш собственный метод, который мы определили |/this.onNoteListener.onnoteclick(getAdapterPosition()) с текущим положением в адаптере.

  • На этом делается вывод о том, как сделать ваш RecyclerView кликабельным.

  • Спасибо, что нашли время в свой рабочий день, чтобы прочитать этот мой пост в блоге. Если у вас есть какие-либо вопросы или проблемы, пожалуйста, прокомментируйте ниже или свяжитесь со мной по адресу Твиттер .

Android (Серия из 20 частей)

Оригинал: “https://dev.to/theplebdev/adding-onclicklistener-to-recyclerview-in-android-3amb”