Как создать Arraylist объектов из переключения OnClickListeners внутри элементов RecyclerView Adapter - PullRequest
0 голосов
/ 12 апреля 2019

Я создаю мультимедийное приложение для Android и пытаюсь добавить в него функцию «Плейлист», пользователь сможет создать собственный плейлист и изменить его.

Я использую RecyclerView, чтобы показать пользователю список песен, из которых он может выбирать.Проблема в том, что я не понимаю, как передать Arraylist выбранных песен из адаптера в фрагмент.Я пытался использовать шаблон Observer, но не знаю, как использовать эту информацию.

Это мой фрагмент для создания списка воспроизведения:

public class CreatePlaylistFragment extends Fragment implements PlaylistAdapterInterface {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_create_playlist, container, false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        ArrayList<ProgramsData> dataArrayList = ProgramsReceiver.getPrograms();
        ArrayList<ProgramsData> sortedList = new ArrayList<>(dataArrayList);

        adapter = new CreatePlaylistAdapter(dataArrayList, view.getContext(), this);
        adapter.adapterInterface = this;


        ivCreatePlaylist.setOnClickListener(v -> {
            Toast.makeText(v.getContext(), "Creating Playlist!", Toast.LENGTH_SHORT).show();

            new PlaylistsJsonWriter(playlistArrayList,getContext()).execute();
        });
    }

    @Override
    public void OnItemClicked(ArrayList<ProgramsData> programs) {
        programsToCreate = programs;
        String s = etListName.getText().toString();
        playlistArrayList.add(new Playlist(s, programsToCreate));

    }
}

Это адаптер Recyclerс ViewHolder в качестве внутреннего класса:


public class CreatePlaylistAdapter extends RecyclerView.Adapter<CreatePlaylistViewHolder> {

    List<ProgramsData> programsDataList;
    Context context;
    public PlaylistAdapterInterface adapterInterface = null;

    public CreatePlaylistAdapter(List<ProgramsData> programsDataList, Context context , PlaylistAdapterInterface adapterInterface) {
        this.programsDataList = programsDataList;
        this.context = context;
        this.adapterInterface = adapterInterface;

    }
    @NonNull
    @Override
    public CreatePlaylistViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        LayoutInflater inflater = LayoutInflater.from(context);
        View view = inflater.inflate(R.layout.chose_program_to_playlist_item, viewGroup, false);
        return new CreatePlaylistViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull CreatePlaylistViewHolder holder, int i) {
        ProgramsData programsData = programsDataList.get(i);

        holder.tvProgramName.setText(programsData.getProgramName());
        if (programsData.getStudentName() != null)
            holder.tvStudentName.setText(programsData.getStudentName());
        else holder.tvLine.setText(""); //if there is no student the line won't be printed

        holder.ivProfilePic.setImageResource(programsData.getProfilePic());
        holder.programsData = programsData;
//        holder.mAdapterInterface = adapterInterface;
        adapterInterface.OnItemClicked(holder.programs);

    }

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

class CreatePlaylistViewHolder extends RecyclerView.ViewHolder {

    TextView tvProgramName;
    TextView tvStudentName;
    TextView tvLine;
    CircleImageView ivProfilePic;
    ToggleButton tbCheck;
    ProgramsData programsData;
    ArrayList<ProgramsData> programs;
    PlaylistAdapterInterface mAdapterInterface;


    public CreatePlaylistViewHolder(@NonNull View itemView) {
        super(itemView);
        tvProgramName = itemView.findViewById(R.id.tvProgramName);
        tvStudentName = itemView.findViewById(R.id.tvStudentName);
        ivProfilePic = itemView.findViewById(R.id.ivProfilePic);
        tvLine = itemView.findViewById(R.id.tvLine);
        tbCheck = itemView.findViewById(R.id.tbCheck);


        programs= new ArrayList<>();

        tbCheck.setOnClickListener(v -> {
            if (tbCheck.isChecked()) {
                tbCheck.setBackgroundResource(R.drawable.ic_radio_button_checked);
                programs.add(programsData);
            } else if (!tbCheck.isChecked()) {
                tbCheck.setBackgroundResource(R.drawable.ic_check);
                programs.remove(programsData);
            }
        });

    }


}

И это интерфейс для шаблона наблюдателя:

public interface PlaylistAdapterInterface {
    void OnItemClicked(ArrayList<ProgramsData> programs);
}

Я знаю, что это много кода, но я просто не понимаю, какпередать данные с адаптера обратно во фрагмент ...

Ответы [ 2 ]

0 голосов
/ 12 апреля 2019

Вы можете использовать метод обратного вызова. Вести список выбранных элементов в списке массивов и отправлять обратно во фрагмент, когда нажата кнопка «Готово» или любая другая кнопка, которую вы поместили для завершения действия. Выполните следующие действия

-Создать интерфейс с параметром списка.

-Фрагмент должен реализовывать этот интерфейс.

-После того, как вы инициализируете адаптер Recyclerview, передайте этот интерфейсный объект.

-После того, как сделано, вызывается переопределенный метод вызова этого интерфейса и отправляется список выбранных песен в качестве аргумента.

0 голосов
/ 12 апреля 2019

Я не совсем понимаю, что вы пытаетесь сделать. Код содержит несколько ошибок, которые я попытаюсь объяснить.

Явная ошибка, которую вы сделали, остается в onBindViewholder, где вы вызываете слушателя при создании каждого элемента, а не после нажатия на него. Вы просто добавляете onClickListener в viewHolder.getItemView () или в конкретном представлении держателя, а затем выполняете операцию, которую вам нужно выполнить после щелчка по элементу. Если вы установите слушателя внутри onBindViewHolder, у вас также есть метод с именем holder.getAdapterPosition (), который вы можете использовать, чтобы понять, на какой элемент вы нажимаете.

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

Если вам нужно только извлечь выбранные песни после того, как пользователь подтвердит свой список воспроизведения, вы можете просто добавить публичный метод на свой адаптер

public List<ProgramsData> getSelectedSongs()

, что вы можете вызвать из своего фрагмента, когда пользователь нажмет кнопку подтверждения.

Чтобы иметь список всех выбранных песен, вы можете иметь другой список

ArrayList<ProgramsData> selectedPrograms;

что вы собираетесь заполнить после клика. Содержимое слушателя внутри onBindViewHolder может быть

ProgramsData currentProgram = programs.get(holder.getAdapterPosition());
if(selectedPrograms.contains(currentProgram){
    selectedPrograms.remove(currentProgram);
}else{
    selectedPrograms.add(currentProgram);
}
notifyItemChanged(holder.getAdapterPosition); //You can use this to update the view of the selected item

Затем внутри метода onBindViewHolderMethod вы можете проверить, являются ли элементы, которые вы связываете, частью selectedList и соответствующим образом обновить представления.

...