Recyclerview множественный выбор выбранный счетчик заказа похож на выбор изображения Instagram - PullRequest
0 голосов
/ 17 июня 2020

Проблема

Я пытаюсь разработать страницу выбора галереи для своего приложения. Пользователь может выбрать несколько изображений / видео из перечисленных элементов (с телефона пользователя). Пользователь может выбрать до 10 элементов одновременно, и порядок выбора должен отображаться для каждого элемента. Порядок выбора также должен корректироваться в зависимости от выбора и отмены выбора.

например: если пользователь отменяет выбор 1, тогда все остальные выделения после выбора 1 должны уменьшиться на единицу.

Что я сделал

Я уже сделал адаптер recyclerview с помощью diffUtils и обработал множественный выбор с помощью библиотеки recyclerview-selection. Но я не могу найти способ показать порядок выбора и настроить его в зависимости от действий пользователя.

Чего я пытаюсь достичь

instagram selection ui

Код

GalleryAdapter

public class GalleryViewAdapter extends ListAdapter<GalleryThumbnailsModel,GalleryViewAdapter.ViewHolder> {

    private Context context;
    private ArrayList<GalleryThumbnailsModel> selectedItemModels;

    private Interaction interaction;
    private SelectionTracker<Long> selectionTracker;

    private static int POST_TYPE_IMAGE = 1;
    private static int POST_TYPE_VIDEO = 3;

    public GalleryViewAdapter(GalleryViewDiffCallback diffCallback,Context context,ArrayList<GalleryThumbnailsModel> selectedItemModels) {
        super(diffCallback);
        this.context = context;
        this.selectedItemModels = selectedItemModels;

        setHasStableIds(true);
    }
    @NonNull
    @Override
    public GalleryViewAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(context).inflate(R.layout.item_gallery_view,parent,false);
        return new GalleryViewAdapter.ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull final GalleryViewAdapter.ViewHolder holder, final int position) {

        GalleryThumbnailsModel item = getItem(position);
        holder.bind(item,selectionTracker.isSelected((long) position));
    }

    @Override
    public long getItemId(int position) {
        return (long) position;
    }

    public void setSelectionTracker(SelectionTracker<Long> selectionTracker) {
        this.selectionTracker = selectionTracker;
    }

    public class ViewHolder extends RecyclerView.ViewHolder {

        ImageView postImage;
        ImageView postTypeVideo;
        ProgressBar progressBar;
        TextView postOrderCount;

        FrameLayout selectedIcon;

        public ViewHolder(View itemView) {
            super(itemView);

            postImage = itemView.findViewById(R.id.post_gallery_image);
            postTypeVideo = itemView.findViewById(R.id.user_post_video);
            progressBar = itemView.findViewById(R.id.progress_loader);
            selectedIcon =itemView.findViewById(R.id.gallery_selected_item);
            postOrderCount = itemView.findViewById(R.id.selected_post_order);
        }

        public void bind(GalleryThumbnailsModel item, boolean selected) {

            new GlideImageLoader(context,postImage,progressBar).load(item.getThumbnail(),null);

            if(selected){
                selectedIcon.setVisibility(View.VISIBLE);
                interaction.onItemSelected(getAdapterPosition(),item);
            }else {
                selectedIcon.setVisibility(View.INVISIBLE);
                interaction.onItemDeselected(getAdapterPosition(),item);
            }

            if(item.getMediaType() == POST_TYPE_VIDEO){
                postTypeVideo.setVisibility(View.VISIBLE);
            }else {
                postTypeVideo.setVisibility(View.INVISIBLE);
            }
        }

        public ItemDetailsLookup.ItemDetails<Long> getItemDetails(){
            return new ItemDetailsLookup.ItemDetails<Long>() {
                @Override
                public int getPosition() {
                    return getAdapterPosition();
                }

                @Nullable
                @Override
                public Long getSelectionKey() {
                    return getItemId();
                }

                @Override
                public boolean inSelectionHotspot(@NonNull MotionEvent e) {
                    return true;
                }
            };
        }
    }

    public static class GalleryViewDiffCallback extends DiffUtil.ItemCallback<GalleryThumbnailsModel>{

        @Override
        public boolean areItemsTheSame(@NonNull GalleryThumbnailsModel oldItem, @NonNull GalleryThumbnailsModel newItem) {
            return oldItem.getUriPath().equals(newItem.getUriPath());
        }

        @Override
        public boolean areContentsTheSame(@NonNull GalleryThumbnailsModel oldItem, @NonNull GalleryThumbnailsModel newItem) {
            return oldItem.equals(newItem);
        }
    }

    public interface Interaction{
        void onItemSelected(int position,GalleryThumbnailsModel item);
        void onItemDeselected(int position,GalleryThumbnailsModel item);
    }

    public void setInteraction(Interaction interaction) {
        this.interaction = interaction;
    }
}

Настройка адаптера во фрагменте

  private void setAdapter() {

        galleryViewAdapter = new GalleryViewAdapter(new GalleryViewAdapter.GalleryViewDiffCallback(),context,selectedItemsModels);
        gridLayoutManager = new GridLayoutManager(context,3,RecyclerView.VERTICAL,false);
        galleryViewAdapter.submitList(galleryThumbnailsModels);
        galleryViewRecycler.setLayoutManager(gridLayoutManager);
        galleryViewRecycler.setHasFixedSize(true);
        galleryViewRecycler.setAdapter(galleryViewAdapter);

        selectionTracker = new SelectionTracker.Builder<Long>(
                "selection",
                galleryViewRecycler,
                new StableIdKeyProvider(galleryViewRecycler),
                new RecyclerSelectionLookup(galleryViewRecycler),
                StorageStrategy.createLongStorage()
        ).withSelectionPredicate(new SelectionTracker.SelectionPredicate<Long>() {
            @Override
            public boolean canSetStateForKey(@NonNull Long key, boolean nextState) {
                // 10 - max selection size
                return !nextState || selectionTracker.getSelection().size() < 10;
            }

            @Override
            public boolean canSetStateAtPosition(int position, boolean nextState) {
                return false;
            }

            @Override
            public boolean canSelectMultiple() {
                return true;
            }
        })
                .build();

        selectionTracker.addObserver(new SelectionTracker.SelectionObserver<Long>() {
            @Override
            public void onSelectionChanged() {
                super.onSelectionChanged();
                int selectedItemCount = selectionTracker.getSelection().size();
                if(selectedItemCount == 0){
                    addMediaLayout.setVisibility(View.INVISIBLE);
                }else if(selectedItemCount > 0 && selectedItemCount < 11){
                    selectedCountTextView.setText(String.valueOf(selectedItemCount));
                    addMediaLayout.setVisibility(View.VISIBLE);
                }
            }
        });

        galleryViewAdapter.setSelectionTracker(selectionTracker);


        galleryViewAdapter.setInteraction(new GalleryViewAdapter.Interaction() {
            @Override
            public void onItemSelected(int position,GalleryThumbnailsModel item) {
                item.setSelectedOrder(selectedItemsModels.size()+1);
                selectedItemsModels.add(item);
            }

            @Override
            public void onItemDeselected(int position,GalleryThumbnailsModel item) {

            }
        });
    }

Я только добавляю код адаптера здесь. В противном случае вопрос станет слишком большим. Я поделюсь полным кодом, если он не предоставит необходимую информацию.

...