use of android.util.SparseBooleanArray in project SmartAndroidSource by jaychou2012.
the class ActionMenuPresenter method flagActionItems.
public boolean flagActionItems() {
final ArrayList<MenuItemImpl> visibleItems = mMenu.getVisibleItems();
final int itemsSize = visibleItems.size();
int maxActions = mMaxItems;
int widthLimit = mActionItemWidthLimit;
final int querySpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
final ViewGroup parent = (ViewGroup) mMenuView;
int requiredItems = 0;
int requestedItems = 0;
int firstActionWidth = 0;
boolean hasOverflow = false;
for (int i = 0; i < itemsSize; i++) {
MenuItemImpl item = visibleItems.get(i);
if (item.requiresActionButton()) {
requiredItems++;
} else if (item.requestsActionButton()) {
requestedItems++;
} else {
hasOverflow = true;
}
if (mExpandedActionViewsExclusive && item.isActionViewExpanded()) {
// Overflow everything if we have an expanded action view and
// we're
// space constrained.
maxActions = 0;
}
}
// Reserve a spot for the overflow item if needed.
if (mReserveOverflow && (hasOverflow || requiredItems + requestedItems > maxActions)) {
maxActions--;
}
maxActions -= requiredItems;
final SparseBooleanArray seenGroups = mActionButtonGroups;
seenGroups.clear();
int cellSize = 0;
int cellsRemaining = 0;
if (mStrictWidthLimit) {
cellsRemaining = widthLimit / mMinCellSize;
final int cellSizeRemaining = widthLimit % mMinCellSize;
cellSize = mMinCellSize + cellSizeRemaining / cellsRemaining;
}
// Flag as many more requested items as will fit.
for (int i = 0; i < itemsSize; i++) {
MenuItemImpl item = visibleItems.get(i);
if (item.requiresActionButton()) {
View v = getItemView(item, mScrapActionButtonView, parent);
if (mScrapActionButtonView == null) {
mScrapActionButtonView = v;
}
if (mStrictWidthLimit) {
cellsRemaining -= ActionMenuView.measureChildForCells(v, cellSize, cellsRemaining, querySpec, 0);
} else {
v.measure(querySpec, querySpec);
}
final int measuredWidth = v.getMeasuredWidth();
widthLimit -= measuredWidth;
if (firstActionWidth == 0) {
firstActionWidth = measuredWidth;
}
final int groupId = item.getGroupId();
if (groupId != 0) {
seenGroups.put(groupId, true);
}
item.setIsActionButton(true);
} else if (item.requestsActionButton()) {
// Items in a group with other items that already have an action
// slot
// can break the max actions rule, but not the width limit.
final int groupId = item.getGroupId();
final boolean inGroup = seenGroups.get(groupId);
boolean isAction = (maxActions > 0 || inGroup) && widthLimit > 0 && (!mStrictWidthLimit || cellsRemaining > 0);
if (isAction) {
View v = getItemView(item, mScrapActionButtonView, parent);
if (mScrapActionButtonView == null) {
mScrapActionButtonView = v;
}
if (mStrictWidthLimit) {
final int cells = ActionMenuView.measureChildForCells(v, cellSize, cellsRemaining, querySpec, 0);
cellsRemaining -= cells;
if (cells == 0) {
isAction = false;
}
} else {
v.measure(querySpec, querySpec);
}
final int measuredWidth = v.getMeasuredWidth();
widthLimit -= measuredWidth;
if (firstActionWidth == 0) {
firstActionWidth = measuredWidth;
}
if (mStrictWidthLimit) {
isAction &= widthLimit >= 0;
} else {
// Did this push the entire first item past the limit?
isAction &= widthLimit + firstActionWidth > 0;
}
}
if (isAction && groupId != 0) {
seenGroups.put(groupId, true);
} else if (inGroup) {
// We broke the width limit. Demote the whole group, they
// all overflow now.
seenGroups.put(groupId, false);
for (int j = 0; j < i; j++) {
MenuItemImpl areYouMyGroupie = visibleItems.get(j);
if (areYouMyGroupie.getGroupId() == groupId) {
// Give back the action slot
if (areYouMyGroupie.isActionButton())
maxActions++;
areYouMyGroupie.setIsActionButton(false);
}
}
}
if (isAction)
maxActions--;
item.setIsActionButton(isAction);
}
}
return true;
}
use of android.util.SparseBooleanArray in project Klyph by jonathangerbaud.
the class AbsHListView method onSaveInstanceState.
@Override
public Parcelable onSaveInstanceState() {
/*
* This doesn't really make sense as the place to dismiss the popups, but there don't seem to be any other useful hooks that
* happen early enough to keep from getting complaints about having leaked the window.
*/
Parcelable superState = super.onSaveInstanceState();
SavedState ss = new SavedState(superState);
if (mPendingSync != null) {
// Just keep what we last restored.
ss.selectedId = mPendingSync.selectedId;
ss.firstId = mPendingSync.firstId;
ss.viewLeft = mPendingSync.viewLeft;
ss.position = mPendingSync.position;
ss.width = mPendingSync.width;
ss.filter = mPendingSync.filter;
ss.inActionMode = mPendingSync.inActionMode;
ss.checkedItemCount = mPendingSync.checkedItemCount;
ss.checkState = mPendingSync.checkState;
ss.checkIdState = mPendingSync.checkIdState;
return ss;
}
boolean haveChildren = getChildCount() > 0 && mItemCount > 0;
long selectedId = getSelectedItemId();
ss.selectedId = selectedId;
ss.width = getWidth();
if (selectedId >= 0) {
// Remember the selection
ss.viewLeft = mSelectedLeft;
ss.position = getSelectedItemPosition();
ss.firstId = INVALID_POSITION;
} else {
if (haveChildren && mFirstPosition > 0) {
// Remember the position of the first child.
// We only do this if we are not currently at the top of
// the list, for two reasons:
// (1) The list may be in the process of becoming empty, in
// which case mItemCount may not be 0, but if we try to
// ask for any information about position 0 we will crash.
// (2) Being "at the top" seems like a special case, anyway,
// and the user wouldn't expect to end up somewhere else when
// they revisit the list even if its content has changed.
View v = getChildAt(0);
ss.viewLeft = v.getLeft();
int firstPos = mFirstPosition;
if (firstPos >= mItemCount) {
firstPos = mItemCount - 1;
}
ss.position = firstPos;
ss.firstId = mAdapter.getItemId(firstPos);
} else {
ss.viewLeft = 0;
ss.firstId = INVALID_POSITION;
ss.position = 0;
}
}
ss.filter = null;
ss.inActionMode = android.os.Build.VERSION.SDK_INT >= 11 && mChoiceMode == ListView.CHOICE_MODE_MULTIPLE_MODAL && mChoiceActionMode != null;
if (mCheckStates != null) {
try {
ss.checkState = mCheckStates.clone();
} catch (NoSuchMethodError e) {
e.printStackTrace();
ss.checkState = new SparseBooleanArray();
}
}
if (mCheckedIdStates != null) {
final LongSparseArray<Integer> idState = new LongSparseArray<Integer>();
final int count = mCheckedIdStates.size();
for (int i = 0; i < count; i++) {
idState.put(mCheckedIdStates.keyAt(i), mCheckedIdStates.valueAt(i));
}
ss.checkIdState = idState;
}
ss.checkedItemCount = mCheckedItemCount;
return ss;
}
use of android.util.SparseBooleanArray in project SmartAndroidSource by jaychou2012.
the class DragListView method moveCheckState.
/**
* Use this to move the check state of an item from one position to another
* in a drop operation. If you have a choiceMode which is not none, this
* method must be called when the order of items changes in an underlying
* adapter which does not have stable IDs (see
* {@link ListAdapter#hasStableIds()}). This is because without IDs, the
* ListView has no way of knowing which items have moved where, and cannot
* update the check state accordingly.
* <p>
* A word of warning about a "feature" in Android that you may run into when
* dealing with movable list items: for an adapter that <em>does</em> have
* stable IDs, ListView will attempt to locate each item based on its ID and
* move the check state from the item's old position to the new position 鈥�
* * which is all fine and good (and removes the need for calling this
* function), except for the half-baked approach. Apparently to save time in
* the naive algorithm used, ListView will only search for an ID in the
* close neighborhood of the old position. If the user moves an item too far
* (specifically, more than 20 rows away), ListView will give up and just
* force the item to be unchecked. So if there is a reasonable chance that
* the user will move items more than 20 rows away from the original
* position, you may wish to use an adapter with unstable IDs and call this
* method manually instead.
*
* @param from
* @param to
*/
public void moveCheckState(int from, int to) {
// This method runs in O(n log n) time (n being the number of list
// items). The bottleneck is the call to AbsListView.setItemChecked,
// which is O(log n) because of the binary search involved in calling
// SparseBooleanArray.put().
//
// To improve on the average time, we minimize the number of calls to
// setItemChecked by only calling it for items that actually have a
// changed state. This is achieved by building a list containing the
// start and end of the "runs" of checked items, and then moving the
// runs. Note that moving an item from A to B is essentially a rotation
// of the range of items in [A, B]. Let's say we have
// . . U V X Y Z . .
// and move U after Z. This is equivalent to a rotation one step to the
// left within the range you are moving across:
// . . V X Y Z U . .
//
// So, to perform the move we enumerate all the runs within the move
// range, then rotate each run one step to the left or right (depending
// on move direction). For example, in the list:
// X X . X X X . X
// we have two runs. One begins at the last item of the list and wraps
// around to the beginning, ending at position 1. The second begins at
// position 3 and ends at position 5. To rotate a run, regardless of
// length, we only need to set a check mark at one end of the run, and
// clear a check mark at the other end:
// X . X X X . X X
SparseBooleanArray cip = getCheckedItemPositions();
int rangeStart = from;
int rangeEnd = to;
if (to < from) {
rangeStart = to;
rangeEnd = from;
}
rangeEnd += 1;
int[] runStart = new int[cip.size()];
int[] runEnd = new int[cip.size()];
int runCount = buildRunList(cip, rangeStart, rangeEnd, runStart, runEnd);
if (runCount == 1 && (runStart[0] == runEnd[0])) {
// item to false like we do below.
return;
}
if (from < to) {
for (int i = 0; i != runCount; i++) {
setItemChecked(rotate(runStart[i], -1, rangeStart, rangeEnd), true);
setItemChecked(rotate(runEnd[i], -1, rangeStart, rangeEnd), false);
}
} else {
for (int i = 0; i != runCount; i++) {
setItemChecked(runStart[i], false);
setItemChecked(runEnd[i], true);
}
}
}
use of android.util.SparseBooleanArray in project SmartAndroidSource by jaychou2012.
the class DragListView method removeCheckState.
/**
* Use this when an item has been deleted, to move the check state of all
* following items up one step. If you have a choiceMode which is not none,
* this method must be called when the order of items changes in an
* underlying adapter which does not have stable IDs (see
* {@link ListAdapter#hasStableIds()}). This is because without IDs, the
* ListView has no way of knowing which items have moved where, and cannot
* update the check state accordingly.
*
* See also further comments on {@link #moveCheckState(int, int)}.
*
* @param position
*/
public void removeCheckState(int position) {
SparseBooleanArray cip = getCheckedItemPositions();
if (cip.size() == 0)
return;
int[] runStart = new int[cip.size()];
int[] runEnd = new int[cip.size()];
int rangeStart = position;
int rangeEnd = cip.keyAt(cip.size() - 1) + 1;
int runCount = buildRunList(cip, rangeStart, rangeEnd, runStart, runEnd);
for (int i = 0; i != runCount; i++) {
if (!(runStart[i] == position || (runEnd[i] < runStart[i] && runEnd[i] > position))) {
// Only set a new check mark in front of this run if it does
// not contain the deleted position. If it does, we only need
// to make it one check mark shorter at the end.
setItemChecked(rotate(runStart[i], -1, rangeStart, rangeEnd), true);
}
setItemChecked(rotate(runEnd[i], -1, rangeStart, rangeEnd), false);
}
}
use of android.util.SparseBooleanArray in project Klyph by jonathangerbaud.
the class MultiSelectDragListPreference method refreshNewValues.
private void refreshNewValues() {
mNewValues.clear();
int n = adapter.getCount();
SparseBooleanArray checkedPositions = listView.getCheckedItemPositions();
for (int i = 0; i < n; i++) {
if (checkedPositions.get(i) == true) {
mNewValues.add((String) mEntryValues[ArrayUtils.indexOf(mEntries, adapter.getItem(i))]);
}
}
}
Aggregations