List of usage examples for android.view ViewDebug TRACE_RECYCLER
boolean TRACE_RECYCLER
To view the source code for android.view ViewDebug TRACE_RECYCLER.
Click Source Link
From source file:com.huewu.pla.lib.internal.PLA_ListView.java
@SuppressWarnings("deprecation") @Override//from w w w . j a va 2s . co m protected void layoutChildren() { final boolean blockLayoutRequests = mBlockLayoutRequests; if (!blockLayoutRequests) { mBlockLayoutRequests = true; } else { return; } try { super.layoutChildren(); invalidate(); if (mAdapter == null) { resetList(); invokeOnItemScrollListener(); return; } int childrenTop = mListPadding.top; // int childrenBottom = mBottom - mTop - mListPadding.bottom; int childrenBottom = getBottom() - getTop() - mListPadding.bottom; int childCount = getChildCount(); int index = 0; View oldFirst = null; View focusLayoutRestoreView = null; // Remember stuff we will need down below switch (mLayoutMode) { case LAYOUT_FORCE_TOP: case LAYOUT_FORCE_BOTTOM: case LAYOUT_SPECIFIC: case LAYOUT_SYNC: break; default: // Remember the previous first child oldFirst = getChildAt(0); } boolean dataChanged = mDataChanged; if (dataChanged) { handleDataChanged(); } // Handle the empty set by removing all views that are visible // and calling it a day if (mItemCount == 0) { resetList(); invokeOnItemScrollListener(); return; } else if (mItemCount != mAdapter.getCount()) { throw new IllegalStateException("The content of the adapter has changed but " + "ListView did not receive a notification. Make sure the content of " + "your adapter is not modified from a background thread, but only " + "from the UI thread. [in ListView(" + getId() + ", " + getClass() + ") with Adapter(" + mAdapter.getClass() + ")]"); } // Pull all children into the RecycleBin. // These views will be reused if possible final int firstPosition = mFirstPosition; final RecycleBin recycleBin = mRecycler; // reset the focus restoration // Don't put header or footer views into the Recycler. Those are // already cached in mHeaderViews; if (dataChanged) { for (int i = 0; i < childCount; i++) { recycleBin.addScrapView(getChildAt(i)); if (ViewDebug.TRACE_RECYCLER) { ViewDebug.trace(getChildAt(i), ViewDebug.RecyclerTraceType.MOVE_TO_SCRAP_HEAP, index, i); } } } else { recycleBin.fillActiveViews(childCount, firstPosition); } // take focus back to us temporarily to avoid the eventual // call to clear focus when removing the focused child below // from messing things up when ViewRoot assigns focus back // to someone else final View focusedChild = getFocusedChild(); if (focusedChild != null) { // TODO: in some cases focusedChild.getParent() == null // we can remember the focused view to restore after relayout if // the // data hasn't changed, or if the focused position is a header // or footer if (!dataChanged || isDirectChildHeaderOrFooter(focusedChild)) { // remember the specific view that had focus focusLayoutRestoreView = findFocus(); if (focusLayoutRestoreView != null) { // tell it we are going to mess with it focusLayoutRestoreView.onStartTemporaryDetach(); } } requestFocus(); } switch (mLayoutMode) { case LAYOUT_SYNC: onLayoutSync(mSyncPosition); // Clear out old views detachAllViewsFromParent(); fillSpecific(mSyncPosition, mSpecificTop); onLayoutSyncFinished(mSyncPosition); break; case LAYOUT_FORCE_BOTTOM: detachAllViewsFromParent(); fillUp(mItemCount - 1, childrenBottom); adjustViewsUpOrDown(); break; case LAYOUT_FORCE_TOP: detachAllViewsFromParent(); mFirstPosition = 0; fillFromTop(childrenTop); adjustViewsUpOrDown(); break; default: if (childCount == 0) { detachAllViewsFromParent(); if (!mStackFromBottom) { fillFromTop(childrenTop); } else { fillUp(mItemCount - 1, childrenBottom); } } else { if (mFirstPosition < mItemCount) { onLayoutSync(mFirstPosition); detachAllViewsFromParent(); fillSpecific(mFirstPosition, oldFirst == null ? childrenTop : oldFirst.getTop()); onLayoutSyncFinished(mFirstPosition); } else { onLayoutSync(0); detachAllViewsFromParent(); fillSpecific(0, childrenTop); onLayoutSyncFinished(0); } } break; } // Flush any cached views that did not get reused above recycleBin.scrapActiveViews(); if (mTouchMode > TOUCH_MODE_DOWN && mTouchMode < TOUCH_MODE_SCROLL) { View child = getChildAt(mMotionPosition - mFirstPosition); if (child != null) positionSelector(child); } else { mSelectedTop = 0; mSelectorRect.setEmpty(); } // even if there is not selected position, we may need to restore // focus (i.e. something focusable in touch mode) if (hasFocus() && focusLayoutRestoreView != null) { focusLayoutRestoreView.requestFocus(); } // tell focus view we are done mucking with it, if it is still in // our view hierarchy. if (focusLayoutRestoreView != null && focusLayoutRestoreView.getWindowToken() != null) { focusLayoutRestoreView.onFinishTemporaryDetach(); } mLayoutMode = LAYOUT_NORMAL; mDataChanged = false; mNeedSync = false; invokeOnItemScrollListener(); } finally { if (!blockLayoutRequests) { mBlockLayoutRequests = false; } } }
From source file:com.huewu.pla.lib.internal.PLAListView.java
@SuppressWarnings("deprecation") @Override//from w ww .j av a 2 s. c o m protected void layoutChildren() { final boolean blockLayoutRequests = mBlockLayoutRequests; if (!blockLayoutRequests) { mBlockLayoutRequests = true; } else return; try { super.layoutChildren(); invalidate(); if (mAdapter == null) { resetList(); invokeOnItemScrollListener(); return; } final int childrenTop = mListPadding.top; // int childrenBottom = mBottom - mTop - mListPadding.bottom; final int childrenBottom = getBottom() - getTop() - mListPadding.bottom; final int childCount = getChildCount(); final int index = 0; View oldFirst = null; View focusLayoutRestoreView = null; // Remember stuff we will need down below switch (mLayoutMode) { case LAYOUT_FORCE_TOP: case LAYOUT_FORCE_BOTTOM: case LAYOUT_SPECIFIC: case LAYOUT_SYNC: break; default: // Remember the previous first child oldFirst = getChildAt(0); } final boolean dataChanged = mDataChanged; if (dataChanged) { handleDataChangedPLA(); } // Handle the empty set by removing all views that are visible // and calling it a day if (mItemCount == 0) { resetList(); invokeOnItemScrollListener(); return; } else if (mItemCount != mAdapter.getCount()) throw new IllegalStateException("The content of the adapter has changed but " + "ListView did not receive a notification. Make sure the content of " + "your adapter is not modified from a background thread, but only " + "from the UI thread. [in ListView(" + getId() + ", " + getClass() + ") with Adapter(" + mAdapter.getClass() + ")]"); // Pull all children into the RecycleBin. // These views will be reused if possible final int firstPosition = mFirstPosition; final RecycleBin recycleBin = mRecycler; // reset the focus restoration // Don't put header or footer views into the Recycler. Those are // already cached in mHeaderViews; if (dataChanged) { for (int i = 0; i < childCount; i++) { recycleBin.addScrapView(getChildAt(i)); if (ViewDebug.TRACE_RECYCLER) { ViewDebug.trace(getChildAt(i), ViewDebug.RecyclerTraceType.MOVE_TO_SCRAP_HEAP, index, i); } } } else { recycleBin.fillActiveViews(childCount, firstPosition); } // take focus back to us temporarily to avoid the eventual // call to clear focus when removing the focused child below // from messing things up when ViewRoot assigns focus back // to someone else final View focusedChild = getFocusedChild(); if (focusedChild != null) { // TODO: in some cases focusedChild.getParent() == null // we can remember the focused view to restore after relayout if // the // data hasn't changed, or if the focused position is a header // or footer if (!dataChanged || isDirectChildHeaderOrFooter(focusedChild)) { // remember the specific view that had focus focusLayoutRestoreView = findFocus(); if (focusLayoutRestoreView != null) { // tell it we are going to mess with it focusLayoutRestoreView.onStartTemporaryDetach(); } } requestFocus(); } switch (mLayoutMode) { case LAYOUT_SYNC: onLayoutSync(mSyncPosition); // Clear out old views detachAllViewsFromParent(); fillSpecific(mSyncPosition, mSpecificTop); onLayoutSyncFinished(mSyncPosition); break; case LAYOUT_FORCE_BOTTOM: detachAllViewsFromParent(); fillUp(mItemCount - 1, childrenBottom); adjustViewsUpOrDown(); break; case LAYOUT_FORCE_TOP: detachAllViewsFromParent(); mFirstPosition = 0; fillFromTop(childrenTop); adjustViewsUpOrDown(); break; default: if (childCount == 0) { detachAllViewsFromParent(); if (!mStackFromBottom) { fillFromTop(childrenTop); } else { fillUp(mItemCount - 1, childrenBottom); } } else { if (mFirstPosition < mItemCount) { onLayoutSync(mFirstPosition); detachAllViewsFromParent(); fillSpecific(mFirstPosition, oldFirst == null ? childrenTop : oldFirst.getTop()); onLayoutSyncFinished(mFirstPosition); } else { onLayoutSync(0); detachAllViewsFromParent(); fillSpecific(0, childrenTop); onLayoutSyncFinished(0); } } break; } // Flush any cached views that did not get reused above recycleBin.scrapActiveViews(); if (mTouchMode > TOUCH_MODE_DOWN && mTouchMode < TOUCH_MODE_SCROLL) { final View child = getChildAt(mMotionPosition - mFirstPosition); if (child != null) { positionSelector(child); } } else { mSelectedTop = 0; mSelectorRect.setEmpty(); } // even if there is not selected position, we may need to restore // focus (i.e. something focusable in touch mode) if (hasFocus() && focusLayoutRestoreView != null) { focusLayoutRestoreView.requestFocus(); } // tell focus view we are done mucking with it, if it is still in // our view hierarchy. if (focusLayoutRestoreView != null && focusLayoutRestoreView.getWindowToken() != null) { focusLayoutRestoreView.onFinishTemporaryDetach(); } mLayoutMode = LAYOUT_NORMAL; mDataChanged = false; mNeedSync = false; invokeOnItemScrollListener(); } finally { if (!blockLayoutRequests) { mBlockLayoutRequests = false; } } }
From source file:com.huewu.pla.lib.internal.PLA_ListView.java
/** * Obtain the view and add it to our list of children. The view can be made * fresh, converted from an unused view, or used as is if it was in the * recycle bin./*from ww w. j av a 2 s. c o m*/ * * @param position * Logical position in the list * @param childrenBottomOrTop * Top or bottom edge of the view to add * @param flow * If flow is true, align top edge to y. If false, align bottom * edge to y. * @param selected * Is this position selected? * @return View that was added */ @SuppressWarnings("deprecation") private View makeAndAddView(int position, int childrenBottomOrTop, boolean flow, boolean selected) { View child; int childrenLeft; if (!mDataChanged) { // Try to use an exsiting view for this position child = mRecycler.getActiveView(position); if (child != null) { if (ViewDebug.TRACE_RECYCLER) { ViewDebug.trace(child, ViewDebug.RecyclerTraceType.RECYCLE_FROM_ACTIVE_HEAP, position, getChildCount()); } // Found it -- we're using an existing child // This just needs to be positioned childrenLeft = getItemLeft(position); setupChild(child, position, childrenBottomOrTop, flow, childrenLeft, selected, true); return child; } } // Notify new item is added to view. onItemAddedToList(position, flow); childrenLeft = getItemLeft(position); // Make a new view for this position, or convert an unused view if // possible child = obtainView(position, mIsScrap); // This needs to be positioned and measured setupChild(child, position, childrenBottomOrTop, flow, childrenLeft, selected, mIsScrap[0]); return child; }
From source file:org.bangbang.support.v4.widget.HListView.java
@Override protected void layoutChildren() { final boolean blockLayoutRequests = mBlockLayoutRequests; if (!blockLayoutRequests) { mBlockLayoutRequests = true; } else {//from w ww .ja va 2 s . c o m return; } try { super.layoutChildren(); invalidate(); if (mAdapter == null) { resetList(); invokeOnItemScrollListener(); return; } int childrenLeft = mListPadding.left; int childrenRight = getRight() - getLeft() - mListPadding.right; int childCount = getChildCount(); int index; int delta = 0; View sel; View oldSel = null; View oldFirst = null; View newSel = null; View focusLayoutRestoreView = null; // Remember stuff we will need down below switch (mLayoutMode) { case LAYOUT_SET_SELECTION: index = mNextSelectedPosition - mFirstPosition; if (index >= 0 && index < childCount) { newSel = getChildAt(index); } break; case LAYOUT_FORCE_TOP: case LAYOUT_FORCE_BOTTOM: case LAYOUT_SPECIFIC: case LAYOUT_SYNC: break; case LAYOUT_MOVE_SELECTION: default: // Remember the previously selected view index = mSelectedPosition - mFirstPosition; if (index >= 0 && index < childCount) { oldSel = getChildAt(index); } // Remember the previous first child oldFirst = getChildAt(0); if (mNextSelectedPosition >= 0) { delta = mNextSelectedPosition - mSelectedPosition; } // Caution: newSel might be null newSel = getChildAt(index + delta); } boolean dataChanged = mDataChanged; if (dataChanged) { handleDataChanged(); } // Handle the empty set by removing all views that are visible // and calling it a day if (mItemCount == 0) { resetList(); invokeOnItemScrollListener(); return; } else if (mItemCount != mAdapter.getCount()) { throw new IllegalStateException("The content of the adapter has changed but " + "ListView did not receive a notification. Make sure the content of " + "your adapter is not modified from a background thread, but only " + "from the UI thread."); } setSelectedPositionInt(mNextSelectedPosition); // Pull all children into the RecycleBin. // These views will be reused if possible final int firstPosition = mFirstPosition; final RecycleBin recycleBin = mRecycler; // reset the focus restoration View focusLayoutRestoreDirectChild = null; // Don't put header or footer views into the Recycler. Those are // already cached in mHeaderViews; if (dataChanged) { for (int i = 0; i < childCount; i++) { recycleBin.addScrapView(getChildAt(i)); if (ViewDebug.TRACE_RECYCLER) { ViewDebug.trace(getChildAt(i), ViewDebug.RecyclerTraceType.MOVE_TO_SCRAP_HEAP, index, i); } } } else { recycleBin.fillActiveViews(childCount, firstPosition); } // take focus back to us temporarily to avoid the eventual // call to clear focus when removing the focused child below // from messing things up when ViewRoot assigns focus back // to someone else final View focusedChild = getFocusedChild(); if (focusedChild != null) { // TODO: in some cases focusedChild.getParent() == null // we can remember the focused view to restore after relayout if the // data hasn't changed, or if the focused position is a header or footer if (!dataChanged || isDirectChildHeaderOrFooter(focusedChild)) { focusLayoutRestoreDirectChild = focusedChild; // remember the specific view that had focus focusLayoutRestoreView = findFocus(); if (focusLayoutRestoreView != null) { // tell it we are going to mess with it focusLayoutRestoreView.onStartTemporaryDetach(); } } requestFocus(); } // Clear out old views //removeAllViewsInLayout(); detachAllViewsFromParent(); switch (mLayoutMode) { case LAYOUT_SET_SELECTION: if (newSel != null) { sel = fillFromSelection(newSel.getLeft(), childrenLeft, childrenRight); } else { sel = fillFromMiddle(childrenLeft, childrenRight); } break; case LAYOUT_SYNC: sel = fillSpecific(mSyncPosition, mSpecificTop); break; case LAYOUT_FORCE_BOTTOM: sel = fillUp(mItemCount - 1, childrenRight); adjustViewsUpOrDown(); break; case LAYOUT_FORCE_TOP: mFirstPosition = 0; sel = fillFromTop(childrenLeft); adjustViewsUpOrDown(); break; case LAYOUT_SPECIFIC: sel = fillSpecific(reconcileSelectedPosition(), mSpecificLeft); break; case LAYOUT_MOVE_SELECTION: sel = moveSelection(oldSel, newSel, delta, childrenLeft, childrenRight); break; default: if (childCount == 0) { if (!mStackFromBottom) { final int position = lookForSelectablePosition(0, true); setSelectedPositionInt(position); sel = fillFromTop(childrenLeft); } else { final int position = lookForSelectablePosition(mItemCount - 1, false); setSelectedPositionInt(position); sel = fillUp(mItemCount - 1, childrenRight); } } else { if (mSelectedPosition >= 0 && mSelectedPosition < mItemCount) { sel = fillSpecific(mSelectedPosition, oldSel == null ? childrenLeft : oldSel.getLeft()); } else if (mFirstPosition < mItemCount) { sel = fillSpecific(mFirstPosition, oldFirst == null ? childrenLeft : oldFirst.getLeft()); } else { sel = fillSpecific(0, childrenLeft); } } break; } // Flush any cached views that did not get reused above recycleBin.scrapActiveViews(); if (sel != null) { // the current selected item should get focus if items // are focusable if (mItemsCanFocus && hasFocus() && !sel.hasFocus()) { final boolean focusWasTaken = (sel == focusLayoutRestoreDirectChild && focusLayoutRestoreView.requestFocus()) || sel.requestFocus(); if (!focusWasTaken) { // selected item didn't take focus, fine, but still want // to make sure something else outside of the selected view // has focus final View focused = getFocusedChild(); if (focused != null) { focused.clearFocus(); } positionSelector(sel); } else { sel.setSelected(false); mSelectorRect.setEmpty(); } } else { positionSelector(sel); } mSelectedTop = sel.getTop(); } else { mSelectedTop = 0; mSelectorRect.setEmpty(); // even if there is not selected position, we may need to restore // focus (i.e. something focusable in touch mode) if (hasFocus() && focusLayoutRestoreView != null) { focusLayoutRestoreView.requestFocus(); } } // tell focus view we are done mucking with it, if it is still in // our view hierarchy. if (focusLayoutRestoreView != null && focusLayoutRestoreView.getWindowToken() != null) { focusLayoutRestoreView.onFinishTemporaryDetach(); } mLayoutMode = LAYOUT_NORMAL; mDataChanged = false; mNeedSync = false; setNextSelectedPositionInt(mSelectedPosition); updateScrollIndicators(); if (mItemCount > 0) { checkSelectionChanged(); } invokeOnItemScrollListener(); } finally { if (!blockLayoutRequests) { mBlockLayoutRequests = false; } } }
From source file:org.bangbang.support.v4.widget.HListView.java
/** * Obtain the view and add it to our list of children. The view can be made * fresh, converted from an unused view, or used as is if it was in the * recycle bin./* w w w . j a v a 2s . co m*/ * * @param position Logical position in the list * @param x Top or bottom edge of the view to add * @param flow If flow is true, align top edge to y. If false, align bottom * edge to y. * @param childrenLeft Left edge where children should be positioned * @param selected Is this position selected? * @return View that was added */ private View makeAndAddView(int position, int x, boolean flow, int childrenLeft, boolean selected) { View child; if (!mDataChanged) { // Try to use an exsiting view for this position child = mRecycler.getActiveView(position); if (child != null) { if (ViewDebug.TRACE_RECYCLER) { ViewDebug.trace(child, ViewDebug.RecyclerTraceType.RECYCLE_FROM_ACTIVE_HEAP, position, getChildCount()); } // Found it -- we're using an existing child // This just needs to be positioned setupChild(child, position, x, flow, childrenLeft, selected, true); return child; } } // Make a new view for this position, or convert an unused view if possible child = obtainView(position); // This needs to be positioned and measured setupChild(child, position, x, flow, childrenLeft, selected, false); return child; }
From source file:com.example.libwidgettv.bak.AbsListView.java
/** * Get a view and have it show the data associated with the specified * position. This is called when we have already discovered that the view is * not available for reuse in the recycle bin. The only choices left are * converting an old view or making a new one. * // ww w.j ava 2 s . c om * @param position * The position to display * @param isScrap * Array of at least 1 boolean, the first entry will become true * if the returned view was taken from the scrap heap, false if * otherwise. * * @return A view displaying the data associated with the specified position */ View obtainView(int position, boolean[] isScrap) { isScrap[0] = false; View scrapView; scrapView = mRecycler.getScrapView(position); View child; if (scrapView != null) { if (ViewDebug.TRACE_RECYCLER) { ViewDebug.trace(scrapView, ViewDebug.RecyclerTraceType.RECYCLE_FROM_SCRAP_HEAP, position, -1); } child = mAdapter.getView(position, scrapView, this); if (ViewDebug.TRACE_RECYCLER) { ViewDebug.trace(child, ViewDebug.RecyclerTraceType.BIND_VIEW, position, getChildCount()); } if (child != scrapView) { mRecycler.addScrapView(scrapView, position); if (mCacheColorHint != 0) { child.setDrawingCacheBackgroundColor(mCacheColorHint); } if (ViewDebug.TRACE_RECYCLER) { ViewDebug.trace(scrapView, ViewDebug.RecyclerTraceType.MOVE_TO_SCRAP_HEAP, position, -1); } } else { isScrap[0] = true; // child.dispatchFinishTemporaryDetach(); child.onFinishTemporaryDetach(); } } else { child = mAdapter.getView(position, null, this); if (mCacheColorHint != 0) { child.setDrawingCacheBackgroundColor(mCacheColorHint); } if (ViewDebug.TRACE_RECYCLER) { ViewDebug.trace(child, ViewDebug.RecyclerTraceType.NEW_VIEW, position, getChildCount()); } } return child; }
From source file:com.huewu.pla.lib.internal.PLAListView.java
/** * Obtain the view and add it to our list of children. The view can be made * fresh, converted from an unused view, or used as is if it was in the * recycle bin.//from w ww . j ava2 s . co m * * @param position Logical position in the list * @param childrenBottomOrTop Top or bottom edge of the view to add * @param flow If flow is true, align top edge to y. If false, align bottom * edge to y. * @param childrenLeft Left edge where children should be positioned * @param selected Is this position selected? * @return View that was added */ @SuppressWarnings("deprecation") private View makeAndAddView(final int position, final int childrenBottomOrTop, final boolean flow, final boolean selected) { View child; int childrenLeft; if (!mDataChanged) { // Try to use an exsiting view for this position child = mRecycler.getActiveView(position); if (child != null) { if (ViewDebug.TRACE_RECYCLER) { ViewDebug.trace(child, ViewDebug.RecyclerTraceType.RECYCLE_FROM_ACTIVE_HEAP, position, getChildCount()); } // Found it -- we're using an existing child // This just needs to be positioned childrenLeft = getItemLeft(position); setupChild(child, position, childrenBottomOrTop, flow, childrenLeft, selected, true); return child; } } // Notify new item is added to view. onItemAddedToList(position, flow); childrenLeft = getItemLeft(position); // Make a new view for this position, or convert an unused view if // possible child = obtainView(position, mIsScrap); // This needs to be positioned and measured setupChild(child, position, childrenBottomOrTop, flow, childrenLeft, selected, mIsScrap[0]); return child; }
From source file:com.example.libwidgettv.bak.AbsListView.java
/** * Track a motion scroll/* w ww. j av a2s . c om*/ * * @param deltaY * Amount to offset mMotionView. This is the accumulated delta * since the motion began. Positive numbers mean the user's * finger is moving down the screen. * @param incrementalDeltaY * Change in deltaY from the previous event. * @return true if we're already at the beginning/end of the list and have * nothing to do. */ boolean trackMotionScroll(int deltaY, int incrementalDeltaY) { final int childCount = getChildCount(); if (childCount == 0) { return true; } final int firstTop = getChildAt(0).getTop(); final int lastBottom = getChildAt(childCount - 1).getBottom(); final Rect listPadding = mListPadding; // "effective padding" In this case is the amount of padding that // affects // how much space should not be filled by items. If we don't clip to // padding // there is no effective padding. int effectivePaddingTop = 0; int effectivePaddingBottom = 0; // if ((mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK) { // effectivePaddingTop = listPadding.top; // effectivePaddingBottom = listPadding.bottom; // } // FIXME account for grid vertical spacing too? final int spaceAbove = effectivePaddingTop - firstTop; final int end = getHeight() - effectivePaddingBottom; final int spaceBelow = lastBottom - end; final int height = getHeight() - getPaddingBottom() - getPaddingTop(); if (deltaY < 0) { deltaY = Math.max(-(height - 1), deltaY); } else { deltaY = Math.min(height - 1, deltaY); } if (incrementalDeltaY < 0) { incrementalDeltaY = Math.max(-(height - 1), incrementalDeltaY); } else { incrementalDeltaY = Math.min(height - 1, incrementalDeltaY); } final int firstPosition = mFirstPosition; // Update our guesses for where the first and last views are if (firstPosition == 0) { mFirstPositionDistanceGuess = firstTop - listPadding.top; } else { mFirstPositionDistanceGuess += incrementalDeltaY; } if (firstPosition + childCount == mItemCount) { mLastPositionDistanceGuess = lastBottom + listPadding.bottom; } else { mLastPositionDistanceGuess += incrementalDeltaY; } final boolean cannotScrollDown = (firstPosition == 0 && firstTop >= listPadding.top && incrementalDeltaY >= 0); final boolean cannotScrollUp = (firstPosition + childCount == mItemCount && lastBottom <= getHeight() - listPadding.bottom && incrementalDeltaY <= 0); if (cannotScrollDown || cannotScrollUp) { return incrementalDeltaY != 0; } final boolean down = incrementalDeltaY < 0; final boolean inTouchMode = isInTouchMode(); if (inTouchMode) { hideSelector(); } final int headerViewsCount = getHeaderViewsCount(); final int footerViewsStart = mItemCount - getFooterViewsCount(); int start = 0; int count = 0; if (down) { int top = -incrementalDeltaY; // if ((mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK) // { // top += listPadding.top; // } for (int i = 0; i < childCount; i++) { final View child = getChildAt(i); if (child.getBottom() >= top) { break; } else { count++; int position = firstPosition + i; if (position >= headerViewsCount && position < footerViewsStart) { mRecycler.addScrapView(child, position); if (ViewDebug.TRACE_RECYCLER) { ViewDebug.trace(child, ViewDebug.RecyclerTraceType.MOVE_TO_SCRAP_HEAP, firstPosition + i, -1); } } } } } else { int bottom = getHeight() - incrementalDeltaY; // if ((mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK) // { // bottom -= listPadding.bottom; // } for (int i = childCount - 1; i >= 0; i--) { final View child = getChildAt(i); if (child.getTop() <= bottom) { break; } else { start = i; count++; int position = firstPosition + i; if (position >= headerViewsCount && position < footerViewsStart) { mRecycler.addScrapView(child, position); if (ViewDebug.TRACE_RECYCLER) { ViewDebug.trace(child, ViewDebug.RecyclerTraceType.MOVE_TO_SCRAP_HEAP, firstPosition + i, -1); } } } } } mMotionViewNewTop = mMotionViewOriginalTop + deltaY; mBlockLayoutRequests = true; if (count > 0) { detachViewsFromParent(start, count); } offsetChildrenTopAndBottom(incrementalDeltaY); if (down) { mFirstPosition += count; } invalidate(); final int absIncrementalDeltaY = Math.abs(incrementalDeltaY); if (spaceAbove < absIncrementalDeltaY || spaceBelow < absIncrementalDeltaY) { fillGap(down); } if (!inTouchMode && mSelectedPosition != INVALID_POSITION) { final int childIndex = mSelectedPosition - mFirstPosition; if (childIndex >= 0 && childIndex < getChildCount()) { positionSelector(mSelectedPosition, getChildAt(childIndex)); } } else if (mSelectorPosition != INVALID_POSITION) { final int childIndex = mSelectorPosition - mFirstPosition; if (childIndex >= 0 && childIndex < getChildCount()) { positionSelector(INVALID_POSITION, getChildAt(childIndex)); } } else { mSelectorRect.setEmpty(); } mBlockLayoutRequests = false; invokeOnItemScrollListener(); awakenScrollBars(); return false; }