ListView#getCheckItemIds() deprecated for ListView#getCheckedItemIds().
ListView#getCheckedItemIds() now works more reliably.
diff --git a/api/current.xml b/api/current.xml
index 0484b77..8989e8f 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -204003,6 +204003,17 @@
synchronized="false"
static="false"
final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+</method>
+<method name="getCheckedItemIds"
+ return="long[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
deprecated="not deprecated"
visibility="public"
>
diff --git a/core/java/android/util/LongSparseArray.java b/core/java/android/util/LongSparseArray.java
index d90045f..1ec8be6 100644
--- a/core/java/android/util/LongSparseArray.java
+++ b/core/java/android/util/LongSparseArray.java
@@ -48,6 +48,28 @@
mValues = new Object[initialCapacity];
mSize = 0;
}
+
+ /**
+ * @return A copy of all keys contained in the sparse array.
+ */
+ public long[] getKeys() {
+ int length = mKeys.length;
+ long[] result = new long[length];
+ System.arraycopy(mKeys, 0, result, 0, length);
+ return result;
+ }
+
+ /**
+ * Sets all supplied keys to the given unique value.
+ * @param keys Keys to set
+ * @param uniqueValue Value to set all supplied keys to
+ */
+ public void setValues(long[] keys, E uniqueValue) {
+ int length = keys.length;
+ for (int i = 0; i < length; i++) {
+ put(keys[i], uniqueValue);
+ }
+ }
/**
* Gets the Object mapped from the specified key, or <code>null</code>
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index e3eb6db..097e859 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -30,6 +30,7 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
+import android.util.LongSparseArray;
import android.util.SparseBooleanArray;
import android.view.FocusFinder;
import android.view.KeyEvent;
@@ -131,6 +132,7 @@
private int mChoiceMode = CHOICE_MODE_NONE;
private SparseBooleanArray mCheckStates;
+ private LongSparseArray<Boolean> mCheckedIdStates;
// used for temporary calculations.
private final Rect mTempRect = new Rect();
@@ -463,6 +465,10 @@
if (mCheckStates != null) {
mCheckStates.clear();
}
+
+ if (mCheckedIdStates != null) {
+ mCheckedIdStates.clear();
+ }
requestLayout();
}
@@ -3310,8 +3316,13 @@
*/
public void setChoiceMode(int choiceMode) {
mChoiceMode = choiceMode;
- if (mChoiceMode != CHOICE_MODE_NONE && mCheckStates == null) {
- mCheckStates = new SparseBooleanArray();
+ if (mChoiceMode != CHOICE_MODE_NONE) {
+ if (mCheckStates == null) {
+ mCheckStates = new SparseBooleanArray();
+ }
+ if (mCheckedIdStates == null && mAdapter.hasStableIds()) {
+ mCheckedIdStates = new LongSparseArray<Boolean>();
+ }
}
}
@@ -3323,14 +3334,25 @@
handled = true;
if (mChoiceMode == CHOICE_MODE_MULTIPLE) {
- boolean oldValue = mCheckStates.get(position, false);
- mCheckStates.put(position, !oldValue);
+ boolean newValue = !mCheckStates.get(position, false);
+ mCheckStates.put(position, newValue);
+ if (mCheckedIdStates != null && mAdapter.hasStableIds()) {
+ if (newValue) {
+ mCheckedIdStates.put(mAdapter.getItemId(position), Boolean.TRUE);
+ } else {
+ mCheckedIdStates.delete(mAdapter.getItemId(position));
+ }
+ }
} else {
- boolean oldValue = mCheckStates.get(position, false);
- if (!oldValue) {
+ boolean newValue = !mCheckStates.get(position, false);
+ if (newValue) {
mCheckStates.clear();
mCheckStates.put(position, true);
- }
+ if (mCheckedIdStates != null && mAdapter.hasStableIds()) {
+ mCheckedIdStates.clear();
+ mCheckedIdStates.put(mAdapter.getItemId(position), Boolean.TRUE);
+ }
+ }
}
mDataChanged = true;
@@ -3358,16 +3380,30 @@
if (mChoiceMode == CHOICE_MODE_MULTIPLE) {
mCheckStates.put(position, value);
+ if (mCheckedIdStates != null && mAdapter.hasStableIds()) {
+ if (value) {
+ mCheckedIdStates.put(mAdapter.getItemId(position), Boolean.TRUE);
+ } else {
+ mCheckedIdStates.delete(mAdapter.getItemId(position));
+ }
+ }
} else {
+ boolean updateIds = mCheckedIdStates != null && mAdapter.hasStableIds();
// Clear all values if we're checking something, or unchecking the currently
// selected item
if (value || isItemChecked(position)) {
mCheckStates.clear();
+ if (updateIds) {
+ mCheckedIdStates.clear();
+ }
}
// this may end up selecting the value we just cleared but this way
// we ensure length of mCheckStates is 1, a fact getCheckedItemPosition relies on
if (value) {
mCheckStates.put(position, true);
+ if (updateIds) {
+ mCheckedIdStates.put(mAdapter.getItemId(position), Boolean.TRUE);
+ }
}
}
@@ -3433,38 +3469,39 @@
/**
* Returns the set of checked items ids. The result is only valid if the
- * choice mode has not been set to {@link #CHOICE_MODE_SINGLE}.
+ * choice mode has not been set to {@link #CHOICE_MODE_NONE}.
+ *
+ * @return A new array which contains the id of each checked item in the
+ * list.
+ *
+ * @deprecated Use {@link #getCheckedItemIds()} instead.
+ */
+ public long[] getCheckItemIds() {
+ return getCheckedItemIds();
+ }
+
+ /**
+ * Returns the set of checked items ids. The result is only valid if the
+ * choice mode has not been set to {@link #CHOICE_MODE_NONE} and the adapter
+ * has stable IDs. ({@link ListAdapter#hasStableIds()} == {@code true})
*
* @return A new array which contains the id of each checked item in the
* list.
*/
- public long[] getCheckItemIds() {
- if (mChoiceMode != CHOICE_MODE_NONE && mCheckStates != null && mAdapter != null) {
- final SparseBooleanArray states = mCheckStates;
- final int count = states.size();
- final long[] ids = new long[count];
- final ListAdapter adapter = mAdapter;
-
- int checkedCount = 0;
- for (int i = 0; i < count; i++) {
- if (states.valueAt(i)) {
- ids[checkedCount++] = adapter.getItemId(states.keyAt(i));
- }
- }
-
- // Trim array if needed. mCheckStates may contain false values
- // resulting in checkedCount being smaller than count.
- if (checkedCount == count) {
- return ids;
- } else {
- final long[] result = new long[checkedCount];
- System.arraycopy(ids, 0, result, 0, checkedCount);
-
- return result;
- }
+ public long[] getCheckedItemIds() {
+ if (mChoiceMode == CHOICE_MODE_NONE || mCheckedIdStates == null || mAdapter == null) {
+ return new long[0];
}
-
- return new long[0];
+
+ final LongSparseArray<Boolean> idStates = mCheckedIdStates;
+ final int count = idStates.size();
+ final long[] ids = new long[count];
+
+ for (int i = 0; i < count; i++) {
+ ids[i] = idStates.keyAt(i);
+ }
+
+ return ids;
}
/**
@@ -3474,17 +3511,23 @@
if (mCheckStates != null) {
mCheckStates.clear();
}
+ if (mCheckedIdStates != null) {
+ mCheckedIdStates.clear();
+ }
}
static class SavedState extends BaseSavedState {
SparseBooleanArray checkState;
+ LongSparseArray<Boolean> checkIdState;
/**
* Constructor called from {@link ListView#onSaveInstanceState()}
*/
- SavedState(Parcelable superState, SparseBooleanArray checkState) {
+ SavedState(Parcelable superState, SparseBooleanArray checkState,
+ LongSparseArray<Boolean> checkIdState) {
super(superState);
this.checkState = checkState;
+ this.checkIdState = checkIdState;
}
/**
@@ -3493,12 +3536,19 @@
private SavedState(Parcel in) {
super(in);
checkState = in.readSparseBooleanArray();
+ long[] idState = in.createLongArray();
+
+ if (idState.length > 0) {
+ checkIdState = new LongSparseArray<Boolean>();
+ checkIdState.setValues(idState, Boolean.TRUE);
+ }
}
@Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeSparseBooleanArray(checkState);
+ out.writeLongArray(checkIdState != null ? checkIdState.getKeys() : new long[0]);
}
@Override
@@ -3523,7 +3573,7 @@
@Override
public Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
- return new SavedState(superState, mCheckStates);
+ return new SavedState(superState, mCheckStates, mCheckedIdStates);
}
@Override
@@ -3536,5 +3586,8 @@
mCheckStates = ss.checkState;
}
+ if (ss.checkIdState != null) {
+ mCheckedIdStates = ss.checkIdState;
+ }
}
}