/** * Set header to be pinned at the top of the first visible item. * * @param viewIndex index of the header view * @param position is position of the header in pixels. */ public void setFadingHeader(int viewIndex, int position, boolean fade) { ensurePinnedHeaderLayout(viewIndex); View child = getChildAt(position - getFirstVisiblePosition()); if (child == null) return; PinnedHeader header = mHeaders[viewIndex]; header.visible = true; header.state = FADING; header.alpha = MAX_ALPHA; header.animating = false; int top = getTotalTopPinnedHeaderHeight(); header.y = top; if (fade) { int bottom = child.getBottom() - top; int headerHeight = header.height; if (bottom < headerHeight) { int portion = bottom - headerHeight; header.alpha = MAX_ALPHA * (headerHeight + portion) / headerHeight; header.y = top + portion; } } }
/** * Makes header invisible. * * @param viewIndex index of the header view * @param animate true if the transition to the new coordinate should be animated */ public void setHeaderInvisible(int viewIndex, boolean animate) { PinnedHeader header = mHeaders[viewIndex]; if (header.visible && (animate || header.animating) && header.state == BOTTOM) { header.sourceY = header.y; if (!header.animating) { header.visible = true; header.targetY = getBottom() + header.height; } header.animating = true; header.targetTime = mAnimationTargetTime; header.targetVisible = false; } else { header.visible = false; } }
@Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); mHeaderPaddingStart = getPaddingStart(); mHeaderWidth = r - l - mHeaderPaddingStart - getPaddingEnd(); }
/** * Returns the list item position at the specified y coordinate. */ public int getPositionAt(int y) { do { int position = pointToPosition(getPaddingLeft() + 1, y); if (position != -1) { return position; } // If position == -1, we must have hit a separator. Let's examine // a nearby pixel y--; } while (y > 0); return 0; }
mHeaderVisibility[i] = visible; if (!visible) { listView.setHeaderInvisible(i, true); int headerViewsCount = listView.getHeaderViewsCount(); for (int i = 0; i < size; i++) { if (mHeaderVisibility[i]) { int position = listView.getPositionAt(topHeaderHeight) - headerViewsCount; int partition = getPartitionForPosition(position); if (i > partition) { listView.setHeaderPinnedAtTop(i, topHeaderHeight, false); topHeaderHeight += listView.getPinnedHeaderHeight(i); maxTopHeader = i; int listHeight = listView.getHeight(); for (int i = size; --i > maxTopHeader;) { if (mHeaderVisibility[i]) { int position = listView.getPositionAt(listHeight - bottomHeaderHeight) - headerViewsCount; if (position < 0) { int height = listView.getPinnedHeaderHeight(i); bottomHeaderHeight += height; listView.setHeaderPinnedAtBottom(i, listHeight - bottomHeaderHeight, false); maxBottomHeader = i;
listView.setHeaderInvisible(index, false); } else { int listPosition = listView.getPositionAt(listView.getTotalTopPinnedHeaderHeight()); int position = listPosition - listView.getHeaderViewsCount(); listView.setHeaderInvisible(index, false); } else { View topChild = listView.getChildAt(listPosition); if (topChild != null) { listView.setFadingHeader(index, listPosition, isLastInSection);
int bottom = getBottom(); boolean hasVisibleHeaders = false; for (int i = 0; i < mSize; i++) { if (mSize > 0 && getFirstVisiblePosition() == 0) { View firstChild = getChildAt(0); PinnedHeader firstHeader = mHeaders[0]; PinnedHeader header = mHeaders[i]; if (header.visible && (header.state == TOP || header.state == FADING)) { drawHeader(canvas, header, currentTime); PinnedHeader header = mHeaders[i]; if (header.visible && header.state == BOTTOM) { drawHeader(canvas, header, currentTime); invalidateIfAnimating();
int height = getHeight(); View selectedView = getSelectedView(); if (selectedView != null) { if (selectedView.getTop() < windowTop) { setSelectionFromTop(position, windowTop); } else if (selectedView.getBottom() > windowBottom) { setSelectionFromTop(position, windowBottom - selectedView.getHeight());
private boolean smoothScrollToPartition(int partition) { if (mAdapter == null) { return false; } final int position = mAdapter.getScrollPositionForHeader(partition); if (position == -1) { return false; } int offset = 0; for (int i = 0; i < partition; i++) { PinnedHeader header = mHeaders[i]; if (header.visible) { offset += header.height; } } smoothScrollToPositionFromTop(position + getHeaderViewsCount(), offset, DEFAULT_SMOOTH_SCROLL_DURATION); return true; }
@Override public boolean onInterceptTouchEvent(MotionEvent ev) { mHeaderTouched = false; if (super.onInterceptTouchEvent(ev)) { return true; } if (mScrollState == SCROLL_STATE_IDLE) { final int y = (int)ev.getY(); final int x = (int)ev.getX(); for (int i = mSize; --i >= 0;) { PinnedHeader header = mHeaders[i]; // For RTL layouts, this also takes into account that the scrollbar is on the left // side. final int padding = getPaddingLeft(); if (header.visible && header.y <= y && header.y + header.height > y && x >= padding && padding + header.view.getWidth() >= x) { mHeaderTouched = true; if (mScrollToSectionOnHeaderTouch && ev.getAction() == MotionEvent.ACTION_DOWN) { return smoothScrollToPartition(i); } else { return true; } } } } return false; }
/** * Set header to be pinned at the top. * * @param viewIndex index of the header view * @param y is position of the header in pixels. * @param animate true if the transition to the new coordinate should be animated */ public void setHeaderPinnedAtTop(int viewIndex, int y, boolean animate) { ensurePinnedHeaderLayout(viewIndex); PinnedHeader header = mHeaders[viewIndex]; header.visible = true; header.y = y; header.state = TOP; // TODO perhaps we should animate at the top as well header.animating = false; }
public int getPinnedHeaderHeight(int viewIndex) { ensurePinnedHeaderLayout(viewIndex); return mHeaders[viewIndex].view.getHeight(); }
ensurePinnedHeaderLayout(viewIndex); PinnedHeader header = mHeaders[viewIndex]; header.state = BOTTOM;