XListview之自定义Header和footer动画

来源:互联网 发布:淘宝店铺违规了怎么办 编辑:程序博客网 时间:2024/05/22 15:14

最近看到很多的下拉刷新都是采用的很cute的动画,所以就将XListview改造了一下,做成了一个可以自动下拉刷新以及自动加载更多的东西

好了,废话不多说,先上图:


尾巴:


ps:header动画资源是在百度贴吧客户端扒出来的,footer动画的资源实在知乎客户端扒出来的

//能否上拉刷新控制

mListView.setPullLoadEnable(false);

//能否下拉刷新控制

mListView.setPullRefreshEnable(false);

//自动下拉刷新控制  

mListView.doAutoRefresh();

//自动加载更多控制

mListView.doAutoLoadMore();


package me.maxwin.view;import me.maxwin.R;import android.content.Context;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.view.ViewTreeObserver.OnGlobalLayoutListener;import android.view.animation.DecelerateInterpolator;import android.widget.AbsListView;import android.widget.AbsListView.OnScrollListener;import android.widget.ListAdapter;import android.widget.ListView;import android.widget.RelativeLayout;import android.widget.Scroller;public class XListView extends ListView implements OnScrollListener {private float mLastY = -1; // save event yprivate Scroller mScroller; // used for scroll backprivate OnScrollListener mScrollListener; // user's scroll listener// the interface to trigger refresh and load more.private IXListViewListener mListViewListener;// -- header viewprivate XListViewHeader mHeaderView;// header view content, use it to calculate the Header's height. And hide it// when disable pull refresh.private RelativeLayout mHeaderViewContent;private int mHeaderViewHeight; // header view's heightprivate boolean mEnablePullRefresh = true;private boolean mPullRefreshing = false; // is refreashing.// -- footer viewprivate XListViewFooter mFooterView;private boolean mEnablePullLoad;private boolean mPullLoading;private boolean mIsFooterReady = false;// -- auto loadprivate int visibleLastIndex = 0; // 最后的可视项索引private boolean autoLoadMore = false;// total list items, used to detect is at the bottom of listview.private int mTotalItemCount;// for mScroller, scroll back from header or footer.private int mScrollBack;private final static int SCROLLBACK_HEADER = 0;private final static int SCROLLBACK_FOOTER = 1;private final static int SCROLL_DURATION = 400; // scroll back durationprivate final static int PULL_LOAD_MORE_DELTA = 50; // when pull up >= 50px// at bottom, trigger// load more.private final static float OFFSET_RADIO = 1.8f; // support iOS like pull// feature./** * @param context */public XListView(Context context) {super(context);initWithContext(context);}public XListView(Context context, AttributeSet attrs) {super(context, attrs);initWithContext(context);}public XListView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);initWithContext(context);}private void initWithContext(Context context) {mScroller = new Scroller(context, new DecelerateInterpolator());// XListView need the scroll event, and it will dispatch the event to// user's listener (as a proxy).super.setOnScrollListener(this);// init header viewmHeaderView = new XListViewHeader(context);mHeaderViewContent = (RelativeLayout) mHeaderView.findViewById(R.id.xlistview_header_content);addHeaderView(mHeaderView);// init footer viewmFooterView = new XListViewFooter(context);// init header heightmHeaderView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {@SuppressWarnings("deprecation")@Overridepublic void onGlobalLayout() {mHeaderViewHeight = mHeaderViewContent.getHeight();getViewTreeObserver().removeGlobalOnLayoutListener(this);}});}@Overridepublic void setAdapter(ListAdapter adapter) {// make sure XListViewFooter is the last footer view, and only add once.if (mIsFooterReady == false) {mIsFooterReady = true;addFooterView(mFooterView);}super.setAdapter(adapter);}/** * enable or disable pull down refresh feature. *  * @param enable */public void setPullRefreshEnable(boolean enable) {mEnablePullRefresh = enable;if (!mEnablePullRefresh) { // disable, hide the contentmHeaderViewContent.setVisibility(View.INVISIBLE);} else {mHeaderViewContent.setVisibility(View.VISIBLE);}}/** * enable or disable pull up load more feature. *  * @param enable */public void setPullLoadEnable(boolean enable) {mEnablePullLoad = enable;if (!mEnablePullLoad) {mFooterView.hide();mFooterView.setOnClickListener(null);// make sure "pull up" don't show a line in bottom when listview// with one pagesetFooterDividersEnabled(false);} else {mPullLoading = false;mFooterView.show();mFooterView.setState(XListViewFooter.STATE_NORMAL);// make sure "pull up" don't show a line in bottom when listview// with one pagesetFooterDividersEnabled(true);// both "pull up" and "click" will invoke load more.mFooterView.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {startLoadMore();}});}}/** * refresh auto */public void doAutoRefresh() {if (mEnablePullRefresh) {mPullRefreshing = true;mHeaderView.setState(XListViewHeader.STATE_REFRESHING);int height = (int) getResources().getDimension(R.dimen.load_header_height);mScroller.startScroll(0, 0, 0, height, SCROLL_DURATION);mScrollBack = SCROLLBACK_HEADER;// trigger computeScrollinvalidate();mListViewListener.onRefresh();}}public void doAutoLoadMore() {autoLoadMore = true;setOnScrollListener(new AutoLoadMoreListener());}/** * stop refresh, reset header view. */public void stopRefresh() {if (mPullRefreshing == true) {mPullRefreshing = false;resetHeaderHeight();}}/** * stop load more, reset footer view. */public void stopLoadMore(boolean hasmore) {if (mPullLoading == true) {mPullLoading = false;if (hasmore) {if (autoLoadMore) {if (mScrollListener == null) {setOnScrollListener(new AutoLoadMoreListener());}}mFooterView.setState(XListViewFooter.STATE_NORMAL);} else {if (mScrollListener instanceof AutoLoadMoreListener) {setOnScrollListener(null);}mFooterView.setState(XListViewFooter.STATE_NOMORE);}}}private void invokeOnScrolling() {if (mScrollListener instanceof OnXScrollListener) {OnXScrollListener l = (OnXScrollListener) mScrollListener;l.onXScrolling(this);}}private void updateHeaderHeight(float delta) {mHeaderView.setVisiableHeight((int) delta+ mHeaderView.getVisiableHeight());if (mEnablePullRefresh && !mPullRefreshing) { // 未处于刷新状态,更新箭头if (mHeaderView.getVisiableHeight() > mHeaderViewHeight) {mHeaderView.setState(XListViewHeader.STATE_READY);} else {mHeaderView.setState(XListViewHeader.STATE_NORMAL);}}setSelection(0); // scroll to top each time}/** * reset header view's height. */private void resetHeaderHeight() {int height = mHeaderView.getVisiableHeight();if (height == 0) // not visible.return;// refreshing and header isn't shown fully. do nothing.if (mPullRefreshing && height <= mHeaderViewHeight) {return;}int finalHeight = 0; // default: scroll back to dismiss header.// is refreshing, just scroll back to show all the header.if (mPullRefreshing && height > mHeaderViewHeight) {finalHeight = mHeaderViewHeight;}mScrollBack = SCROLLBACK_HEADER;mScroller.startScroll(0, height, 0, finalHeight - height,SCROLL_DURATION);// trigger computeScrollinvalidate();}private void updateFooterHeight(float delta) {int height = mFooterView.getBottomMargin() + (int) delta;if (mEnablePullLoad && !mPullLoading) {if (height > PULL_LOAD_MORE_DELTA) { // height enough to invoke load// more.mFooterView.setState(XListViewFooter.STATE_READY);} else {mFooterView.setState(XListViewFooter.STATE_NORMAL);}}mFooterView.setBottomMargin(height);// setSelection(mTotalItemCount - 1); // scroll to bottom}private void resetFooterHeight() {int bottomMargin = mFooterView.getBottomMargin();if (bottomMargin > 0) {mScrollBack = SCROLLBACK_FOOTER;mScroller.startScroll(0, bottomMargin, 0, -bottomMargin,SCROLL_DURATION);invalidate();}}private void startLoadMore() {mPullLoading = true;mFooterView.setState(XListViewFooter.STATE_LOADING);if (mListViewListener != null) {mListViewListener.onLoadMore();}}@Overridepublic boolean onTouchEvent(MotionEvent ev) {if (mLastY == -1) {mLastY = ev.getRawY();}switch (ev.getAction()) {case MotionEvent.ACTION_DOWN:mLastY = ev.getRawY();break;case MotionEvent.ACTION_MOVE:final float deltaY = ev.getRawY() - mLastY;mLastY = ev.getRawY();if (getFirstVisiblePosition() == 0&& (mHeaderView.getVisiableHeight() > 0 || deltaY > 0)) {// the first item is showing, header has shown or pull down.updateHeaderHeight(deltaY / OFFSET_RADIO);invokeOnScrolling();} else if (getLastVisiblePosition() == mTotalItemCount - 1&& (mFooterView.getBottomMargin() > 0 || deltaY < 0)) {// last item, already pulled up or want to pull up.updateFooterHeight(-deltaY / OFFSET_RADIO);}break;default:mLastY = -1; // resetif (getFirstVisiblePosition() == 0) {// invoke refreshif (mEnablePullRefresh&& mHeaderView.getVisiableHeight() > mHeaderViewHeight) {mPullRefreshing = true;mHeaderView.setState(XListViewHeader.STATE_REFRESHING);if (mListViewListener != null) {mListViewListener.onRefresh();}}resetHeaderHeight();} else if (getLastVisiblePosition() == mTotalItemCount - 1) {// invoke load more.if (mEnablePullLoad&& mFooterView.getBottomMargin() > PULL_LOAD_MORE_DELTA&& !mPullLoading) {startLoadMore();}resetFooterHeight();}break;}return super.onTouchEvent(ev);}@Overridepublic void computeScroll() {if (mScroller.computeScrollOffset()) {if (mScrollBack == SCROLLBACK_HEADER) {mHeaderView.setVisiableHeight(mScroller.getCurrY());} else {mFooterView.setBottomMargin(mScroller.getCurrY());}postInvalidate();invokeOnScrolling();}super.computeScroll();}@Overridepublic void setOnScrollListener(OnScrollListener l) {mScrollListener = l;}@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {if (mScrollListener != null) {mScrollListener.onScrollStateChanged(view, scrollState);}}@Overridepublic void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {// send to user's listenermTotalItemCount = totalItemCount;if (mScrollListener != null) {mScrollListener.onScroll(view, firstVisibleItem, visibleItemCount,totalItemCount);}}public void setXListViewListener(IXListViewListener l) {mListViewListener = l;}/** * you can listen ListView.OnScrollListener or this one. it will invoke * onXScrolling when header/footer scroll back. */public interface OnXScrollListener extends OnScrollListener {public void onXScrolling(View view);}/** * implements this interface to get refresh/load more event. */public interface IXListViewListener {public void onRefresh();public void onLoadMore();}public class AutoLoadMoreListener implements OnXScrollListener {@Overridepublic void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {if (totalItemCount > visibleItemCount) {visibleLastIndex = firstVisibleItem + visibleItemCount - 1;} else {visibleLastIndex = 0;}}@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {int itemsLastIndex = getAdapter().getCount() - 1; // 数据集最后一项的索引if (scrollState == OnScrollListener.SCROLL_STATE_IDLE&& visibleLastIndex == itemsLastIndex) {// 如果是自动加载,可以在这里放置异步加载数据的代码if (mEnablePullLoad) {mPullLoading = true;mFooterView.setState(XListViewFooter.STATE_LOADING);mListViewListener.onLoadMore();}}}@Overridepublic void onXScrolling(View view) {}}}



资源地址:http://download.csdn.net/detail/u011566000/8447955

0 0
原创粉丝点击