【问题标题】:Recyclerview multiple selection selected order count similar to instagram image selectionRecyclerview多选选单数类似于instagram图片选单
【发布时间】:2020-10-07 08:02:19
【问题描述】:

问题

我正在尝试为我的应用开发图库选择器页面。用户可以从列出的项目(从用户手机)中选择多个图像/视频。用户一次最多可以选择 10 个项目,并且应显示每个项目的选择顺序。选择顺序也应根据选择和取消选择进行调整。

例如:如果用户取消选择选择 1,则选择 1 之后的所有其他选择应减一。

我做了什么

我已经使用 diffUtils 制作了 recyclerview 适配器,并使用 recyclerview-selection 库处理了多项选择。但我找不到显示选择顺序并根据用户操作进行调整的方法。

多么努力的目标

代码

画廊适配器

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;
    }
}

在 Fragment 中设置适配器

  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) {

            }
        });
    }

我只是在这里添加适配器代码。否则问题会变得太大。如果没有提供必要的信息,我将分享完整的代码。

【问题讨论】:

    标签: java android android-recyclerview multipleselection


    【解决方案1】:

    您可以将 selectionTracker.selection.size() 传递给 ViewHolder 类中的绑定函数,因此您将始终拥有最新计数

        @Override
        public void onBindViewHolder(@NonNull final GalleryViewAdapter.ViewHolder holder, final int position) {
    
           int count = selectionTracker.selection.size()
            holder.bind(item,count,selectionTracker.isSelected((long) position));
        }
    

    【讨论】:

    • 这可行,但如果适配器调用 notifyDataSetChanged(),则所有项目都显示相同的内容(即 selection.size())。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-24
    • 1970-01-01
    • 1970-01-01
    • 2019-06-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多