Created
June 5, 2013 03:26
-
-
Save shanyou/5711408 to your computer and use it in GitHub Desktop.
AmazingListView.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.foound.widget; | |
| import android.content.*; | |
| import android.graphics.*; | |
| import android.util.*; | |
| import android.view.*; | |
| import android.widget.*; | |
| import com.foound.widget.AmazingAdapter.HasMorePagesListener; | |
| /** | |
| * A ListView that maintains a header pinned at the top of the list. The | |
| * pinned header can be pushed up and dissolved as needed. | |
| * | |
| * It also supports pagination by setting a custom view as the loading | |
| * indicator. | |
| */ | |
| public class AmazingListView extends ListView implements HasMorePagesListener { | |
| public static final String TAG = AmazingListView.class.getSimpleName(); | |
| View listFooter; | |
| boolean footerViewAttached = false; | |
| private View mHeaderView; | |
| private boolean mHeaderViewVisible; | |
| private int mHeaderViewWidth; | |
| private int mHeaderViewHeight; | |
| private AmazingAdapter adapter; | |
| public void setPinnedHeaderView(View view) { | |
| mHeaderView = view; | |
| // Disable vertical fading when the pinned header is present | |
| // TODO change ListView to allow separate measures for top and bottom fading edge; | |
| // in this particular case we would like to disable the top, but not the bottom edge. | |
| if (mHeaderView != null) { | |
| setFadingEdgeLength(0); | |
| } | |
| requestLayout(); | |
| } | |
| @Override | |
| protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { | |
| super.onMeasure(widthMeasureSpec, heightMeasureSpec); | |
| if (mHeaderView != null) { | |
| measureChild(mHeaderView, widthMeasureSpec, heightMeasureSpec); | |
| mHeaderViewWidth = mHeaderView.getMeasuredWidth(); | |
| mHeaderViewHeight = mHeaderView.getMeasuredHeight(); | |
| } | |
| } | |
| @Override | |
| protected void onLayout(boolean changed, int left, int top, int right, int bottom) { | |
| super.onLayout(changed, left, top, right, bottom); | |
| if (mHeaderView != null) { | |
| mHeaderView.layout(0, 0, mHeaderViewWidth, mHeaderViewHeight); | |
| configureHeaderView(getFirstVisiblePosition()); | |
| } | |
| } | |
| public void configureHeaderView(int position) { | |
| if (mHeaderView == null) { | |
| return; | |
| } | |
| int state = adapter.getPinnedHeaderState(position); | |
| switch (state) { | |
| case AmazingAdapter.PINNED_HEADER_GONE: { | |
| mHeaderViewVisible = false; | |
| break; | |
| } | |
| case AmazingAdapter.PINNED_HEADER_VISIBLE: { | |
| adapter.configurePinnedHeader(mHeaderView, position, 255); | |
| if (mHeaderView.getTop() != 0) { | |
| mHeaderView.layout(0, 0, mHeaderViewWidth, mHeaderViewHeight); | |
| } | |
| mHeaderViewVisible = true; | |
| break; | |
| } | |
| case AmazingAdapter.PINNED_HEADER_PUSHED_UP: { | |
| View firstView = getChildAt(0); | |
| if (firstView != null) { | |
| int bottom = firstView.getBottom(); | |
| int headerHeight = mHeaderView.getHeight(); | |
| int y; | |
| int alpha; | |
| if (bottom < headerHeight) { | |
| y = (bottom - headerHeight); | |
| alpha = 255 * (headerHeight + y) / headerHeight; | |
| } else { | |
| y = 0; | |
| alpha = 255; | |
| } | |
| adapter.configurePinnedHeader(mHeaderView, position, alpha); | |
| if (mHeaderView.getTop() != y) { | |
| mHeaderView.layout(0, y, mHeaderViewWidth, mHeaderViewHeight + y); | |
| } | |
| mHeaderViewVisible = true; | |
| } | |
| break; | |
| } | |
| } | |
| } | |
| @Override | |
| protected void dispatchDraw(Canvas canvas) { | |
| super.dispatchDraw(canvas); | |
| if (mHeaderViewVisible) { | |
| drawChild(canvas, mHeaderView, getDrawingTime()); | |
| } | |
| } | |
| public AmazingListView(Context context) { | |
| super(context); | |
| } | |
| public AmazingListView(Context context, AttributeSet attrs) { | |
| super(context, attrs); | |
| } | |
| public AmazingListView(Context context, AttributeSet attrs, int defStyle) { | |
| super(context, attrs, defStyle); | |
| } | |
| public void setLoadingView(View listFooter) { | |
| this.listFooter = listFooter; | |
| } | |
| public View getLoadingView() { | |
| return listFooter; | |
| } | |
| @Override | |
| public void setAdapter(ListAdapter adapter) { | |
| if (!(adapter instanceof AmazingAdapter)) { | |
| throw new IllegalArgumentException(AmazingListView.class.getSimpleName() + " must use adapter of type " + AmazingAdapter.class.getSimpleName()); | |
| } | |
| // previous adapter | |
| if (this.adapter != null) { | |
| this.adapter.setHasMorePagesListener(null); | |
| this.setOnScrollListener(null); | |
| } | |
| this.adapter = (AmazingAdapter) adapter; | |
| ((AmazingAdapter)adapter).setHasMorePagesListener(this); | |
| this.setOnScrollListener((AmazingAdapter) adapter); | |
| View dummy = new View(getContext()); | |
| super.addFooterView(dummy); | |
| super.setAdapter(adapter); | |
| super.removeFooterView(dummy); | |
| } | |
| @Override | |
| public AmazingAdapter getAdapter() { | |
| return adapter; | |
| } | |
| @Override | |
| public void noMorePages() { | |
| if (listFooter != null) { | |
| this.removeFooterView(listFooter); | |
| } | |
| footerViewAttached = false; | |
| } | |
| @Override | |
| public void mayHaveMorePages() { | |
| if (! footerViewAttached && listFooter != null) { | |
| this.addFooterView(listFooter); | |
| footerViewAttached = true; | |
| } | |
| } | |
| public boolean isLoadingViewVisible() { | |
| return footerViewAttached; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment