Fields Summary |
---|
public static final int | TRANSCRIPT_MODE_DISABLEDDisables the transcript mode. |
public static final int | TRANSCRIPT_MODE_NORMALThe list will automatically scroll to the bottom when a data set change
notification is received and only if the last item is already visible
on screen. |
public static final int | TRANSCRIPT_MODE_ALWAYS_SCROLLThe list will automatically scroll to the bottom, no matter what items
are currently visible. |
static final int | TOUCH_MODE_RESTIndicates that we are not in the middle of a touch gesture |
static final int | TOUCH_MODE_DOWNIndicates we just received the touch event and we are waiting to see if the it is a tap or a
scroll gesture. |
static final int | TOUCH_MODE_TAPIndicates the touch has been recognized as a tap and we are now waiting to see if the touch
is a longpress |
static final int | TOUCH_MODE_DONE_WAITINGIndicates we have waited for everything we can wait for, but the user's finger is still down |
static final int | TOUCH_MODE_SCROLLIndicates the touch gesture is a scroll |
static final int | TOUCH_MODE_FLINGIndicates the view is in the process of being flung |
static final int | TOUCH_MODE_FAST_SCROLLIndicates that the user is currently dragging the fast scroll thumb |
static final int | LAYOUT_NORMALRegular layout - usually an unsolicited layout from the view system |
static final int | LAYOUT_FORCE_TOPShow the first item |
static final int | LAYOUT_SET_SELECTIONForce the selected item to be on somewhere on the screen |
static final int | LAYOUT_FORCE_BOTTOMShow the last item |
static final int | LAYOUT_SPECIFICMake a mSelectedItem appear in a specific location and build the rest of
the views from there. The top is specified by mSpecificTop. |
static final int | LAYOUT_SYNCLayout to sync as a result of a data change. Restore mSyncPosition to have its top
at mSpecificTop |
static final int | LAYOUT_MOVE_SELECTIONLayout as a result of using the navigation keys |
int | mLayoutModeControls how the next layout will happen |
AdapterDataSetObserver | mDataSetObserverShould be used by subclasses to listen to changes in the dataset |
ListAdapter | mAdapterThe adapter containing the data to be displayed by this view |
boolean | mDrawSelectorOnTopIndicates whether the list selector should be drawn on top of the children or behind |
android.graphics.drawable.Drawable | mSelectorThe drawable used to draw the selector |
android.graphics.Rect | mSelectorRectDefines the selector's location and dimension at drawing time |
final RecycleBin | mRecyclerThe data set used to store unused views that should be reused during the next layout
to avoid creating new ones |
int | mSelectionLeftPaddingThe selection's left padding |
int | mSelectionTopPaddingThe selection's top padding |
int | mSelectionRightPaddingThe selection's right padding |
int | mSelectionBottomPaddingThe selection's bottom padding |
android.graphics.Rect | mListPaddingThis view's padding |
int | mWidthMeasureSpecSubclasses must retain their measure spec from onMeasure() into this member |
android.view.View | mScrollUpThe top scroll indicator |
android.view.View | mScrollDownThe down scroll indicator |
boolean | mCachingStartedWhen the view is scrolling, this flag is set to true to indicate subclasses that
the drawing cache was enabled on the children |
int | mMotionPositionThe position of the view that received the down motion event |
int | mMotionViewOriginalTopThe offset to the top of the mMotionPosition view when the down motion event was received |
int | mMotionViewNewTopThe desired offset to the top of the mMotionPosition view after a scroll |
int | mMotionXThe X value associated with the the down motion event |
int | mMotionYThe Y value associated with the the down motion event |
int | mTouchModeOne of TOUCH_MODE_REST, TOUCH_MODE_DOWN, TOUCH_MODE_TAP, TOUCH_MODE_SCROLL, or
TOUCH_MODE_DONE_WAITING |
int | mLastYY value from on the previous motion event (if any) |
int | mMotionCorrectionHow far the finger moved before we started scrolling |
private android.view.VelocityTracker | mVelocityTrackerDetermines speed during touch scrolling |
private FlingRunnable | mFlingRunnableHandles one frame of a fling |
int | mSelectedTopThe offset in pixels form the top of the AdapterView to the top
of the currently selected view. Used to save and restore state. |
boolean | mStackFromBottomIndicates whether the list is stacked from the bottom edge or
the top edge. |
boolean | mScrollingCacheEnabledWhen set to true, the list automatically discards the children's
bitmap cache after scrolling. |
boolean | mFastScrollEnabledWhether or not to enable the fast scroll feature on this list |
private OnScrollListener | mOnScrollListenerOptional callback to notify client when scroll position has changed |
PopupWindow | mPopupKeeps track of our accessory window |
EditText | mTextFilterUsed with type filter window |
private boolean | mSmoothScrollbarEnabledIndicates whether to use pixels-based or position-based scrollbar
properties. |
private boolean | mTextFilterEnabledIndicates that this view supports filtering |
private boolean | mFilteredIndicates that this view is currently displaying a filtered view of the data |
private android.graphics.Rect | mTouchFrameRectangle used for hit testing children |
int | mResurrectToPositionThe position to resurrect the selected position to. |
private android.view.ContextMenu.ContextMenuInfo | mContextMenuInfo |
private static final int | TOUCH_MODE_UNKNOWNUsed to request a layout when we changed touch mode |
private static final int | TOUCH_MODE_ON |
private static final int | TOUCH_MODE_OFF |
private int | mLastTouchMode |
private static final boolean | PROFILE_SCROLLING |
private boolean | mScrollProfilingStarted |
private static final boolean | PROFILE_FLINGING |
private boolean | mFlingProfilingStarted |
private CheckForLongPress | mPendingCheckForLongPressThe last CheckForLongPress runnable we posted, if any |
private Runnable | mPendingCheckForTapThe last CheckForTap runnable we posted, if any |
private CheckForKeyLongPress | mPendingCheckForKeyLongPressThe last CheckForKeyLongPress runnable we posted, if any |
private PerformClick | mPerformClickActs upon click |
private int | mTranscriptModeThis view is in transcript mode -- it shows the bottom of the list when the data
changes |
private int | mCacheColorHintIndicates that this list is always drawn on top of a solid, single-color, opaque
background |
private boolean | mIsChildViewEnabledThe select child's view (from the adapter's getView) is enabled. |
private int | mLastScrollStateThe last scroll state reported to clients through {@link OnScrollListener}. |
private FastScroller | mFastScrollerHelper object that renders and controls the fast scroll thumb. |
private int | mTouchSlop |
private float | mDensityScale |
private android.view.inputmethod.InputConnection | mDefInputConnection |
private android.view.inputmethod.InputConnectionWrapper | mPublicInputConnection |
Methods Summary |
---|
private boolean | acceptFilter()
if (!mTextFilterEnabled || !(getAdapter() instanceof Filterable) ||
((Filterable) getAdapter()).getFilter() == null) {
return false;
}
return true;
|
public void | addTouchables(java.util.ArrayList views){@inheritDoc}
final int count = getChildCount();
final int firstPosition = mFirstPosition;
final ListAdapter adapter = mAdapter;
if (adapter == null) {
return;
}
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (adapter.isEnabled(firstPosition + i)) {
views.add(child);
}
child.addTouchables(views);
}
|
public void | afterTextChanged(android.text.Editable s)For our text watcher that is associated with the text filter. Does
nothing.
|
public void | beforeTextChanged(java.lang.CharSequence s, int start, int count, int after)For our text watcher that is associated with the text filter. Does
nothing.
|
public boolean | checkInputConnectionProxy(android.view.View view)For filtering we proxy an input connection to an internal text editor,
and this allows the proxying to happen.
return view == mTextFilter;
|
protected boolean | checkLayoutParams(ViewGroup.LayoutParams p)
return p instanceof AbsListView.LayoutParams;
|
private void | clearScrollingCache()
if (mCachingStarted) {
setChildrenDrawnWithCacheEnabled(false);
if ((mPersistentDrawingCache & PERSISTENT_SCROLLING_CACHE) == 0) {
setChildrenDrawingCacheEnabled(false);
}
if (!isAlwaysDrawnWithCacheEnabled()) {
invalidate();
}
mCachingStarted = false;
}
|
public void | clearTextFilter()Clear the text filter.
if (mFiltered) {
mTextFilter.setText("");
mFiltered = false;
if (mPopup != null && mPopup.isShowing()) {
dismissPopup();
}
}
|
protected int | computeVerticalScrollExtent()
final int count = getChildCount();
if (count > 0) {
if (mSmoothScrollbarEnabled) {
int extent = count * 100;
View view = getChildAt(0);
final int top = view.getTop();
int height = view.getHeight();
if (height > 0) {
extent += (top * 100) / height;
}
view = getChildAt(count - 1);
final int bottom = view.getBottom();
height = view.getHeight();
if (height > 0) {
extent -= ((bottom - getHeight()) * 100) / height;
}
return extent;
} else {
return 1;
}
}
return 0;
|
protected int | computeVerticalScrollOffset()
final int firstPosition = mFirstPosition;
final int childCount = getChildCount();
if (firstPosition >= 0 && childCount > 0) {
if (mSmoothScrollbarEnabled) {
final View view = getChildAt(0);
final int top = view.getTop();
int height = view.getHeight();
if (height > 0) {
return Math.max(firstPosition * 100 - (top * 100) / height, 0);
}
} else {
int index;
final int count = mItemCount;
if (firstPosition == 0) {
index = 0;
} else if (firstPosition + childCount == count) {
index = count;
} else {
index = firstPosition + childCount / 2;
}
return (int) (firstPosition + childCount * (index / (float) count));
}
}
return 0;
|
protected int | computeVerticalScrollRange()
return mSmoothScrollbarEnabled ? Math.max(mItemCount * 100, 0) : mItemCount;
|
android.view.ContextMenu.ContextMenuInfo | createContextMenuInfo(android.view.View view, int position, long id)Creates the ContextMenuInfo returned from {@link #getContextMenuInfo()}. This
methods knows the view, position and ID of the item that received the
long press.
return new AdapterContextMenuInfo(view, position, id);
|
private void | createScrollingCache()
if (mScrollingCacheEnabled && !mCachingStarted) {
setChildrenDrawnWithCacheEnabled(true);
setChildrenDrawingCacheEnabled(true);
mCachingStarted = true;
}
|
private void | createTextFilter(boolean animateEntrance)Creates the window for the text filter and populates it with an EditText field;
if (mPopup == null) {
Context c = getContext();
PopupWindow p = new PopupWindow(c);
LayoutInflater layoutInflater = (LayoutInflater)
c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mTextFilter = (EditText) layoutInflater.inflate(
com.android.internal.R.layout.typing_filter, null);
// For some reason setting this as the "real" input type changes
// the text view in some way that it doesn't work, and I don't
// want to figure out why this is.
mTextFilter.setRawInputType(EditorInfo.TYPE_CLASS_TEXT
| EditorInfo.TYPE_TEXT_VARIATION_FILTER);
mTextFilter.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI);
mTextFilter.addTextChangedListener(this);
p.setFocusable(false);
p.setTouchable(false);
p.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
p.setContentView(mTextFilter);
p.setWidth(LayoutParams.WRAP_CONTENT);
p.setHeight(LayoutParams.WRAP_CONTENT);
p.setBackgroundDrawable(null);
mPopup = p;
getViewTreeObserver().addOnGlobalLayoutListener(this);
}
if (animateEntrance) {
mPopup.setAnimationStyle(com.android.internal.R.style.Animation_TypingFilter);
} else {
mPopup.setAnimationStyle(com.android.internal.R.style.Animation_TypingFilterRestore);
}
|
void | dismissPopup()Removes the filter window
if (mPopup != null) {
mPopup.dismiss();
}
|
protected void | dispatchDraw(android.graphics.Canvas canvas)
int saveCount = 0;
final boolean clipToPadding = (mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK;
if (clipToPadding) {
saveCount = canvas.save();
final int scrollX = mScrollX;
final int scrollY = mScrollY;
canvas.clipRect(scrollX + mPaddingLeft, scrollY + mPaddingTop,
scrollX + mRight - mLeft - mPaddingRight,
scrollY + mBottom - mTop - mPaddingBottom);
mGroupFlags &= ~CLIP_TO_PADDING_MASK;
}
final boolean drawSelectorOnTop = mDrawSelectorOnTop;
if (!drawSelectorOnTop) {
drawSelector(canvas);
}
super.dispatchDraw(canvas);
if (drawSelectorOnTop) {
drawSelector(canvas);
}
if (clipToPadding) {
canvas.restoreToCount(saveCount);
mGroupFlags |= CLIP_TO_PADDING_MASK;
}
|
protected void | dispatchSetPressed(boolean pressed)
// Don't dispatch setPressed to our children. We call setPressed on ourselves to
// get the selector in the right state, but we don't want to press each child.
|
public void | draw(android.graphics.Canvas canvas)
super.draw(canvas);
if (mFastScroller != null) {
mFastScroller.draw(canvas);
}
|
private void | drawSelector(android.graphics.Canvas canvas)
if (shouldShowSelector() && mSelectorRect != null && !mSelectorRect.isEmpty()) {
final Drawable selector = mSelector;
selector.setBounds(mSelectorRect);
selector.draw(canvas);
}
|
protected void | drawableStateChanged()
super.drawableStateChanged();
if (mSelector != null) {
mSelector.setState(getDrawableState());
}
|
abstract void | fillGap(boolean down)Fills the gap left open by a touch-scroll. During a touch scroll, children that
remain on screen are shifted and the other ones are discarded. The role of this
method is to fill the gap thus created by performing a partial layout in the
empty space.
|
abstract int | findMotionRow(int y)Find the row closest to y. This row will be used as the motion row when scrolling
|
protected ViewGroup.LayoutParams | generateLayoutParams(ViewGroup.LayoutParams p)
return new LayoutParams(p);
|
public android.widget.AbsListView$LayoutParams | generateLayoutParams(android.util.AttributeSet attrs)
return new AbsListView.LayoutParams(getContext(), attrs);
|
protected float | getBottomFadingEdgeStrength()
final int count = getChildCount();
final float fadeEdge = super.getBottomFadingEdgeStrength();
if (count == 0) {
return fadeEdge;
} else {
if (mFirstPosition + count - 1 < mItemCount - 1) {
return 1.0f;
}
final int bottom = getChildAt(count - 1).getBottom();
final int height = getHeight();
final float fadeLength = (float) getVerticalFadingEdgeLength();
return bottom > height - mPaddingBottom ?
(float) (bottom - height + mPaddingBottom) / fadeLength : fadeEdge;
}
|
public int | getCacheColorHint()When set to a non-zero value, the cache color hint indicates that this list is always drawn
on top of a solid, single-color, opaque background
return mCacheColorHint;
|
protected android.view.ContextMenu.ContextMenuInfo | getContextMenuInfo()
return mContextMenuInfo;
|
static int | getDistance(android.graphics.Rect source, android.graphics.Rect dest, int direction)What is the distance between the source and destination rectangles given the direction of
focus navigation between them? The direction basically helps figure out more quickly what is
self evident by the relationship between the rects...
int sX, sY; // source x, y
int dX, dY; // dest x, y
switch (direction) {
case View.FOCUS_RIGHT:
sX = source.right;
sY = source.top + source.height() / 2;
dX = dest.left;
dY = dest.top + dest.height() / 2;
break;
case View.FOCUS_DOWN:
sX = source.left + source.width() / 2;
sY = source.bottom;
dX = dest.left + dest.width() / 2;
dY = dest.top;
break;
case View.FOCUS_LEFT:
sX = source.left;
sY = source.top + source.height() / 2;
dX = dest.right;
dY = dest.top + dest.height() / 2;
break;
case View.FOCUS_UP:
sX = source.left + source.width() / 2;
sY = source.top;
dX = dest.left + dest.width() / 2;
dY = dest.bottom;
break;
default:
throw new IllegalArgumentException("direction must be one of "
+ "{FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT}.");
}
int deltaX = dX - sX;
int deltaY = dY - sY;
return deltaY * deltaY + deltaX * deltaX;
|
public void | getFocusedRect(android.graphics.Rect r)
View view = getSelectedView();
if (view != null) {
// the focused rectangle of the selected view offset into the
// coordinate space of this view.
view.getFocusedRect(r);
offsetDescendantRectToMyCoords(view, r);
} else {
// otherwise, just the norm
super.getFocusedRect(r);
}
|
int | getFooterViewsCount()Returns the number of footer views in the list. Footer views are special views
at the bottom of the list that should not be recycled during a layout.
return 0;
|
int | getHeaderViewsCount()Returns the number of header views in the list. Header views are special views
at the top of the list that should not be recycled during a layout.
return 0;
|
public int | getListPaddingBottom()List padding is the maximum of the normal view's padding and the padding of the selector.
return mListPadding.bottom;
|
public int | getListPaddingLeft()List padding is the maximum of the normal view's padding and the padding of the selector.
return mListPadding.left;
|
public int | getListPaddingRight()List padding is the maximum of the normal view's padding and the padding of the selector.
return mListPadding.right;
|
public int | getListPaddingTop()List padding is the maximum of the normal view's padding and the padding of the selector.
return mListPadding.top;
|
public android.view.View | getSelectedView()
if (mItemCount > 0 && mSelectedPosition >= 0) {
return getChildAt(mSelectedPosition - mFirstPosition);
} else {
return null;
}
|
public android.graphics.drawable.Drawable | getSelector()Returns the selector {@link android.graphics.drawable.Drawable} that is used to draw the
selection in the list.
return mSelector;
|
public int | getSolidColor()
return mCacheColorHint;
|
public java.lang.CharSequence | getTextFilter()Returns the list's text filter, if available.
if (mTextFilterEnabled && mTextFilter != null) {
return mTextFilter.getText();
}
return null;
|
protected float | getTopFadingEdgeStrength()
final int count = getChildCount();
final float fadeEdge = super.getTopFadingEdgeStrength();
if (count == 0) {
return fadeEdge;
} else {
if (mFirstPosition > 0) {
return 1.0f;
}
final int top = getChildAt(0).getTop();
final float fadeLength = (float) getVerticalFadingEdgeLength();
return top < mPaddingTop ? (float) -(top - mPaddingTop) / fadeLength : fadeEdge;
}
|
public int | getTranscriptMode()Returns the current transcript mode.
return mTranscriptMode;
|
protected void | handleDataChanged()
int count = mItemCount;
if (count > 0) {
int newPos;
int selectablePos;
// Find the row we are supposed to sync to
if (mNeedSync) {
// Update this first, since setNextSelectedPositionInt inspects it
mNeedSync = false;
if (mTranscriptMode == TRANSCRIPT_MODE_ALWAYS_SCROLL ||
(mTranscriptMode == TRANSCRIPT_MODE_NORMAL &&
mFirstPosition + getChildCount() >= mOldItemCount)) {
mLayoutMode = LAYOUT_FORCE_BOTTOM;
return;
}
switch (mSyncMode) {
case SYNC_SELECTED_POSITION:
if (isInTouchMode()) {
// We saved our state when not in touch mode. (We know this because
// mSyncMode is SYNC_SELECTED_POSITION.) Now we are trying to
// restore in touch mode. Just leave mSyncPosition as it is (possibly
// adjusting if the available range changed) and return.
mLayoutMode = LAYOUT_SYNC;
mSyncPosition = Math.min(Math.max(0, mSyncPosition), count - 1);
return;
} else {
// See if we can find a position in the new data with the same
// id as the old selection. This will change mSyncPosition.
newPos = findSyncPosition();
if (newPos >= 0) {
// Found it. Now verify that new selection is still selectable
selectablePos = lookForSelectablePosition(newPos, true);
if (selectablePos == newPos) {
// Same row id is selected
mSyncPosition = newPos;
if (mSyncHeight == getHeight()) {
// If we are at the same height as when we saved state, try
// to restore the scroll position too.
mLayoutMode = LAYOUT_SYNC;
} else {
// We are not the same height as when the selection was saved, so
// don't try to restore the exact position
mLayoutMode = LAYOUT_SET_SELECTION;
}
// Restore selection
setNextSelectedPositionInt(newPos);
return;
}
}
}
break;
case SYNC_FIRST_POSITION:
// Leave mSyncPosition as it is -- just pin to available range
mLayoutMode = LAYOUT_SYNC;
mSyncPosition = Math.min(Math.max(0, mSyncPosition), count - 1);
return;
}
}
if (!isInTouchMode()) {
// We couldn't find matching data -- try to use the same position
newPos = getSelectedItemPosition();
// Pin position to the available range
if (newPos >= count) {
newPos = count - 1;
}
if (newPos < 0) {
newPos = 0;
}
// Make sure we select something selectable -- first look down
selectablePos = lookForSelectablePosition(newPos, true);
if (selectablePos >= 0) {
setNextSelectedPositionInt(selectablePos);
return;
} else {
// Looking down didn't work -- try looking up
selectablePos = lookForSelectablePosition(newPos, false);
if (selectablePos >= 0) {
setNextSelectedPositionInt(selectablePos);
return;
}
}
} else {
// We already know where we want to resurrect the selection
if (mResurrectToPosition >= 0) {
return;
}
}
}
// Nothing is selected. Give up and reset everything.
mLayoutMode = mStackFromBottom ? LAYOUT_FORCE_BOTTOM : LAYOUT_FORCE_TOP;
mSelectedPosition = INVALID_POSITION;
mSelectedRowId = INVALID_ROW_ID;
mNextSelectedPosition = INVALID_POSITION;
mNextSelectedRowId = INVALID_ROW_ID;
mNeedSync = false;
checkSelectionChanged();
|
public boolean | hasTextFilter()Returns if the ListView currently has a text filter.
return mFiltered;
|
void | hideSelector()
if (mSelectedPosition != INVALID_POSITION) {
mResurrectToPosition = mSelectedPosition;
if (mNextSelectedPosition >= 0 && mNextSelectedPosition != mSelectedPosition) {
mResurrectToPosition = mNextSelectedPosition;
}
setSelectedPositionInt(INVALID_POSITION);
setNextSelectedPositionInt(INVALID_POSITION);
mSelectedTop = 0;
mSelectorRect.setEmpty();
}
|
private void | initAbsListView()
// Setting focusable in touch mode will set the focusable property to true
setFocusableInTouchMode(true);
setWillNotDraw(false);
setAlwaysDrawnWithCacheEnabled(false);
setScrollingCacheEnabled(true);
mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
mDensityScale = getContext().getResources().getDisplayMetrics().density;
|
public void | invalidateViews()Causes all the views to be rebuilt and redrawn.
mDataChanged = true;
rememberSyncState();
requestLayout();
invalidate();
|
void | invokeOnItemScrollListener()Notify our scroll listener (if there is one) of a change in scroll state
if (mFastScroller != null) {
mFastScroller.onScroll(this, mFirstPosition, getChildCount(), mItemCount);
}
if (mOnScrollListener != null) {
mOnScrollListener.onScroll(this, mFirstPosition, getChildCount(), mItemCount);
}
|
public boolean | isFastScrollEnabled()Returns the current state of the fast scroll feature.
return mFastScrollEnabled;
|
protected boolean | isInFilterMode()
return mFiltered;
|
public boolean | isScrollingCacheEnabled()Indicates whether the children's drawing cache is used during a scroll.
By default, the drawing cache is enabled but this will consume more memory.
return mScrollingCacheEnabled;
|
public boolean | isSmoothScrollbarEnabled()Returns the current state of the fast scroll feature.
return mSmoothScrollbarEnabled;
|
public boolean | isStackFromBottom()Indicates whether the content of this view is pinned to, or stacked from,
the bottom edge.
return mStackFromBottom;
|
public boolean | isTextFilterEnabled()Indicates whether type filtering is enabled for this view
return mTextFilterEnabled;
|
protected boolean | isVerticalScrollBarHidden()If fast scroll is visible, then don't draw the vertical scrollbar.
return mFastScroller != null && mFastScroller.isVisible();
|
void | keyPressed()Sets the selector state to "pressed" and posts a CheckForKeyLongPress to see if
this is a long press.
Drawable selector = mSelector;
Rect selectorRect = mSelectorRect;
if (selector != null && (isFocused() || touchModeDrawsInPressedState())
&& selectorRect != null && !selectorRect.isEmpty()) {
final View v = getChildAt(mSelectedPosition - mFirstPosition);
if (v != null) {
if (v.hasFocusable()) return;
v.setPressed(true);
}
setPressed(true);
final boolean longClickable = isLongClickable();
Drawable d = selector.getCurrent();
if (d != null && d instanceof TransitionDrawable) {
if (longClickable) {
((TransitionDrawable) d).startTransition(ViewConfiguration
.getLongPressTimeout());
} else {
((TransitionDrawable) d).resetTransition();
}
}
if (longClickable && !mDataChanged) {
if (mPendingCheckForKeyLongPress == null) {
mPendingCheckForKeyLongPress = new CheckForKeyLongPress();
}
mPendingCheckForKeyLongPress.rememberWindowAttachCount();
postDelayed(mPendingCheckForKeyLongPress, ViewConfiguration.getLongPressTimeout());
}
}
|
protected void | layoutChildren()
|
android.view.View | obtainView(int position)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.
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);
if (mCacheColorHint != 0) {
child.setDrawingCacheBackgroundColor(mCacheColorHint);
}
if (ViewDebug.TRACE_RECYCLER) {
ViewDebug.trace(scrapView, ViewDebug.RecyclerTraceType.MOVE_TO_SCRAP_HEAP,
position, -1);
}
}
} 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;
|
protected void | onAttachedToWindow()
super.onAttachedToWindow();
final ViewTreeObserver treeObserver = getViewTreeObserver();
if (treeObserver != null) {
treeObserver.addOnTouchModeChangeListener(this);
}
|
protected int[] | onCreateDrawableState(int extraSpace)
// If the child view is enabled then do the default behavior.
if (mIsChildViewEnabled) {
// Common case
return super.onCreateDrawableState(extraSpace);
}
// The selector uses this View's drawable state. The selected child view
// is disabled, so we need to remove the enabled state from the drawable
// states.
final int enabledState = ENABLED_STATE_SET[0];
// If we don't have any extra space, it will return one of the static state arrays,
// and clearing the enabled state on those arrays is a bad thing! If we specify
// we need extra space, it will create+copy into a new array that safely mutable.
int[] state = super.onCreateDrawableState(extraSpace + 1);
int enabledPos = -1;
for (int i = state.length - 1; i >= 0; i--) {
if (state[i] == enabledState) {
enabledPos = i;
break;
}
}
// Remove the enabled state
if (enabledPos >= 0) {
System.arraycopy(state, enabledPos + 1, state, enabledPos,
state.length - enabledPos - 1);
}
return state;
|
public android.view.inputmethod.InputConnection | onCreateInputConnection(android.view.inputmethod.EditorInfo outAttrs)Return an InputConnection for editing of the filter text.
if (isTextFilterEnabled()) {
// XXX we need to have the text filter created, so we can get an
// InputConnection to proxy to. Unfortunately this means we pretty
// much need to make it as soon as a list view gets focus.
createTextFilter(false);
if (mPublicInputConnection == null) {
mDefInputConnection = new BaseInputConnection(this, false);
mPublicInputConnection = new InputConnectionWrapper(
mTextFilter.onCreateInputConnection(outAttrs), true) {
@Override
public boolean reportFullscreenMode(boolean enabled) {
// Use our own input connection, since it is
// the "real" one the IME is talking with.
return mDefInputConnection.reportFullscreenMode(enabled);
}
@Override
public boolean performEditorAction(int editorAction) {
// The editor is off in its own window; we need to be
// the one that does this.
if (editorAction == EditorInfo.IME_ACTION_DONE) {
InputMethodManager imm = (InputMethodManager)
getContext().getSystemService(
Context.INPUT_METHOD_SERVICE);
if (imm != null) {
imm.hideSoftInputFromWindow(getWindowToken(), 0);
}
return true;
}
return false;
}
@Override
public boolean sendKeyEvent(KeyEvent event) {
// Use our own input connection, since the filter
// text view may not be shown in a window so has
// no ViewRoot to dispatch events with.
return mDefInputConnection.sendKeyEvent(event);
}
};
}
outAttrs.inputType = EditorInfo.TYPE_CLASS_TEXT
| EditorInfo.TYPE_TEXT_VARIATION_FILTER;
outAttrs.imeOptions = EditorInfo.IME_ACTION_DONE;
return mPublicInputConnection;
}
return null;
|
protected void | onDetachedFromWindow()
super.onDetachedFromWindow();
final ViewTreeObserver treeObserver = getViewTreeObserver();
if (treeObserver != null) {
treeObserver.removeOnTouchModeChangeListener(this);
}
|
public void | onFilterComplete(int count)
if (mSelectedPosition < 0 && count > 0) {
mResurrectToPosition = INVALID_POSITION;
resurrectSelection();
}
|
protected void | onFocusChanged(boolean gainFocus, int direction, android.graphics.Rect previouslyFocusedRect)
super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
if (gainFocus && mSelectedPosition < 0 && !isInTouchMode()) {
resurrectSelection();
}
|
public void | onGlobalLayout()
if (isShown()) {
// Show the popup if we are filtered
if (mFiltered && mPopup != null && !mPopup.isShowing()) {
showPopup();
}
} else {
// Hide the popup when we are no longer visible
if (mPopup.isShowing()) {
dismissPopup();
}
}
|
public boolean | onInterceptTouchEvent(android.view.MotionEvent ev)
int action = ev.getAction();
int x = (int) ev.getX();
int y = (int) ev.getY();
View v;
if (mFastScroller != null) {
boolean intercepted = mFastScroller.onInterceptTouchEvent(ev);
if (intercepted) {
return true;
}
}
switch (action) {
case MotionEvent.ACTION_DOWN: {
int motionPosition = findMotionRow(y);
if (mTouchMode != TOUCH_MODE_FLING && motionPosition >= 0) {
// User clicked on an actual view (and was not stopping a fling).
// Remember where the motion event started
v = getChildAt(motionPosition - mFirstPosition);
mMotionViewOriginalTop = v.getTop();
mMotionX = x;
mMotionY = y;
mMotionPosition = motionPosition;
mTouchMode = TOUCH_MODE_DOWN;
clearScrollingCache();
}
mLastY = Integer.MIN_VALUE;
break;
}
case MotionEvent.ACTION_MOVE: {
switch (mTouchMode) {
case TOUCH_MODE_DOWN:
if (startScrollIfNeeded(y - mMotionY)) {
return true;
}
break;
}
break;
}
case MotionEvent.ACTION_UP: {
mTouchMode = TOUCH_MODE_REST;
reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
break;
}
}
return false;
|
public boolean | onKeyUp(int keyCode, android.view.KeyEvent event)
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_ENTER:
if (isPressed() && mSelectedPosition >= 0 && mAdapter != null &&
mSelectedPosition < mAdapter.getCount()) {
final View view = getChildAt(mSelectedPosition - mFirstPosition);
performItemClick(view, mSelectedPosition, mSelectedRowId);
setPressed(false);
if (view != null) view.setPressed(false);
return true;
}
}
return super.onKeyUp(keyCode, event);
|
protected void | onLayout(boolean changed, int l, int t, int r, int b)
super.onLayout(changed, l, t, r, b);
mInLayout = true;
layoutChildren();
mInLayout = false;
|
protected void | onMeasure(int widthMeasureSpec, int heightMeasureSpec)
if (mSelector == null) {
useDefaultSelector();
}
final Rect listPadding = mListPadding;
listPadding.left = mSelectionLeftPadding + mPaddingLeft;
listPadding.top = mSelectionTopPadding + mPaddingTop;
listPadding.right = mSelectionRightPadding + mPaddingRight;
listPadding.bottom = mSelectionBottomPadding + mPaddingBottom;
|
public void | onRestoreInstanceState(android.os.Parcelable state)
SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
mDataChanged = true;
mSyncHeight = ss.height;
if (ss.selectedId >= 0) {
mNeedSync = true;
mSyncRowId = ss.selectedId;
mSyncPosition = ss.position;
mSpecificTop = ss.viewTop;
mSyncMode = SYNC_SELECTED_POSITION;
} else if (ss.firstId >= 0) {
setSelectedPositionInt(INVALID_POSITION);
// Do this before setting mNeedSync since setNextSelectedPosition looks at mNeedSync
setNextSelectedPositionInt(INVALID_POSITION);
mNeedSync = true;
mSyncRowId = ss.firstId;
mSyncPosition = ss.position;
mSpecificTop = ss.viewTop;
mSyncMode = SYNC_FIRST_POSITION;
}
setFilterText(ss.filter);
requestLayout();
|
public android.os.Parcelable | onSaveInstanceState()
/*
* This doesn't really make sense as the place to dismiss the
* popup, 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.
*/
dismissPopup();
Parcelable superState = super.onSaveInstanceState();
SavedState ss = new SavedState(superState);
boolean haveChildren = getChildCount() > 0;
long selectedId = getSelectedItemId();
ss.selectedId = selectedId;
ss.height = getHeight();
if (selectedId >= 0) {
// Remember the selection
ss.viewTop = mSelectedTop;
ss.position = getSelectedItemPosition();
ss.firstId = INVALID_POSITION;
} else {
if (haveChildren) {
// Remember the position of the first child
View v = getChildAt(0);
ss.viewTop = v.getTop();
ss.position = mFirstPosition;
ss.firstId = mAdapter.getItemId(mFirstPosition);
} else {
ss.viewTop = 0;
ss.firstId = INVALID_POSITION;
ss.position = 0;
}
}
ss.filter = null;
if (mFiltered) {
final EditText textFilter = mTextFilter;
if (textFilter != null) {
Editable filterText = textFilter.getText();
if (filterText != null) {
ss.filter = filterText.toString();
}
}
}
return ss;
|
protected void | onSizeChanged(int w, int h, int oldw, int oldh)
if (getChildCount() > 0) {
mDataChanged = true;
rememberSyncState();
}
if (mFastScroller != null) {
mFastScroller.onSizeChanged(w, h, oldw, oldh);
}
|
public void | onTextChanged(java.lang.CharSequence s, int start, int before, int count)For our text watcher that is associated with the text filter. Performs
the actual filtering as the text changes, and takes care of hiding and
showing the popup displaying the currently entered filter text.
if (mPopup != null && isTextFilterEnabled()) {
int length = s.length();
boolean showing = mPopup.isShowing();
if (!showing && length > 0) {
// Show the filter popup if necessary
showPopup();
mFiltered = true;
} else if (showing && length == 0) {
// Remove the filter popup if the user has cleared all text
dismissPopup();
mFiltered = false;
}
if (mAdapter instanceof Filterable) {
Filter f = ((Filterable) mAdapter).getFilter();
// Filter should not be null when we reach this part
if (f != null) {
f.filter(s, this);
} else {
throw new IllegalStateException("You cannot call onTextChanged with a non "
+ "filterable adapter");
}
}
}
|
public boolean | onTouchEvent(android.view.MotionEvent ev)
if (mFastScroller != null) {
boolean intercepted = mFastScroller.onTouchEvent(ev);
if (intercepted) {
return true;
}
}
final int action = ev.getAction();
final int x = (int) ev.getX();
final int y = (int) ev.getY();
View v;
int deltaY;
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(ev);
switch (action) {
case MotionEvent.ACTION_DOWN: {
int motionPosition = pointToPosition(x, y);
if (!mDataChanged) {
if ((mTouchMode != TOUCH_MODE_FLING) && (motionPosition >= 0)
&& (getAdapter().isEnabled(motionPosition))) {
// User clicked on an actual view (and was not stopping a fling). It might be a
// click or a scroll. Assume it is a click until proven otherwise
mTouchMode = TOUCH_MODE_DOWN;
// FIXME Debounce
if (mPendingCheckForTap == null) {
mPendingCheckForTap = new CheckForTap();
}
postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
} else {
if (ev.getEdgeFlags() != 0 && motionPosition < 0) {
// If we couldn't find a view to click on, but the down event was touching
// the edge, we will bail out and try again. This allows the edge correcting
// code in ViewRoot to try to find a nearby view to select
return false;
}
// User clicked on whitespace, or stopped a fling. It is a scroll.
createScrollingCache();
mTouchMode = TOUCH_MODE_SCROLL;
motionPosition = findMotionRow(y);
reportScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
}
}
if (motionPosition >= 0) {
// Remember where the motion event started
v = getChildAt(motionPosition - mFirstPosition);
mMotionViewOriginalTop = v.getTop();
mMotionX = x;
mMotionY = y;
mMotionPosition = motionPosition;
}
mLastY = Integer.MIN_VALUE;
break;
}
case MotionEvent.ACTION_MOVE: {
deltaY = y - mMotionY;
switch (mTouchMode) {
case TOUCH_MODE_DOWN:
case TOUCH_MODE_TAP:
case TOUCH_MODE_DONE_WAITING:
// Check if we have moved far enough that it looks more like a
// scroll than a tap
startScrollIfNeeded(deltaY);
break;
case TOUCH_MODE_SCROLL:
if (PROFILE_SCROLLING) {
if (!mScrollProfilingStarted) {
Debug.startMethodTracing("AbsListViewScroll");
mScrollProfilingStarted = true;
}
}
if (y != mLastY) {
deltaY -= mMotionCorrection;
int incrementalDeltaY = mLastY != Integer.MIN_VALUE ? y - mLastY : deltaY;
trackMotionScroll(deltaY, incrementalDeltaY);
// Check to see if we have bumped into the scroll limit
View motionView = this.getChildAt(mMotionPosition - mFirstPosition);
if (motionView != null) {
// Check if the top of the motion view is where it is
// supposed to be
if (motionView.getTop() != mMotionViewNewTop) {
// We did not scroll the full amount. Treat this essentially like the
// start of a new touch scroll
final int motionPosition = findMotionRow(y);
mMotionCorrection = 0;
motionView = getChildAt(motionPosition - mFirstPosition);
mMotionViewOriginalTop = motionView.getTop();
mMotionY = y;
mMotionPosition = motionPosition;
}
}
mLastY = y;
}
break;
}
break;
}
case MotionEvent.ACTION_UP: {
switch (mTouchMode) {
case TOUCH_MODE_DOWN:
case TOUCH_MODE_TAP:
case TOUCH_MODE_DONE_WAITING:
final int motionPosition = mMotionPosition;
final View child = getChildAt(motionPosition - mFirstPosition);
if (child != null && !child.hasFocusable()) {
if (mTouchMode != TOUCH_MODE_DOWN) {
child.setPressed(false);
}
if (mPerformClick == null) {
mPerformClick = new PerformClick();
}
final AbsListView.PerformClick performClick = mPerformClick;
performClick.mChild = child;
performClick.mClickMotionPosition = motionPosition;
performClick.rememberWindowAttachCount();
mResurrectToPosition = motionPosition;
if (mTouchMode == TOUCH_MODE_DOWN || mTouchMode == TOUCH_MODE_TAP) {
final Handler handler = getHandler();
if (handler != null) {
handler.removeCallbacks(mTouchMode == TOUCH_MODE_DOWN ?
mPendingCheckForTap : mPendingCheckForLongPress);
}
mLayoutMode = LAYOUT_NORMAL;
mTouchMode = TOUCH_MODE_TAP;
if (!mDataChanged) {
setSelectedPositionInt(mMotionPosition);
layoutChildren();
child.setPressed(true);
positionSelector(child);
setPressed(true);
if (mSelector != null) {
Drawable d = mSelector.getCurrent();
if (d != null && d instanceof TransitionDrawable) {
((TransitionDrawable)d).resetTransition();
}
}
postDelayed(new Runnable() {
public void run() {
child.setPressed(false);
setPressed(false);
if (!mDataChanged) {
post(performClick);
}
mTouchMode = TOUCH_MODE_REST;
}
}, ViewConfiguration.getPressedStateDuration());
}
return true;
} else {
if (!mDataChanged) {
post(performClick);
}
}
}
mTouchMode = TOUCH_MODE_REST;
break;
case TOUCH_MODE_SCROLL:
final VelocityTracker velocityTracker = mVelocityTracker;
velocityTracker.computeCurrentVelocity(1000);
int initialVelocity = (int)velocityTracker.getYVelocity();
if ((Math.abs(initialVelocity) >
ViewConfiguration.get(mContext).getScaledMinimumFlingVelocity()) &&
(getChildCount() > 0)) {
if (mFlingRunnable == null) {
mFlingRunnable = new FlingRunnable();
}
reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);
mFlingRunnable.start(-initialVelocity);
} else {
mTouchMode = TOUCH_MODE_REST;
reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
}
}
setPressed(false);
// Need to redraw since we probably aren't drawing the selector anymore
invalidate();
final Handler handler = getHandler();
if (handler != null) {
handler.removeCallbacks(mPendingCheckForLongPress);
}
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
mVelocityTracker = null;
}
if (PROFILE_SCROLLING) {
if (mScrollProfilingStarted) {
Debug.stopMethodTracing();
mScrollProfilingStarted = false;
}
}
break;
}
case MotionEvent.ACTION_CANCEL: {
mTouchMode = TOUCH_MODE_REST;
setPressed(false);
View motionView = this.getChildAt(mMotionPosition - mFirstPosition);
if (motionView != null) {
motionView.setPressed(false);
}
clearScrollingCache();
final Handler handler = getHandler();
if (handler != null) {
handler.removeCallbacks(mPendingCheckForLongPress);
}
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
mVelocityTracker = null;
}
}
}
return true;
|
public void | onTouchModeChanged(boolean isInTouchMode)
if (isInTouchMode) {
// Get rid of the selection when we enter touch mode
hideSelector();
// Layout, but only if we already have done so previously.
// (Otherwise may clobber a LAYOUT_SYNC layout that was requested to restore
// state.)
if (getHeight() > 0 && getChildCount() > 0) {
// We do not lose focus initiating a touch (since AbsListView is focusable in
// touch mode). Force an initial layout to get rid of the selection.
mLayoutMode = LAYOUT_NORMAL;
layoutChildren();
}
}
|
public void | onWindowFocusChanged(boolean hasWindowFocus)
super.onWindowFocusChanged(hasWindowFocus);
final int touchMode = isInTouchMode() ? TOUCH_MODE_ON : TOUCH_MODE_OFF;
if (!hasWindowFocus) {
setChildrenDrawingCacheEnabled(false);
removeCallbacks(mFlingRunnable);
// Always hide the type filter
dismissPopup();
if (touchMode == TOUCH_MODE_OFF) {
// Remember the last selected element
mResurrectToPosition = mSelectedPosition;
}
} else {
if (mFiltered) {
// Show the type filter only if a filter is in effect
showPopup();
}
// If we changed touch mode since the last time we had focus
if (touchMode != mLastTouchMode && mLastTouchMode != TOUCH_MODE_UNKNOWN) {
// If we come back in trackball mode, we bring the selection back
if (touchMode == TOUCH_MODE_OFF) {
// This will trigger a layout
resurrectSelection();
// If we come back in touch mode, then we want to hide the selector
} else {
hideSelector();
mLayoutMode = LAYOUT_NORMAL;
layoutChildren();
}
}
}
mLastTouchMode = touchMode;
|
private boolean | performLongPress(android.view.View child, int longPressPosition, long longPressId)
boolean handled = false;
if (mOnItemLongClickListener != null) {
handled = mOnItemLongClickListener.onItemLongClick(AbsListView.this, child,
longPressPosition, longPressId);
}
if (!handled) {
mContextMenuInfo = createContextMenuInfo(child, longPressPosition, longPressId);
handled = super.showContextMenuForChild(AbsListView.this);
}
if (handled) {
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
}
return handled;
|
public int | pointToPosition(int x, int y)Maps a point to a position in the list.
Rect frame = mTouchFrame;
if (frame == null) {
mTouchFrame = new Rect();
frame = mTouchFrame;
}
final int count = getChildCount();
for (int i = count - 1; i >= 0; i--) {
final View child = getChildAt(i);
if (child.getVisibility() == View.VISIBLE) {
child.getHitRect(frame);
if (frame.contains(x, y)) {
return mFirstPosition + i;
}
}
}
return INVALID_POSITION;
|
public long | pointToRowId(int x, int y)Maps a point to a the rowId of the item which intersects that point.
int position = pointToPosition(x, y);
if (position >= 0) {
return mAdapter.getItemId(position);
}
return INVALID_ROW_ID;
|
private void | positionPopup()
int screenHeight = getResources().getDisplayMetrics().heightPixels;
final int[] xy = new int[2];
getLocationOnScreen(xy);
// TODO: The 20 below should come from the theme and be expressed in dip
// TODO: And the gravity should be defined in the theme as well
final int bottomGap = screenHeight - xy[1] - getHeight() + (int) (mDensityScale * 20);
if (!mPopup.isShowing()) {
mPopup.showAtLocation(this, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL,
xy[0], bottomGap);
} else {
mPopup.update(xy[0], bottomGap, -1, -1);
}
|
void | positionSelector(android.view.View sel)
final Rect selectorRect = mSelectorRect;
selectorRect.set(sel.getLeft(), sel.getTop(), sel.getRight(), sel.getBottom());
positionSelector(selectorRect.left, selectorRect.top, selectorRect.right,
selectorRect.bottom);
final boolean isChildViewEnabled = mIsChildViewEnabled;
if (sel.isEnabled() != isChildViewEnabled) {
mIsChildViewEnabled = !isChildViewEnabled;
refreshDrawableState();
}
|
private void | positionSelector(int l, int t, int r, int b)
mSelectorRect.set(l - mSelectionLeftPadding, t - mSelectionTopPadding, r
+ mSelectionRightPadding, b + mSelectionBottomPadding);
|
public void | reclaimViews(java.util.List views)Move all views (excluding headers and footers) held by this AbsListView into the supplied
List. This includes views displayed on the screen as well as views stored in AbsListView's
internal view recycler.
int childCount = getChildCount();
RecyclerListener listener = mRecycler.mRecyclerListener;
// Reclaim views on screen
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
AbsListView.LayoutParams lp = (AbsListView.LayoutParams)child.getLayoutParams();
// Don't reclaim header or footer views, or views that should be ignored
if (lp != null && mRecycler.shouldRecycleViewType(lp.viewType)) {
views.add(child);
if (listener != null) {
// Pretend they went through the scrap heap
listener.onMovedToScrapHeap(child);
}
}
}
mRecycler.reclaimScrapViews(views);
removeAllViewsInLayout();
|
int | reconcileSelectedPosition()
int position = mSelectedPosition;
if (position < 0) {
position = mResurrectToPosition;
}
position = Math.max(0, position);
position = Math.min(position, mItemCount - 1);
return position;
|
void | reportScrollStateChange(int newState)Fires an "on scroll state changed" event to the registered
{@link android.widget.AbsListView.OnScrollListener}, if any. The state change
is fired only if the specified state is different from the previously known state.
if (newState != mLastScrollState) {
if (mOnScrollListener != null) {
mOnScrollListener.onScrollStateChanged(this, newState);
mLastScrollState = newState;
}
}
|
public void | requestLayout()
if (!mBlockLayoutRequests && !mInLayout) {
super.requestLayout();
}
|
void | requestLayoutIfNecessary()
if (getChildCount() > 0) {
resetList();
requestLayout();
invalidate();
}
|
void | resetList()The list is empty. Clear everything out.
removeAllViewsInLayout();
mFirstPosition = 0;
mDataChanged = false;
mNeedSync = false;
mOldSelectedPosition = INVALID_POSITION;
mOldSelectedRowId = INVALID_ROW_ID;
setSelectedPositionInt(INVALID_POSITION);
setNextSelectedPositionInt(INVALID_POSITION);
mSelectedTop = 0;
mSelectorRect.setEmpty();
invalidate();
|
void | resetListAndClearViews()The list is empty and we need to change the layout, so *really* clear everything out.
rememberSyncState();
removeAllViewsInLayout();
mRecycler.clear();
mRecycler.setViewTypeCount(mAdapter.getViewTypeCount());
requestLayout();
|
boolean | resurrectSelection()Attempt to bring the selection back if the user is switching from touch
to trackball mode
final int childCount = getChildCount();
if (childCount <= 0) {
return false;
}
int selectedTop = 0;
int selectedPos;
int childrenTop = mListPadding.top;
int childrenBottom = mBottom - mTop - mListPadding.bottom;
final int firstPosition = mFirstPosition;
final int toPosition = mResurrectToPosition;
boolean down = true;
if (toPosition >= firstPosition && toPosition < firstPosition + childCount) {
selectedPos = toPosition;
final View selected = getChildAt(selectedPos - mFirstPosition);
selectedTop = selected.getTop();
int selectedBottom = selected.getBottom();
// We are scrolled, don't get in the fade
if (selectedTop < childrenTop) {
selectedTop = childrenTop + getVerticalFadingEdgeLength();
} else if (selectedBottom > childrenBottom) {
selectedTop = childrenBottom - selected.getMeasuredHeight()
- getVerticalFadingEdgeLength();
}
} else {
if (toPosition < firstPosition) {
// Default to selecting whatever is first
selectedPos = firstPosition;
for (int i = 0; i < childCount; i++) {
final View v = getChildAt(i);
final int top = v.getTop();
if (i == 0) {
// Remember the position of the first item
selectedTop = top;
// See if we are scrolled at all
if (firstPosition > 0 || top < childrenTop) {
// If we are scrolled, don't select anything that is
// in the fade region
childrenTop += getVerticalFadingEdgeLength();
}
}
if (top >= childrenTop) {
// Found a view whose top is fully visisble
selectedPos = firstPosition + i;
selectedTop = top;
break;
}
}
} else {
final int itemCount = mItemCount;
down = false;
selectedPos = firstPosition + childCount - 1;
for (int i = childCount - 1; i >= 0; i--) {
final View v = getChildAt(i);
final int top = v.getTop();
final int bottom = v.getBottom();
if (i == childCount - 1) {
selectedTop = top;
if (firstPosition + childCount < itemCount || bottom > childrenBottom) {
childrenBottom -= getVerticalFadingEdgeLength();
}
}
if (bottom <= childrenBottom) {
selectedPos = firstPosition + i;
selectedTop = top;
break;
}
}
}
}
mResurrectToPosition = INVALID_POSITION;
removeCallbacks(mFlingRunnable);
mTouchMode = TOUCH_MODE_REST;
clearScrollingCache();
mSpecificTop = selectedTop;
selectedPos = lookForSelectablePosition(selectedPos, down);
if (selectedPos >= firstPosition && selectedPos <= getLastVisiblePosition()) {
mLayoutMode = LAYOUT_SPECIFIC;
setSelectionInt(selectedPos);
invokeOnItemScrollListener();
} else {
selectedPos = INVALID_POSITION;
}
reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
return selectedPos >= 0;
|
boolean | sendToTextFilter(int keyCode, int count, android.view.KeyEvent event)Sends a key to the text filter window
if (!acceptFilter()) {
return false;
}
boolean handled = false;
boolean okToSend = true;
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_UP:
case KeyEvent.KEYCODE_DPAD_DOWN:
case KeyEvent.KEYCODE_DPAD_LEFT:
case KeyEvent.KEYCODE_DPAD_RIGHT:
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_ENTER:
okToSend = false;
break;
case KeyEvent.KEYCODE_BACK:
if (mFiltered && mPopup != null && mPopup.isShowing() &&
event.getAction() == KeyEvent.ACTION_DOWN) {
handled = true;
mTextFilter.setText("");
}
okToSend = false;
break;
case KeyEvent.KEYCODE_SPACE:
// Only send spaces once we are filtered
okToSend = mFiltered = true;
break;
}
if (okToSend) {
createTextFilter(true);
KeyEvent forwardEvent = event;
if (forwardEvent.getRepeatCount() > 0) {
forwardEvent = KeyEvent.changeTimeRepeat(event, event.getEventTime(), 0);
}
int action = event.getAction();
switch (action) {
case KeyEvent.ACTION_DOWN:
handled = mTextFilter.onKeyDown(keyCode, forwardEvent);
break;
case KeyEvent.ACTION_UP:
handled = mTextFilter.onKeyUp(keyCode, forwardEvent);
break;
case KeyEvent.ACTION_MULTIPLE:
handled = mTextFilter.onKeyMultiple(keyCode, count, event);
break;
}
}
return handled;
|
public void | setCacheColorHint(int color)When set to a non-zero value, the cache color hint indicates that this list is always drawn
on top of a solid, single-color, opaque background
mCacheColorHint = color;
|
public void | setDrawSelectorOnTop(boolean onTop)Controls whether the selection highlight drawable should be drawn on top of the item or
behind it.
mDrawSelectorOnTop = onTop;
|
public void | setFastScrollEnabled(boolean enabled)Enables fast scrolling by letting the user quickly scroll through lists by
dragging the fast scroll thumb. The adapter attached to the list may want
to implement {@link SectionIndexer} if it wishes to display alphabet preview and
jump between sections of the list.
mFastScrollEnabled = enabled;
if (enabled) {
if (mFastScroller == null) {
mFastScroller = new FastScroller(getContext(), this);
}
} else {
if (mFastScroller != null) {
mFastScroller.stop();
mFastScroller = null;
}
}
|
public void | setFilterText(java.lang.String filterText)Sets the initial value for the text filter.
// TODO: Should we check for acceptFilter()?
if (mTextFilterEnabled && !TextUtils.isEmpty(filterText)) {
createTextFilter(false);
// This is going to call our listener onTextChanged, but we might not
// be ready to bring up a window yet
mTextFilter.setText(filterText);
mTextFilter.setSelection(filterText.length());
if (mAdapter instanceof Filterable) {
// if mPopup is non-null, then onTextChanged will do the filtering
if (mPopup == null) {
Filter f = ((Filterable) mAdapter).getFilter();
f.filter(filterText);
}
// Set filtered to true so we will display the filter window when our main
// window is ready
mFiltered = true;
mDataSetObserver.clearSavedState();
}
}
|
protected boolean | setFrame(int left, int top, int right, int bottom)
final boolean changed = super.setFrame(left, top, right, bottom);
// Reposition the popup when the frame has changed. This includes
// translating the widget, not just changing its dimension. The
// filter popup needs to follow the widget.
if (mFiltered && changed && getWindowVisibility() == View.VISIBLE && mPopup != null &&
mPopup.isShowing()) {
positionPopup();
}
return changed;
|
public void | setOnScrollListener(android.widget.AbsListView$OnScrollListener l)Set the listener that will receive notifications every time the list scrolls.
mOnScrollListener = l;
invokeOnItemScrollListener();
|
public void | setRecyclerListener(android.widget.AbsListView$RecyclerListener listener)Sets the recycler listener to be notified whenever a View is set aside in
the recycler for later reuse. This listener can be used to free resources
associated to the View.
mRecycler.mRecyclerListener = listener;
|
public void | setScrollIndicators(android.view.View up, android.view.View down)
mScrollUp = up;
mScrollDown = down;
|
public void | setScrollingCacheEnabled(boolean enabled)Enables or disables the children's drawing cache during a scroll.
By default, the drawing cache is enabled but this will use more memory.
When the scrolling cache is enabled, the caches are kept after the
first scrolling. You can manually clear the cache by calling
{@link android.view.ViewGroup#setChildrenDrawingCacheEnabled(boolean)}.
if (mScrollingCacheEnabled && !enabled) {
clearScrollingCache();
}
mScrollingCacheEnabled = enabled;
|
abstract void | setSelectionInt(int position)Makes the item at the supplied position selected.
|
public void | setSelector(int resID)Set a Drawable that should be used to highlight the currently selected item.
setSelector(getResources().getDrawable(resID));
|
public void | setSelector(android.graphics.drawable.Drawable sel)
if (mSelector != null) {
mSelector.setCallback(null);
unscheduleDrawable(mSelector);
}
mSelector = sel;
Rect padding = new Rect();
sel.getPadding(padding);
mSelectionLeftPadding = padding.left;
mSelectionTopPadding = padding.top;
mSelectionRightPadding = padding.right;
mSelectionBottomPadding = padding.bottom;
sel.setCallback(this);
sel.setState(getDrawableState());
|
public void | setSmoothScrollbarEnabled(boolean enabled)When smooth scrollbar is enabled, the position and size of the scrollbar thumb
is computed based on the number of visible pixels in the visible items. This
however assumes that all list items have the same height. If you use a list in
which items have different heights, the scrollbar will change appearance as the
user scrolls through the list. To avoid this issue, you need to disable this
property.
When smooth scrollbar is disabled, the position and size of the scrollbar thumb
is based solely on the number of items in the adapter and the position of the
visible items inside the adapter. This provides a stable scrollbar as the user
navigates through a list of items with varying heights.
mSmoothScrollbarEnabled = enabled;
|
public void | setStackFromBottom(boolean stackFromBottom)When stack from bottom is set to true, the list fills its content starting from
the bottom of the view.
if (mStackFromBottom != stackFromBottom) {
mStackFromBottom = stackFromBottom;
requestLayoutIfNecessary();
}
|
public void | setTextFilterEnabled(boolean textFilterEnabled)Enables or disables the type filter window. If enabled, typing when
this view has focus will filter the children to match the users input.
Note that the {@link Adapter} used by this view must implement the
{@link Filterable} interface.
mTextFilterEnabled = textFilterEnabled;
|
public void | setTranscriptMode(int mode)Puts the list or grid into transcript mode. In this mode the list or grid will always scroll
to the bottom to show new items.
mTranscriptMode = mode;
|
boolean | shouldShowSelector()Indicates whether this view is in a state where the selector should be drawn. This will
happen if we have focus but are not in touch mode, or we are in the middle of displaying
the pressed state for an item.
return (hasFocus() && !isInTouchMode()) || touchModeDrawsInPressedState();
|
public boolean | showContextMenuForChild(android.view.View originalView)
final int longPressPosition = getPositionForView(originalView);
if (longPressPosition >= 0) {
final long longPressId = mAdapter.getItemId(longPressPosition);
boolean handled = false;
if (mOnItemLongClickListener != null) {
handled = mOnItemLongClickListener.onItemLongClick(AbsListView.this, originalView,
longPressPosition, longPressId);
}
if (!handled) {
mContextMenuInfo = createContextMenuInfo(
getChildAt(longPressPosition - mFirstPosition),
longPressPosition, longPressId);
handled = super.showContextMenuForChild(originalView);
}
return handled;
}
return false;
|
private void | showPopup()Shows the filter window
// Make sure we have a window before showing the popup
if (getWindowVisibility() == View.VISIBLE) {
createTextFilter(true);
positionPopup();
// Make sure we get focus if we are showing the popup
checkFocus();
}
|
private boolean | startScrollIfNeeded(int deltaY)
// Check if we have moved far enough that it looks more like a
// scroll than a tap
final int distance = Math.abs(deltaY);
if (distance > mTouchSlop) {
createScrollingCache();
mTouchMode = TOUCH_MODE_SCROLL;
mMotionCorrection = deltaY;
final Handler handler = getHandler();
// Handler should not be null unless the AbsListView is not attached to a
// window, which would make it very hard to scroll it... but the monkeys
// say it's possible.
if (handler != null) {
handler.removeCallbacks(mPendingCheckForLongPress);
}
setPressed(false);
View motionView = getChildAt(mMotionPosition - mFirstPosition);
if (motionView != null) {
motionView.setPressed(false);
}
reportScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
// Time to start stealing events! Once we've stolen them, don't let anyone
// steal from us
requestDisallowInterceptTouchEvent(true);
return true;
}
return false;
|
boolean | touchModeDrawsInPressedState()
// FIXME use isPressed for this
switch (mTouchMode) {
case TOUCH_MODE_TAP:
case TOUCH_MODE_DONE_WAITING:
return true;
default:
return false;
}
|
void | trackMotionScroll(int deltaY, int incrementalDeltaY)Track a motion scroll
final int childCount = getChildCount();
if (childCount == 0) {
return;
}
final int firstTop = getChildAt(0).getTop();
final int lastBottom = getChildAt(childCount - 1).getBottom();
final Rect listPadding = mListPadding;
// FIXME account for grid vertical spacing too?
final int spaceAbove = listPadding.top - firstTop;
final int end = getHeight() - listPadding.bottom;
final int spaceBelow = lastBottom - end;
final int height = getHeight() - mPaddingBottom - mPaddingTop;
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 absIncrementalDeltaY = Math.abs(incrementalDeltaY);
if (spaceAbove >= absIncrementalDeltaY && spaceBelow >= absIncrementalDeltaY) {
hideSelector();
offsetChildrenTopAndBottom(incrementalDeltaY);
invalidate();
mMotionViewNewTop = mMotionViewOriginalTop + deltaY;
} else {
final int firstPosition = mFirstPosition;
if (firstPosition == 0 && firstTop >= listPadding.top && deltaY > 0) {
// Don't need to move views down if the top of the first position is already visible
return;
}
if (firstPosition + childCount == mItemCount && lastBottom <= end && deltaY < 0) {
// Don't need to move views up if the bottom of the last position is already visible
return;
}
final boolean down = incrementalDeltaY < 0;
hideSelector();
final int headerViewsCount = getHeaderViewsCount();
final int footerViewsStart = mItemCount - getFooterViewsCount();
int start = 0;
int count = 0;
if (down) {
final int top = listPadding.top - incrementalDeltaY;
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);
if (ViewDebug.TRACE_RECYCLER) {
ViewDebug.trace(child,
ViewDebug.RecyclerTraceType.MOVE_TO_SCRAP_HEAP,
firstPosition + i, -1);
}
}
}
}
} else {
final int bottom = getHeight() - listPadding.bottom - incrementalDeltaY;
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);
if (ViewDebug.TRACE_RECYCLER) {
ViewDebug.trace(child,
ViewDebug.RecyclerTraceType.MOVE_TO_SCRAP_HEAP,
firstPosition + i, -1);
}
}
}
}
}
mMotionViewNewTop = mMotionViewOriginalTop + deltaY;
mBlockLayoutRequests = true;
detachViewsFromParent(start, count);
offsetChildrenTopAndBottom(incrementalDeltaY);
if (down) {
mFirstPosition += count;
}
invalidate();
fillGap(down);
mBlockLayoutRequests = false;
invokeOnItemScrollListener();
}
|
void | updateScrollIndicators()
if (mScrollUp != null) {
boolean canScrollUp;
// 0th element is not visible
canScrollUp = mFirstPosition > 0;
// ... Or top of 0th element is not visible
if (!canScrollUp) {
if (getChildCount() > 0) {
View child = getChildAt(0);
canScrollUp = child.getTop() < mListPadding.top;
}
}
mScrollUp.setVisibility(canScrollUp ? View.VISIBLE : View.INVISIBLE);
}
if (mScrollDown != null) {
boolean canScrollDown;
int count = getChildCount();
// Last item is not visible
canScrollDown = (mFirstPosition + count) < mItemCount;
// ... Or bottom of the last element is not visible
if (!canScrollDown && count > 0) {
View child = getChildAt(count - 1);
canScrollDown = child.getBottom() > mBottom - mListPadding.bottom;
}
mScrollDown.setVisibility(canScrollDown ? View.VISIBLE : View.INVISIBLE);
}
|
private void | useDefaultSelector()
setSelector(getResources().getDrawable(
com.android.internal.R.drawable.list_selector_background));
|
public boolean | verifyDrawable(android.graphics.drawable.Drawable dr)
return mSelector == dr || super.verifyDrawable(dr);
|