如何在 recyclerview 中执行多选?

How to perform multiselection in recyclerview?

我正在制作一个具有个性化功能的应用程序,用户可以在其中 select 他的偏好,并且基于该应用程序将显示数据。单击项目时,它应该是 selected(使项目边框突出显示)并且重新单击它应该是 unselected 并且 [=15= 中应该有 multiselection ] 是我的应用程序个性化屏幕的屏幕截图

这与您要找的有点相似,请尝试使用 DragSelectRecyclerView 它会适合您,并为边框高亮创建一个选择器。

<com.afollestad.dragselectrecyclerview.DragSelectRecyclerView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="vertical" />

你也可以这样使用

http://www.grokkingandroid.com/statelistdrawables-for-recyclerview-selection/

http://bignerdranch.github.io/recyclerview-multiselect/

  • Object 上使用与 recyclerview 一起工作的字段 isSelected (boolean)
  • Adapterclass的onBindViewHolder方法处:使用setOnClickListenerImageView显示头像。当用户点击时,为对象更改 isSelected 并为 imageView 设置背景 isSelectedtruefalse.

使用它来 select recyclerview 中的多行并使用 actionmode 删除。

SelectableAdapter.class

public abstract class SelectableAdapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> {
@SuppressWarnings("unused")
private static final String TAG = SelectableAdapter.class.getSimpleName();

private SparseBooleanArray selectedItems;

public SelectableAdapter() {
    selectedItems = new SparseBooleanArray();
}

/**
 * Indicates if the item at position position is selected
 * @param position Position of the item to check
 * @return true if the item is selected, false otherwise
 */
public boolean isSelected(int position) {
    return getSelectedItems().contains(position);
}

/**
 * Toggle the selection status of the item at a given position
 * @param position Position of the item to toggle the selection status for
 */
public void toggleSelection(int position) {
    if (selectedItems.get(position, false)) {
        selectedItems.delete(position);
    } else {
        selectedItems.put(position, true);
    }
    notifyItemChanged(position);
}

/**
 * Clear the selection status for all items
 */
public void clearSelection() {
    List<Integer> selection = getSelectedItems();
    selectedItems.clear();
    for (Integer i : selection) {
        notifyItemChanged(i);
    }
}

/**
 * Count the selected items
 * @return Selected items count
 */
public int getSelectedItemCount() {
    return selectedItems.size();
}

/**
 * Indicates the list of selected items
 * @return List of selected items ids
 */
public List<Integer> getSelectedItems() {
    List<Integer> items = new ArrayList<>(selectedItems.size());
    for (int i = 0; i < selectedItems.size(); ++i) {
        items.add(selectedItems.keyAt(i));
    }
    return items;
}
}

Item.class

public class Item {

private String title;

public Item(String title){
    this.title=title;
}

public String getTitle() {
    return title;
}

public void setTitle(String title) {
    this.title = title;
}
}

Adapter.class

public class Adapter extends SelectableAdapter<Adapter.ViewHolder> {
@SuppressWarnings("unused")
private static final String TAG = Adapter.class.getSimpleName();
private static final int ITEM_COUNT = 50;
private List<Item> items;

private ViewHolder.ClickListener clickListener;

public Adapter(ViewHolder.ClickListener clickListener) {
    super();

    this.clickListener = clickListener;

    items = new ArrayList<>();
    for (int i = 0; i < ITEM_COUNT; ++i) {
        items.add(new Item("Item " + i));
    }
}

public void removeItem(int position) {
    items.remove(position);
    notifyItemRemoved(position);
}

public void removeItems(List<Integer> positions) {
    // Reverse-sort the list
    Collections.sort(positions, new Comparator<Integer>() {
        @Override
        public int compare(Integer lhs, Integer rhs) {
            return rhs - lhs;
        }
    });

    // Split the list in ranges
    while (!positions.isEmpty()) {
        if (positions.size() == 1) {
            removeItem(positions.get(0));
            positions.remove(0);
        } else {
            int count = 1;
            while (positions.size() > count && positions.get(count).equals(positions.get(count - 1) - 1)) {
                ++count;
            }

            if (count == 1) {
                removeItem(positions.get(0));
            } else {
                removeRange(positions.get(count - 1), count);
            }

            for (int i = 0; i < count; ++i) {
                positions.remove(0);
            }
        }
    }
}

private void removeRange(int positionStart, int itemCount) {
    for (int i = 0; i < itemCount; ++i) {
        items.remove(positionStart);
    }
    notifyItemRangeRemoved(positionStart, itemCount);
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_card, parent, false);
    return new ViewHolder(v, clickListener);
}

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    final Item item = items.get(position);

    holder.title.setText(item.getTitle());

    // Highlight the item if it's selected
    holder.selectedOverlay.setVisibility(isSelected(position) ? View.VISIBLE : View.INVISIBLE);
}

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


public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener,
        View.OnLongClickListener {
    @SuppressWarnings("unused")
    private static final String TAG = ViewHolder.class.getSimpleName();

    TextView title;
    TextView subtitle;
    View selectedOverlay;

    private ClickListener listener;

    public ViewHolder(View itemView, ClickListener listener) {
        super(itemView);

        title = (TextView) itemView.findViewById(R.id.textView);
        selectedOverlay = (View)itemView.findViewById(R.id.selectedOverlay);

        this.listener = listener;

        itemView.setOnClickListener(this);
        itemView.setOnLongClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if (listener != null) {
            listener.onItemClicked(getLayoutPosition());
        }
    }

    @Override
    public boolean onLongClick(View v) {
        if (listener != null) {
            return listener.onItemLongClicked(getLayoutPosition());
        }

        return false;
    }

    public interface ClickListener {
         void onItemClicked(int position);
         boolean onItemLongClicked(int position);
    }
}

}

MainActivity.class

public class MainActivity extends AppCompatActivity implements Adapter.ViewHolder.ClickListener {

@SuppressWarnings("unused")
private static final String TAG = MainActivity.class.getSimpleName();

private Adapter adapter;
private ActionModeCallback actionModeCallback = new ActionModeCallback();
private ActionMode actionMode;

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

    adapter = new Adapter(this);

    RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
    recyclerView.setAdapter(adapter);
    recyclerView.setItemAnimator(new DefaultItemAnimator());
    recyclerView.setLayoutManager(new GridLayoutManager(this,3));
}

@Override
public void onItemClicked(int position) {
    if (actionMode != null) {
        toggleSelection(position);
    } else {
        //adapter.removeItem(position);
    }
}

@Override
public boolean onItemLongClicked(int position) {
    if (actionMode == null) {
        actionMode = startSupportActionMode(actionModeCallback);
    }

    toggleSelection(position);

    return true;
}

/**
 * Toggle the selection state of an item.
 *
 * If the item was the last one in the selection and is unselected, the selection is stopped.
 * Note that the selection must already be started (actionMode must not be null).
 *
 * @param position Position of the item to toggle the selection state
 */
private void toggleSelection(int position) {
    adapter.toggleSelection(position);
    int count = adapter.getSelectedItemCount();

    if (count == 0) {
        actionMode.finish();
    } else {
        actionMode.setTitle(String.valueOf(count));
        actionMode.invalidate();
    }
}

private class ActionModeCallback implements ActionMode.Callback {
    @SuppressWarnings("unused")
    private final String TAG = ActionModeCallback.class.getSimpleName();

    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        mode.getMenuInflater().inflate (R.menu.toolbar_menu, menu);
        return true;
    }

    @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        return false;
    }

    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        switch (item.getItemId()) {
            case R.id.action_delete:
                adapter.removeItems(adapter.getSelectedItems());
                mode.finish();
                return true;

            default:
                return false;
        }
    }

    @Override
    public void onDestroyActionMode(ActionMode mode) {
        adapter.clearSelection();
        actionMode = null;
    }
}
}

item_card.xml

<?xml version="1.0" encoding="utf-8"?>

<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:foreground="?android:attr/selectableItemBackground"
app:cardUseCompatPadding="true">

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="8dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
>

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textAppearance="?android:attr/textAppearanceMedium"
    android:id="@+id/textView"
    android:padding="7dp"
    android:text="sample"/>

 </LinearLayout>

 <View
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:visibility="invisible"
    android:id="@+id/selectedOverlay"
    android:background="@color/transparent"/>

 </android.support.v7.widget.CardView>

添加到 sonnv1368 的回答中:

试试这个:

在您的模型中创建一个布尔值 class 对象以跟踪图像视图的选择:说 boolean isSelected;

@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
    Object item = objectList.get(position);
    holder.imageView.setSelected(item.getSelected());

}

public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    ImageView imageView;
    public ViewHolder(View view) {
      //initialization code here
      imageView.setOnClickListener(this);
    }

    @Override
    public void onClick( View view ) {
      Object object = objectList.get(getAdapterPosition());
      object.isSelected() ? object.setSelected(false) : object.setSelected(true);
      notifyItemChanged(getAdapterPosition());
    }
}