首页 > 代码库 > 下拉刷新,上拉加载更多ListView
下拉刷新,上拉加载更多ListView
点击这里下载源码 点击这里查看更多
这里是重写ListView实现下拉刷新下拉加载的源码:
public class DropDownListView extends ListView implements OnScrollListener { private boolean isDropDownStyle = true; private boolean isOnBottomStyle = true; private boolean isAutoLoadOnBottom = false; private String headerDefaultText; private String headerPullText; private String headerReleaseText; private String headerLoadingText; private String footerDefaultText; private String footerLoadingText; private String footerNoMoreText; private Context context; /** header layout view **/ private RelativeLayout headerLayout; private ImageView headerImage; private ProgressBar headerProgressBar; private TextView headerText; private TextView headerSecondText; /** footer layout view **/ private RelativeLayout footerLayout; private ProgressBar footerProgressBar; private Button footerButton; private OnDropDownListener onDropDownListener; private OnScrollListener onScrollListener; /** rate about drop down distance and header padding top when drop down **/ private float headerPaddingTopRate = 1.5f; /** min distance which header can release to loading **/ private int headerReleaseMinDistance; /** whether bottom listener has more **/ private boolean hasMore = true; /** whether show footer loading progress bar when loading **/ private boolean isShowFooterProgressBar = true; /** whether show footer when no more data **/ private boolean isShowFooterWhenNoMore = false; private int currentScrollState; private int currentHeaderStatus; /** whether reached top, when has reached top, don't show header layout **/ private boolean hasReachedTop = false; /** image flip animation **/ private RotateAnimation flipAnimation; /** image reverse flip animation **/ private RotateAnimation reverseFlipAnimation; /** header layout original height **/ private int headerOriginalHeight; /** header layout original padding top **/ private int headerOriginalTopPadding; /** y of point which user touch down **/ private float actionDownPointY; /** whether is on bottom loading **/ private boolean isOnBottomLoading = false; public DropDownListView(Context context) { super(context); init(context); } public DropDownListView(Context context, AttributeSet attrs) { super(context, attrs); getAttrs(context, attrs); init(context); } public DropDownListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); getAttrs(context, attrs); init(context); } private void init(Context context) { this.context = context; initDropDownStyle(); initOnBottomStyle(); // should set, to run onScroll method and so on super.setOnScrollListener(this); } /** * init drop down style, only init once */ private void initDropDownStyle() { if (headerLayout != null) { if (isDropDownStyle) { addHeaderView(headerLayout); } else { removeHeaderView(headerLayout); } return; } if (!isDropDownStyle) { return; } headerReleaseMinDistance = context.getResources().getDimensionPixelSize( R.dimen.drop_down_list_header_release_min_distance); flipAnimation = new RotateAnimation(0, 180, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f); flipAnimation.setInterpolator(new LinearInterpolator()); flipAnimation.setDuration(250); flipAnimation.setFillAfter(true); reverseFlipAnimation = new RotateAnimation(-180, 0, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f); reverseFlipAnimation.setInterpolator(new LinearInterpolator()); reverseFlipAnimation.setDuration(250); reverseFlipAnimation.setFillAfter(true); headerDefaultText = context.getString(R.string.drop_down_list_header_default_text); headerPullText = context.getString(R.string.drop_down_list_header_pull_text); headerReleaseText = context.getString(R.string.drop_down_list_header_release_text); headerLoadingText = context.getString(R.string.drop_down_list_header_loading_text); LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); headerLayout = (RelativeLayout)inflater.inflate(R.layout.drop_down_list_header, this, false); headerText = (TextView)headerLayout.findViewById(R.id.drop_down_list_header_default_text); headerImage = (ImageView)headerLayout.findViewById(R.id.drop_down_list_header_image); headerProgressBar = (ProgressBar)headerLayout.findViewById(R.id.drop_down_list_header_progress_bar); headerSecondText = (TextView)headerLayout.findViewById(R.id.drop_down_list_header_second_text); headerLayout.setClickable(true); headerLayout.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { onDropDown(); } }); headerText.setText(headerDefaultText); addHeaderView(headerLayout); measureHeaderLayout(headerLayout); headerOriginalHeight = headerLayout.getMeasuredHeight(); headerOriginalTopPadding = headerLayout.getPaddingTop(); currentHeaderStatus = HEADER_STATUS_CLICK_TO_LOAD; } /** * init on bottom style, only init once */ private void initOnBottomStyle() { if (footerLayout != null) { if (isOnBottomStyle) { addFooterView(footerLayout); } else { removeFooterView(footerLayout); } return; } if (!isOnBottomStyle) { return; } footerDefaultText = context.getString(R.string.drop_down_list_footer_default_text); footerLoadingText = context.getString(R.string.drop_down_list_footer_loading_text); footerNoMoreText = context.getString(R.string.drop_down_list_footer_no_more_text); LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); footerLayout = (RelativeLayout)inflater.inflate(R.layout.drop_down_list_footer, this, false); footerButton = (Button)footerLayout.findViewById(R.id.drop_down_list_footer_button); footerButton.setDrawingCacheBackgroundColor(0); footerButton.setEnabled(true); footerProgressBar = (ProgressBar)footerLayout.findViewById(R.id.drop_down_list_footer_progress_bar); addFooterView(footerLayout); } /** * @return isDropDownStyle */ public boolean isDropDownStyle() { return isDropDownStyle; } /** * @param isDropDownStyle */ public void setDropDownStyle(boolean isDropDownStyle) { if (this.isDropDownStyle != isDropDownStyle) { this.isDropDownStyle = isDropDownStyle; initDropDownStyle(); } } /** * @return isOnBottomStyle */ public boolean isOnBottomStyle() { return isOnBottomStyle; } /** * @param isOnBottomStyle */ public void setOnBottomStyle(boolean isOnBottomStyle) { if (this.isOnBottomStyle != isOnBottomStyle) { this.isOnBottomStyle = isOnBottomStyle; initOnBottomStyle(); } } /** * @return isAutoLoadOnBottom */ public boolean isAutoLoadOnBottom() { return isAutoLoadOnBottom; } /** * set whether auto load when on bottom * * @param isAutoLoadOnBottom */ public void setAutoLoadOnBottom(boolean isAutoLoadOnBottom) { this.isAutoLoadOnBottom = isAutoLoadOnBottom; } /** * get whether show footer loading progress bar when loading * * @return the isShowFooterProgressBar */ public boolean isShowFooterProgressBar() { return isShowFooterProgressBar; } /** * set whether show footer loading progress bar when loading * * @param isShowFooterProgressBar */ public void setShowFooterProgressBar(boolean isShowFooterProgressBar) { this.isShowFooterProgressBar = isShowFooterProgressBar; } /** * get isShowFooterWhenNoMore * * @return the isShowFooterWhenNoMore */ public boolean isShowFooterWhenNoMore() { return isShowFooterWhenNoMore; } /** * set isShowFooterWhenNoMore * * @param isShowFooterWhenNoMore the isShowFooterWhenNoMore to set */ public void setShowFooterWhenNoMore(boolean isShowFooterWhenNoMore) { this.isShowFooterWhenNoMore = isShowFooterWhenNoMore; } /** * get footer button * * @return */ public Button getFooterButton() { return footerButton; } @Override public void setAdapter(ListAdapter adapter) { super.setAdapter(adapter); if (isDropDownStyle) { setSecondPositionVisible(); } } @Override public void setOnScrollListener(AbsListView.OnScrollListener listener) { onScrollListener = listener; } /** * @param onDropDownListener */ public void setOnDropDownListener(OnDropDownListener onDropDownListener) { this.onDropDownListener = onDropDownListener; } /** * @param onBottomListener */ public void setOnBottomListener(OnClickListener onBottomListener) { footerButton.setOnClickListener(onBottomListener); } @Override public boolean onTouchEvent(MotionEvent event) { if (!isDropDownStyle) { return super.onTouchEvent(event); } hasReachedTop = false; switch (event.getAction()) { case MotionEvent.ACTION_DOWN: actionDownPointY = event.getY(); break; case MotionEvent.ACTION_MOVE: adjustHeaderPadding(event); break; case MotionEvent.ACTION_UP: if (!isVerticalScrollBarEnabled()) { setVerticalScrollBarEnabled(true); } /** * set status when finger leave screen if first item visible and header status is not * HEADER_STATUS_LOADING * <ul> * <li>if current header status is HEADER_STATUS_RELEASE_TO_LOAD, call onDropDown.</li> * <li>if current header status is HEADER_STATUS_DROP_DOWN_TO_LOAD, then set header status to * HEADER_STATUS_CLICK_TO_LOAD and hide header layout.</li> * </ul> */ if (getFirstVisiblePosition() == 0 && currentHeaderStatus != HEADER_STATUS_LOADING) { switch (currentHeaderStatus) { case HEADER_STATUS_RELEASE_TO_LOAD: onDropDown(); break; case HEADER_STATUS_DROP_DOWN_TO_LOAD: setHeaderStatusClickToLoad(); setSecondPositionVisible(); break; case HEADER_STATUS_CLICK_TO_LOAD: default: break; } } break; } return super.onTouchEvent(event); } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if (isDropDownStyle) { if (currentScrollState == SCROLL_STATE_TOUCH_SCROLL && currentHeaderStatus != HEADER_STATUS_LOADING) { /** * when state of ListView is SCROLL_STATE_TOUCH_SCROLL(ListView is scrolling and finger is on screen) * and header status is not HEADER_STATUS_LOADING * <ul> * if header layout is visiable, * <li>if height of header is higher than a fixed value, then set header status to * HEADER_STATUS_RELEASE_TO_LOAD.</li> * <li>else set header status to HEADER_STATUS_DROP_DOWN_TO_LOAD.</li> * </ul> * <ul> * if header layout is not visiable, * <li>set header status to HEADER_STATUS_CLICK_TO_LOAD.</li> * </ul> */ if (firstVisibleItem == 0) { headerImage.setVisibility(View.VISIBLE); int pointBottom = headerOriginalHeight + headerReleaseMinDistance; if (headerLayout.getBottom() >= pointBottom) { setHeaderStatusReleaseToLoad(); } else if (headerLayout.getBottom() < pointBottom) { setHeaderStatusDropDownToLoad(); } } else { setHeaderStatusClickToLoad(); } } else if (currentScrollState == SCROLL_STATE_FLING && firstVisibleItem == 0 && currentHeaderStatus != HEADER_STATUS_LOADING) { /** * when state of ListView is SCROLL_STATE_FLING(ListView is scrolling but finger has leave screen) and * first item(header layout) is visible and header status is not HEADER_STATUS_LOADING, then hide first * item, set second item visible and set hasReachedTop true. */ setSecondPositionVisible(); hasReachedTop = true; } else if (currentScrollState == SCROLL_STATE_FLING && hasReachedTop) { /** * when state of ListView is SCROLL_STATE_FLING(ListView is scrolling but finger has leave screen) and * hasReachedTop is true(it's because flick back), then hide first item, set second item visible. */ setSecondPositionVisible(); } } // if isOnBottomStyle and isAutoLoadOnBottom and hasMore, then call onBottom function auto if (isOnBottomStyle && isAutoLoadOnBottom && hasMore) { if (firstVisibleItem > 0 && totalItemCount > 0 && (firstVisibleItem + visibleItemCount == totalItemCount)) { onBottom(); } } if (onScrollListener != null) { onScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount); } } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { if (isDropDownStyle) { currentScrollState = scrollState; if (currentScrollState == SCROLL_STATE_IDLE) { hasReachedTop = false; } } if (onScrollListener != null) { onScrollListener.onScrollStateChanged(view, scrollState); } } /** * drop down begin, adjust view status */ private void onDropDownBegin() { if (isDropDownStyle) { setHeaderStatusLoading(); } } /** * on drop down loading, you can call it by manual, but you should manual call onBottomComplete at the same time. */ public void onDropDown() { if (currentHeaderStatus != HEADER_STATUS_LOADING && isDropDownStyle && onDropDownListener != null) { onDropDownBegin(); onDropDownListener.onDropDown(); } } /** * drop down complete, restore view status * * @param secondText display below header text, if null, not display */ public void onDropDownComplete(CharSequence secondText) { if (isDropDownStyle) { setHeaderSecondText(secondText); onDropDownComplete(); } } /** * set header second text * * @param secondText secondText display below header text, if null, not display */ public void setHeaderSecondText(CharSequence secondText) { if (isDropDownStyle) { if (secondText == null) { headerSecondText.setVisibility(View.GONE); } else { headerSecondText.setVisibility(View.VISIBLE); headerSecondText.setText(secondText); } } } /** * drop down complete, restore view status */ public void onDropDownComplete() { if (isDropDownStyle) { setHeaderStatusClickToLoad(); if (headerLayout.getBottom() > 0) { invalidateViews(); setSecondPositionVisible(); } } } /** * on bottom begin, adjust view status */ private void onBottomBegin() { if (isOnBottomStyle) { if (isShowFooterProgressBar) { footerProgressBar.setVisibility(View.VISIBLE); } footerButton.setText(footerLoadingText); footerButton.setEnabled(false); } } /** * on bottom loading, you can call it by manual, but you should manual call onBottomComplete at the same time. */ public void onBottom() { if (isOnBottomStyle && !isOnBottomLoading) { isOnBottomLoading = true; onBottomBegin(); footerButton.performClick(); } } /** * on bottom load complete, restore view status */ public void onBottomComplete() { if (isOnBottomStyle) { if (isShowFooterProgressBar) { footerProgressBar.setVisibility(View.GONE); } if (!hasMore) { footerButton.setText(footerNoMoreText); footerButton.setEnabled(false); if (!isShowFooterWhenNoMore) { removeFooterView(footerLayout); } } else { footerButton.setText(footerDefaultText); footerButton.setEnabled(true); } isOnBottomLoading = false; } } /** * OnDropDownListener, called when header released * * @author <a href=http://www.mamicode.com/"http://www.trinea.cn" target="_blank">Trinea 2012-5-31>下拉刷新,上拉加载更多ListView
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。