@Override public void handleMessage(Message msg) { switch (msg.what) { case OnItemChecked: // 为局部刷新用 ArrayList<Integer> change = new ArrayList<Integer>(); int p = (Integer) msg.obj; change.add(p); if (beans.get(p).isChecked()) { beans.get(p).setChecked(false); } else { int size = getCheckedSize(); while (size >= 10) { for (int i = 0; i < beans.size(); i++) { if (beans.get(i).isChecked()) { beans.get(i).setChecked(false); change.add(i); size--; break; } } } beans.get(p).setChecked(true); } updateItems(change); break; default: break; } super.handleMessage(msg); }
/** * Defines the choice behavior for the List. By default, Lists do not have any choice behavior * ({@link ChoiceMode#NONE}). By setting the choiceMode to {@link ChoiceMode#SINGLE}, the List * allows up to one item to be in a chosen state. By setting the choiceMode to {@link * ChoiceMode#MULTIPLE}, the list allows any number of items to be chosen. * * @param choiceMode One of {@link ChoiceMode#NONE}, {@link ChoiceMode#SINGLE}, or {@link * ChoiceMode#MULTIPLE} */ public void setChoiceMode(ChoiceMode choiceMode) { if (mChoiceMode == choiceMode) { return; } mChoiceMode = choiceMode; if (mChoiceMode != ChoiceMode.NONE) { if (mCheckedStates == null) { mCheckedStates = new CheckedStates(); } final Adapter adapter = mRecyclerView.getAdapter(); if (mCheckedIdStates == null && adapter != null && adapter.hasStableIds()) { mCheckedIdStates = new CheckedIdStates(); } } }
public void onAdapterDataChanged() { final Adapter adapter = mRecyclerView.getAdapter(); if (mChoiceMode == ChoiceMode.NONE || adapter == null || !adapter.hasStableIds()) { return; } final int itemCount = adapter.getItemCount(); // Clear out the positional check states, we'll rebuild it below from IDs. mCheckedStates.clear(); for (int checkedIndex = 0; checkedIndex < mCheckedIdStates.size(); checkedIndex++) { final long currentId = mCheckedIdStates.keyAt(checkedIndex); final int currentPosition = mCheckedIdStates.valueAt(checkedIndex); final long newPositionId = adapter.getItemId(currentPosition); if (currentId != newPositionId) { // Look around to see if the ID is nearby. If not, uncheck it. final int start = Math.max(0, currentPosition - CHECK_POSITION_SEARCH_DISTANCE); final int end = Math.min(currentPosition + CHECK_POSITION_SEARCH_DISTANCE, itemCount); boolean found = false; for (int searchPos = start; searchPos < end; searchPos++) { final long searchId = adapter.getItemId(searchPos); if (currentId == searchId) { found = true; mCheckedStates.put(searchPos, true); mCheckedIdStates.setValueAt(checkedIndex, searchPos); break; } } if (!found) { mCheckedIdStates.delete(currentId); mCheckedCount--; checkedIndex--; } } else { mCheckedStates.put(currentPosition, true); } } }
/** * Sets the checked state of the specified position. The is only valid if the choice mode has been * set to {@link ChoiceMode#SINGLE} or {@link ChoiceMode#MULTIPLE}. * * @param position The item whose checked state is to be checked * @param checked The new checked state for the item */ public void setItemChecked(int position, boolean checked) { if (mChoiceMode == ChoiceMode.NONE) { return; } final Adapter adapter = mRecyclerView.getAdapter(); if (mChoiceMode == ChoiceMode.MULTIPLE) { boolean oldValue = mCheckedStates.get(position); mCheckedStates.put(position, checked); if (mCheckedIdStates != null && adapter.hasStableIds()) { if (checked) { mCheckedIdStates.put(adapter.getItemId(position), position); } else { mCheckedIdStates.delete(adapter.getItemId(position)); } } if (oldValue != checked) { if (checked) { mCheckedCount++; } else { mCheckedCount--; } } } else { boolean updateIds = mCheckedIdStates != null && adapter.hasStableIds(); // Clear all values if we're checking something, or unchecking the currently // selected item if (checked || isItemChecked(position)) { mCheckedStates.clear(); if (updateIds) { mCheckedIdStates.clear(); } } // This may end up selecting the checked we just cleared but this way // we ensure length of mCheckStates is 1, a fact getCheckedItemPosition relies on if (checked) { mCheckedStates.put(position, true); if (updateIds) { mCheckedIdStates.put(adapter.getItemId(position), position); } mCheckedCount = 1; } else if (mCheckedStates.size() == 0 || !mCheckedStates.valueAt(0)) { mCheckedCount = 0; } } updateOnScreenCheckedViews(); }
@Override boolean performItemClick(RecyclerView parent, View view, int position, long id) { final Adapter adapter = mRecyclerView.getAdapter(); boolean checkedStateChanged = false; if (mChoiceMode == ChoiceMode.MULTIPLE) { boolean checked = !mCheckedStates.get(position, false); mCheckedStates.put(position, checked); if (mCheckedIdStates != null && adapter.hasStableIds()) { if (checked) { mCheckedIdStates.put(adapter.getItemId(position), position); } else { mCheckedIdStates.delete(adapter.getItemId(position)); } } if (checked) { mCheckedCount++; } else { mCheckedCount--; } checkedStateChanged = true; } else if (mChoiceMode == ChoiceMode.SINGLE) { boolean checked = !mCheckedStates.get(position, false); if (checked) { mCheckedStates.clear(); mCheckedStates.put(position, true); if (mCheckedIdStates != null && adapter.hasStableIds()) { mCheckedIdStates.clear(); mCheckedIdStates.put(adapter.getItemId(position), position); } mCheckedCount = 1; } else if (mCheckedStates.size() == 0 || !mCheckedStates.valueAt(0)) { mCheckedCount = 0; } checkedStateChanged = true; } if (checkedStateChanged) { updateOnScreenCheckedViews(); } return false; }
@Override public boolean handleKeyboardShortcutRepeat( @NonNull final KeyboardShortcutsHandler handler, final int keyCode, final int repeatCount, @NonNull final KeyEvent event, int metaState) { final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event, metaState); if (action == null) return false; final int direction; switch (action) { case ACTION_NAVIGATION_PREVIOUS: { direction = -1; break; } case ACTION_NAVIGATION_NEXT: { direction = 1; break; } case ACTION_NAVIGATION_PAGE_DOWN: { RecyclerViewUtils.pageScroll(view, manager, 1); return true; } case ACTION_NAVIGATION_PAGE_UP: { RecyclerViewUtils.pageScroll(view, manager, -1); return true; } default: { return false; } } final View focusedChild = RecyclerViewUtils.findRecyclerViewChild(view, manager.getFocusedChild()); final int position; final int firstVisibleItemPosition = manager.findFirstVisibleItemPosition(); final int lastVisibleItemPosition = manager.findLastVisibleItemPosition(); final int itemCount = adapter.getItemCount(); final boolean backupOutsideRange = positionBackup > lastVisibleItemPosition || positionBackup < firstVisibleItemPosition; if (focusedChild != null) { position = view.getChildLayoutPosition(focusedChild); } else if (firstVisibleItemPosition == 0) { position = -1; } else if (lastVisibleItemPosition == itemCount - 1) { position = itemCount; } else if (direction > 0 && backupOutsideRange) { position = firstVisibleItemPosition; } else if (direction < 0 && backupOutsideRange) { position = lastVisibleItemPosition; } else { position = positionBackup; } positionBackup = position; RecyclerViewUtils.focusNavigate(view, manager, position, direction); return true; }