@Override public void setSelector(Drawable sel) { super.setSelector(sel); if (frame != null) { frame.setSelector(sel); } }
@Override public void setVisibility(int visibility) { if (frame != null) { frame.setVisibility(visibility); } super.setVisibility(visibility); }
@Override public void setSelectionFromTop(int position, int offset) { if (!isCalledFromSuper()) { if (adapter == null) { positionToSetWhenAdapterIsReady = position; offsetToSetWhenAdapterIsReady = offset; return; } if (areHeadersSticky) { if (frame != null && frame.hasHeader()) { offset += frame.getHeaderHeight(); } } position = adapter.translateAdapterPosition(position); } super.setSelectionFromTop(position, offset); }
@Override public void onClick(View v) { if (frame.isHeader(v)) { if (onHeaderClickListener != null) { onHeaderClickListener.onHeaderClick(this, v, headerPosition, currentHeaderId, true); } } }
@Override public void setDrawSelectorOnTop(boolean onTop) { super.setDrawSelectorOnTop(onTop); drawSelectorOnTop = onTop; if (frame != null) { frame.setDrawSelectorOnTop(drawSelectorOnTop); } }
@SuppressWarnings("deprecation") @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); if (frame == null) { ViewGroup parent = ((ViewGroup) getParent()); int listIndex = parent.indexOfChild(this); parent.removeView(this); int visibility = getVisibility(); setVisibility(View.VISIBLE); frame = new StickyListHeadersListViewWrapper(getContext()); frame.setSelector(getSelector()); frame.setDrawSelectorOnTop(drawSelectorOnTop); frame.setVisibility(visibility); ViewGroup.MarginLayoutParams p = (MarginLayoutParams) getLayoutParams(); if (clippingToPadding) { frame.setPadding(0, getPaddingTop(), 0, getPaddingBottom()); setPadding(getPaddingLeft(), 0, getPaddingRight(), 0); } ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); setLayoutParams(params); frame.addView(this); frame.setBackgroundDrawable(getBackground()); super.setBackgroundDrawable(null); frame.setLayoutParams(p); parent.addView(frame, listIndex); } }
@Override @Deprecated public void setBackgroundDrawable(Drawable background) { if (frame != null) { frame.setBackgroundDrawable(background); } else { super.setBackgroundDrawable(background); } }
@Override public void smoothScrollToPositionFromTop(int position, int offset, int duration) { if (!isCalledFromSuper()) { if (adapter == null) { positionToSetWhenAdapterIsReady = position; offsetToSetWhenAdapterIsReady = offset; return; } if (areHeadersSticky) { if (frame != null && frame.hasHeader()) { offset += frame.getHeaderHeight(); } } position = adapter.translateAdapterPosition(position); } try { super.smoothScrollToPositionFromTop(position, offset, duration); } catch (NoSuchMethodError e) { // droid_utils: API < 11 TODO: update lib to fix this properly } }
@Override protected void dispatchDraw(Canvas canvas) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.FROYO) { post( new Runnable() { @Override public void run() { scrollChanged(StickyListHeadersListView.super.getFirstVisiblePosition()); } }); } if (!drawingListUnderStickyHeader) { canvas.clipRect( 0, Math.max(frame.getHeaderBottomPosition(), 0), canvas.getWidth(), canvas.getHeight()); } super.dispatchDraw(canvas); }
@Override public void setAdapter(ListAdapter adapter) { if (this.isInEditMode()) { super.setAdapter(adapter); return; } if (!clipToPaddingHasBeenSet) { clippingToPadding = true; } if (adapter != null && !(adapter instanceof StickyListHeadersAdapter)) { throw new IllegalArgumentException("Adapter must implement StickyListHeadersAdapter"); } if (this.adapter != null) { this.adapter.unregisterInternalDataSetObserver(dataSetChangedObserver); this.adapter = null; } if (adapter != null) { if (adapter instanceof SectionIndexer) { this.adapter = new StickyListHeadersSectionIndexerAdapterWrapper( getContext(), (StickyListHeadersAdapter) adapter); } else { this.adapter = new StickyListHeadersAdapterWrapper(getContext(), (StickyListHeadersAdapter) adapter); } this.adapter.setDivider(divider); this.adapter.setDividerHeight(dividerHeight); this.adapter.registerInternalDataSetObserver(dataSetChangedObserver); setSelectionFromTop(positionToSetWhenAdapterIsReady, offsetToSetWhenAdapterIsReady); } currentHeaderId = null; if (frame != null) { frame.removeHeader(); } updateHeaderVisibilities(); invalidate(); super.setAdapter(this.adapter); }
@Override public void onInvalidated() { currentHeaderId = null; frame.removeHeader(); }
private void scrollChanged(int firstVisibleItem) { if (adapter == null || frame == null) { return; } int adapterCount = adapter.getCount(); if (adapterCount == 0 || !areHeadersSticky) { frame.removeHeader(); return; } final int listViewHeaderCount = getHeaderViewsCount(); firstVisibleItem = getFixedFirstVisibleItem(firstVisibleItem) - listViewHeaderCount; if (firstVisibleItem < 0 || firstVisibleItem > adapterCount - 1) { if (currentHeaderId != null || dataChanged) { currentHeaderId = null; frame.removeHeader(); updateHeaderVisibilities(); invalidate(); dataChanged = false; } return; } boolean headerHasChanged = false; long newHeaderId = adapter.getHeaderId(firstVisibleItem); if (currentHeaderId == null || currentHeaderId != newHeaderId) { headerPosition = firstVisibleItem; View header = adapter.getHeaderView(headerPosition, frame.removeHeader(), frame); header.setOnClickListener(this); frame.setHeader(header); headerHasChanged = true; } currentHeaderId = newHeaderId; int childCount = getChildCount(); if (childCount > 0) { View viewToWatch = null; int watchingChildDistance = Integer.MAX_VALUE; boolean viewToWatchIsFooter = false; for (int i = 0; i < childCount; i++) { View child = getChildAt(i); boolean childIsFooter = footerViews != null && footerViews.contains(child); int childDistance; if (clippingToPadding) { childDistance = child.getTop() - getPaddingTop(); } else { childDistance = child.getTop(); } if (childDistance < 0) { continue; } if (viewToWatch == null || (!viewToWatchIsFooter && !adapter.isHeader(viewToWatch)) || ((childIsFooter || adapter.isHeader(child)) && childDistance < watchingChildDistance)) { viewToWatch = child; viewToWatchIsFooter = childIsFooter; watchingChildDistance = childDistance; } } int headerHeight = frame.getHeaderHeight(); int headerBottomPosition = 0; if (viewToWatch != null && (viewToWatchIsFooter || adapter.isHeader(viewToWatch))) { if (firstVisibleItem == listViewHeaderCount && getChildAt(0).getTop() > 0 && !clippingToPadding) { headerBottomPosition = 0; } else { if (clippingToPadding) { headerBottomPosition = Math.min(viewToWatch.getTop(), headerHeight + getPaddingTop()); headerBottomPosition = headerBottomPosition < getPaddingTop() ? headerHeight + getPaddingTop() : headerBottomPosition; } else { headerBottomPosition = Math.min(viewToWatch.getTop(), headerHeight); headerBottomPosition = headerBottomPosition < 0 ? headerHeight : headerBottomPosition; } } } else { headerBottomPosition = headerHeight; if (clippingToPadding) { headerBottomPosition += getPaddingTop(); } } if (frame.getHeaderBottomPosition() != headerBottomPosition || headerHasChanged) { frame.setHeaderBottomPosition(headerBottomPosition); } updateHeaderVisibilities(); } }