Google 相冊風格的RecyclerView多選效果: drag-select-recyclerview

Gradle依賴
build.gradle 文件:
repositories { // ... maven { url "https://jitpack.io" } } dependencies { // ... compile('com.afollestad:drag-select-recyclerview:0.1.0@aar') { transitive = true } }
介紹
本庫主要的兩個類是DragSelectRecyclerView和DragSelectRecyclerViewAdapter。兩個一起工作為你提供需要的功能。
DragSelectRecyclerView
DragSelectRecyclerView取代你通常在布局中使用的RecyclerView。它攔截觸摸事件判斷選擇模式是否處于激活狀態,然后自動向你的adapter報告。
<com.afollestad.dragselectrecyclerview.DragSelectRecyclerView android:id="@+id/list" android:layout_width="match_parent" android:layout_height="match_parent" android:scrollbars="vertical" />
設置基本上和普通RecyclerView一樣。你必須為他設置一個LayoutManager與RecyclerView.Adapter:
DragSelectRecyclerView list = (DragSelectRecyclerView) findViewById(R.id.list); list.setLayoutManager(new GridLayoutManager(this, 3)); list.setAdapter(adapter);
這里最主要的區別就是 setAdapter()里面放入的東西,它不能是普通的RecyclerView.Adapter,必須是DragSelectRecyclerViewAdapter的子類。下面將會討論。
DragSelectRecyclerViewAdapter
DragSelectRecyclerViewAdapter是一個DragSelectRecyclerView可以與之交互的RecyclerView.Adapter 的子類。它跟蹤被選中的索引-讓你可以改變它們,清除它們,監聽它們的變化以及檢查某個索引是否被選中。
最基本的adapter實現如下:
public class MainAdapter extends DragSelectRecyclerViewAdapter<MainAdapter.MainViewHolder> implements View.OnClickListener, View.OnLongClickListener { // Receives View.OnClickListener set in onBindViewHolder(), tag contains index @Override public void onClick(View v) { if (v.getTag() != null) { int index = (int) v.getTag(); // Forwards to the adapter's constructor callback if (mCallback != null) mCallback.onClick(index); } } // Receives View.OnLongClickListener set in onBindViewHolder(), tag contains index @Override public boolean onLongClick(View v) { if (v.getTag() != null) { int index = (int) v.getTag(); // Forwards to the adapter's constructor callback if (mCallback != null) mCallback.onLongClick(index); return true; } return false; } public interface ClickListener { void onClick(int index); void onLongClick(int index); } private final ClickListener mCallback; // Constructor takes click listener callback protected MainAdapter(ClickListener callback) { super(); mCallback = callback; } @Override public MainViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.griditem_main, parent, false); return new MainViewHolder(v); } @Override public void onBindViewHolder(MainViewHolder holder, int position) { // Sets position + 1 to a label view holder.label.setText(String.format("%d", position + 1)); if (isIndexSelected(position)) { // Item is selected, change it somehow } else { // Item is not selected, reset it to a non-selected state } // Tag is used to retrieve index from the click/long-click listeners holder.itemView.setTag(position); holder.itemView.setOnClickListener(this); holder.itemView.setOnLongClickListener(this); } @Override public int getItemCount() { return 60; } public class MainViewHolder extends RecyclerView.ViewHolder { public final TextView label; public MainViewHolder(View itemView) { super(itemView); this.label = (TextView) itemView.findViewById(R.id.label); } } }
You choose what to do when an item is selected (in onBindViewHolder). isIndexSelected(int)returns true or false. The click listener implementation used here will aid in the next section.
你自己選擇在一個item被選擇(在onBindViewHolder中)的時候做什么。
用戶激活
除非你告訴library,否則它不會啟用選擇模式。用戶要能夠自己激活它,上面adapter中click listener的實現可以幫助你做到這點。
public class MainActivity extends AppCompatActivity implements MainAdapter.ClickListener, DragSelectRecyclerViewAdapter.SelectionListener { private DragSelectRecyclerView mList; private MainAdapter mAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Setup adapter and callbacks mAdapter = new MainAdapter(this); // Listen for selection changes to update indicators mAdapter.setSelectionListener(this); // Restore selected indices after Activity recreation mAdapter.restoreInstanceState(savedInstanceState); // Setup the RecyclerView mList = (DragSelectRecyclerView) findViewById(R.id.list); mList.setLayoutManager(new GridLayoutManager(this, getResources().getInteger(R.integer.grid_width))); mList.setAdapter(mAdapter); } @Override public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) { super.onSaveInstanceState(outState, outPersistentState); // Save selected indices to be restored after recreation mAdapter.saveInstanceState(outState); } @Override public void onClick(int index) { // Single click will select or deselect an item mAdapter.toggleSelected(index); } @Override public void onLongClick(int index) { // Long click initializes drag selection, and selects the initial item mList.setDragSelectActive(true, index); } @Override public void onDragSelectionChanged(int count) { // TODO Selection was changed, updating an indicator, e.g. a Toolbar or contextual action bar } }
DragSelectRecyclerViewAdapter包含了許多可以幫助你的方法!
// Clears all selected indices adapter.clearSelected(); // Sets an index as selected (true) or unselected (false); adapter.setSelected(index, true); // If an index is selected, unselect it. Otherwise select it. Returns new selection state. boolean selectedNow = adapter.toggleSelected(index); // Gets the number of selected indices int count = adapter.getSelectedCount(); // Gets all selected indices Integer[] selectedItems = adapter.getSelectedIndices(); // Checks if an index is selected, useful in adapter subclass boolean selected = adapter.isIndexSelected(index); // Sets a listener that's notified of selection changes, used in the section above adapter.setSelectionListener(listener); // Used in section above, saves selected indices to Bundle adapter.saveInstanceState(outState); // Used in section above, restores selected indices from Bundle adapter.restoreInstanceState(inState);