Log.e(“parent”,“onScroll”);
if (mOnScrollListenerDelegate != null) {
mOnScrollListenerDelegate.onScroll(view, firstVisibleItem,
visibleItemCount, totalItemCount);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) {
scrollChanged(firstVisibleItem);
}
}
};
public StickyListHeadersListView(Context context) {
this(context, null);
}
public StickyListHeadersListView(Context context, AttributeSet attrs) {
this(context, attrs, android.R.attr.listViewStyle);
}
public StickyListHeadersListView(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
super.setOnScrollListener(mOnScrollListener);
// null out divider, dividers are handled by adapter so they look good
// with headers
super.setDivider(null);
super.setDividerHeight(0);
mViewConfig = ViewConfiguration.get(context);
if (mClippingToPadding == null) {
mClippingToPadding = true;
}
try {
Field selectorRectField = AbsListView.class
.getDeclaredField(“mSelectorRect”);
selectorRectField.setAccessible(true);
mSelectorRect = (Rect) selectorRectField.get(this);
mSelectorPositionField = AbsListView.class
.getDeclaredField(“mSelectorPosition”);
mSelectorPositionField.setAccessible(true);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if (changed) {
reset();
scrollChanged(getFirstVisiblePosition());
}
}
private void reset() {
mHeader = null;
mCurrentHeaderId = null;
mHeaderPosition = null;
mHeaderBottomPosition = -1;
}
@Override
public boolean performItemClick(View view, int position, long id) {
if (view instanceof WrapperView) {
view = ((WrapperView) view).mItem;
}
return super.performItemClick(view, position, id);
}
@Override
public void setDivider(Drawable divider) {
this.mDivider = divider;
if (divider != null) {
int dividerDrawableHeight = divider.getIntrinsicHeight();
if (dividerDrawableHeight >= 0) {
setDividerHeight(dividerDrawableHeight);
}
}
if (mAdapter != null) {
mAdapter.setDivider(divider);
requestLayout();
invalidate();
}
}
@Override
public void setDividerHeight(int height) {
mDividerHeight = height;
if (mAdapter != null) {
mAdapter.setDividerHeight(height);
requestLayout();
invalidate();
}
}
@Override
public void setOnScrollListener(OnScrollListener l) {
mOnScrollListenerDelegate = l;
}
public void setAreHeadersSticky(boolean areHeadersSticky) {
if (this.mAreHeadersSticky != areHeadersSticky) {
this.mAreHeadersSticky = areHeadersSticky;
requestLayout();
}
}
public boolean getAreHeadersSticky() {
return mAreHeadersSticky;
}
@Override
public void setAdapter(ListAdapter adapter) {
if (this.isInEditMode()) {
super.setAdapter(adapter);
return;
}
if (adapter == null) {
mAdapter = null;
reset();
super.setAdapter(null);
return;
}
if (!(adapter instanceof StickyListHeadersAdapter)) {
throw new IllegalArgumentException(
“Adapter must implement StickyListHeadersAdapter”);
}
mAdapter = wrapAdapter(adapter);
reset();
super.setAdapter(this.mAdapter);
}
private AdapterWrapper wrapAdapter(ListAdapter adapter) {
AdapterWrapper wrapper;
if (adapter instanceof SectionIndexer) {
wrapper = new SectionIndexerAdapterWrapper(getContext(),
(StickyListHeadersAdapter) adapter);
} else {
wrapper = new AdapterWrapper(getContext(),
(StickyListHeadersAdapter) adapter);
}
wrapper.setDivider(mDivider);
wrapper.setDividerHeight(mDividerHeight);
wrapper.registerDataSetObserver(mDataSetChangedObserver);
wrapper.setOnHeaderClickListener(mAdapterHeaderClickListener);
return wrapper;
}
public StickyListHeadersAdapter getWrappedAdapter() {
return mAdapter == null ? null : mAdapter.mDelegate;
}
public View getWrappedView(int position) {
View view = getChildAt(position);
if ((view instanceof WrapperView))
return ((WrapperView) view).mItem;
return view;
}
@Override
protected void dispatchDraw(Canvas canvas) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.FROYO) {
scrollChanged(getFirstVisiblePosition());
}
positionSelectorRect();
if (!mAreHeadersSticky || mHeader == null) {
super.dispatchDraw(canvas);
return;
}
if (!mDrawingListUnderStickyHeader) {
mClippingRect
.set(0, mHeaderBottomPosition, getWidth(), getHeight());
canvas.save();
canvas.clipRect(mClippingRect); 《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》无偿开源 徽信搜索公众号【编程进阶路】
}
super.dispatchDraw(canvas);
if (!mDrawingListUnderStickyHeader) {
canvas.restore();
}
drawStickyHeader(canvas);
}
private void positionSelectorRect() {
if (!mSelectorRect.isEmpty()) {
int selectorPosition = getSelectorPosition();
if (selectorPosition >= 0) {
int firstVisibleItem = fixedFirstVisibleItem(getFirstVisiblePosition());
View v = getChildAt(selectorPosition - firstVisibleItem);
if (v instanceof WrapperView) {
WrapperView wrapper = ((WrapperView) v);
mSelectorRect.top = wrapper.getTop() + wrapper.mItemTop;
}
}
}
}
private int getSelectorPosition() {
if (mSelectorPositionField == null) { // not all supported andorid
// version have this variable
for (int i = 0; i < getChildCount(); i++) {
if (getChildAt(i).getBottom() == mSelectorRect.bottom) {
return i + fixedFirstVisibleItem(getFirstVisiblePosition());
}
}
} else {
try {
return mSelectorPositionField.getInt(this);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return -1;
}
private void drawStickyHeader(Canvas canvas) {
int headerHeight = getHeaderHeight();
int top = mHeaderBottomPosition - headerHeight;
// clip the headers drawing region
mClippingRect.left = getPaddingLeft();
mClippingRect.right = getWidth() - getPaddingRight();
mClippingRect.bottom = top + headerHeight;
mClippingRect.top = mClippingToPadding ? getPaddingTop() : 0;
canvas.save();
canvas.clipRect(mClippingRect);
canvas.translate(getPaddingLeft(), top);
mHeader.draw(canvas);
canvas.restore();
}
private void measureHeader() {
int widthMeasureSpec = MeasureSpec.makeMeasureSpec(getWidth()
-
getPaddingLeft() - getPaddingRight()
-
(isScrollBarOverlay() ? 0 : getVerticalScrollbarWidth()), MeasureSpec.EXACTLY);
int heightMeasureSpec = 0;
ViewGroup.LayoutParams params = mHeader.getLayoutParams();
if (params != null && params.height > 0) {
heightMeasureSpec = MeasureSpec.makeMeasureSpec(params.height,
MeasureSpec.EXACTLY);
} else {
heightMeasureSpec = MeasureSpec.makeMeasureSpec(0,
MeasureSpec.UNSPECIFIED);
}
mHeader.measure(widthMeasureSpec, heightMeasureSpec);
mHeader.layout(getPaddingLeft(), 0, getWidth()
- getPaddingRight(), mHeader.getMeasuredHeight());
}
private boolean isScrollBarOverlay() {
int scrollBarStyle = getScrollBarStyle();
return scrollBarStyle == SCROLLBARS_INSIDE_OVERLAY || scrollBarStyle == SCROLLBARS_OUTSIDE_OVERLAY;
}
private int getHeaderHeight() {
return mHeader == null ? 0 : mHeader.getMeasuredHeight();
}
@Override
public void setClipToPadding(boolean clipToPadding) {