Android 自定义下拉刷新上拉加载更多Listview
2015-10-12 21:37
656 查看
好久没写了。。先说一下这边隐藏头部布局的原理:
先是预备工作:上拉加载更多底部布局
然后就是自定义RefreshListview!
注释很详细,大家慢慢看一下:
这样就可以在布局中使用自己的RefreshListview了:
demo下载:demo下载链接
能看到大家的评论,我会很开心的!
//将padding设置为header的高度的负值来隐藏它 footerView.setPadding(0, -footerViewH, 0, 0);
先是预备工作:上拉加载更多底部布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:orientation="horizontal"> <ProgressBar android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:layout_marginBottom="10dp" android:indeterminate="true" android:layout_centerInParent="true" android:indeterminateDrawable="@drawable/indeterminate_drawable" android:indeterminateDuration="500" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:layout_marginBottom="10dp" android:textSize="30dp" android:layout_marginLeft="15dp" android:text="正在加载更多..."/> </LinearLayout>下拉刷新头部布局:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:orientation="horizontal"> <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:layout_marginBottom="10dp"> <ImageView android:id="@+id/iv_arrow" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:src="@drawable/indicator_arrow" /> <ProgressBar android:id="@+id/pb_ratate" android:layout_width="wrap_content" android:layout_height="wrap_content" android:visibility="invisible" android:indeterminate="true" android:layout_centerInParent="true" android:indeterminateDrawable="@drawable/indeterminate_drawable" android:indeterminateDuration="500" /> </RelativeLayout> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:layout_marginBottom="10dp" android:orientation="vertical" android:layout_gravity="center" android:gravity="center"> <TextView android:id="@+id/tv_state" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="20dp" android:textColor="#aa000000" android:text="下拉刷新" /> <TextView android:id="@+id/tv_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="18dp" android:textColor="#99666666" android:text="最后刷新:2015-12-03" /> </LinearLayout> </LinearLayout>
然后就是自定义RefreshListview!
注释很详细,大家慢慢看一下:
public class RefreshListView extends ListView implements AbsListView.OnScrollListener { private View headView; private ImageView iv_arrow;//箭头图标 private ProgressBar pb_ratate;//刷新中图标 private TextView tv_state;//刷新状态文本 private TextView tv_time;//最新刷新时间 private View footerView; private int headViewH; private int footerViewH; //触摸点Y的坐标 private int downY; private final int PULL_REFRESH = 0;//下拉刷新的状态 private final int RELEASE_REFRESH = 1;//松开刷新的状态 private final int REFRESHING = 2;//正在刷新状态 private int currentState = PULL_REFRESH;//当前状态,默认为下拉刷新状态 private boolean isLoadingMore = false;//是否加载更多 private RotateAnimation upAnimation; private RotateAnimation downAnimation; public RefreshListView(Context context) { super(context); init(); } public RefreshListView(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { setOnScrollListener(this); initHeaderView(); initRotateAnimation(); initFooterView(); } /** * 初始化headerview */ private void initHeaderView() { headView = View.inflate(getContext(), R.layout.layout_header, null); iv_arrow = (ImageView) headView.findViewById(R.id.iv_arrow); pb_ratate = (ProgressBar) headView.findViewById(R.id.pb_ratate); tv_state = (TextView) headView.findViewById(R.id.tv_state); tv_time = (TextView) headView.findViewById(R.id.tv_time); //通知系统主动去测量 headView.measure(0, 0); //getMeasuredHeight()获取测量后的高度 headViewH = headView.getMeasuredHeight(); //将padding设置为header的高度的负值来隐藏它 headView.setPadding(0, -headViewH, 0, 0); addHeaderView(headView); } private void initRotateAnimation() { upAnimation = new RotateAnimation(0, -180, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f); upAnimation.setDuration(300); upAnimation.setFillAfter(true); downAnimation = new RotateAnimation(-180, -360, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f); downAnimation.setDuration(300); downAnimation.setFillAfter(true); } /** * 初始化FooterView */ private void initFooterView() { footerView = View.inflate(getContext(), R.layout.layout_footer, null); //通知系统主动去测量 footerView.measure(0, 0); //getMeasuredHeight()获取测量后的高度 footerViewH = footerView.getMeasuredHeight(); //将padding设置为header的高度的负值来隐藏它 footerView.setPadding(0, -footerViewH, 0, 0); addFooterView(footerView); } @Override public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: downY = (int) ev.getY(); break; case MotionEvent.ACTION_MOVE: if (currentState == REFRESHING) { break; } int delaY = (int) (ev.getY() - downY); //距离顶部的大小 int paddingTop = -headViewH + delaY; //只有当paddingTop> -headViewH,且第一项为首项时才进行拦截 if (paddingTop > -headViewH && getFirstVisiblePosition() == 0) { headView.setPadding(0, paddingTop, 0, 0); if (paddingTop >= 0 && currentState == PULL_REFRESH) { //从下拉刷新进去松开刷新状态 currentState = RELEASE_REFRESH; refreshHeadView(); } else if (paddingTop < 0 && currentState == RELEASE_REFRESH) { //进去下拉刷新状态 currentState = PULL_REFRESH; refreshHeadView(); } return true;//拦截TOUCH_MOVE,不让listview处理move事件 } break; case MotionEvent.ACTION_UP: if (currentState == PULL_REFRESH) { headView.setPadding(0, -headViewH, 0, 0); } else if (currentState == RELEASE_REFRESH) { headView.setPadding(0, 0, 0, 0); currentState = REFRESHING; refreshHeadView(); if (onRefreshListener != null) { onRefreshListener.onPullRefresh(); } } break; } return super.onTouchEvent(ev); } /** * 根据currentState改变headview */ private void refreshHeadView() { switch (currentState) { case PULL_REFRESH: tv_state.setText("下拉刷新"); iv_arrow.startAnimation(downAnimation); break; case RELEASE_REFRESH: tv_state.setText("松开刷新"); iv_arrow.startAnimation(upAnimation); break; case REFRESHING: tv_state.setText("正在拼命加载中..."); iv_arrow.clearAnimation();//因为向上旋转的动画有可能还未完成 iv_arrow.setVisibility(View.INVISIBLE); pb_ratate.setVisibility(VISIBLE); break; } } /** * 完成刷新,重置状态,在获取完数据并更新完adapter之后,在UI线程中调用 */ public void completeRefresh() { if (isLoadingMore){ footerView.setPadding(0,0,0,-footerViewH); isLoadingMore=false; }else { headView.setPadding(0, -headViewH, 0, 0); currentState = PULL_REFRESH; pb_ratate.setVisibility(INVISIBLE); iv_arrow.setVisibility(VISIBLE); tv_state.setText("下拉刷新"); tv_time.setText("最后刷新" + getCurrentTime()); } } /** * 获取当前系统时间,并格式化 * * @return */ private String getCurrentTime() { SimpleDateFormat format = new SimpleDateFormat("yy-MM-dd HH:mm:ss"); return format.format(new Date()); } /** * 提供监听接口,监听加载数据 */ private OnRefreshListener onRefreshListener; public void setOnRefreshListener(OnRefreshListener onRefreshListener) { this.onRefreshListener = onRefreshListener; } public interface OnRefreshListener { void onPullRefresh(); void onLoadingMore(); } /** * scrollState: * SCROLL_STATE_IDLE = 0;闲置状态,手指触摸结束 * SCROLL_STATE_TOUCH_SCROLL = 1;手指触摸滚动,就是手指按着滑动 * SCROLL_STATE_FLING = 2;惯性滑动,就是手指快速滑动 * * @param view * @param scrollState */ @Override public void onScrollStateChanged(AbsListView view, int scrollState) { /** * @return The number of items owned by the Adapter associated with this * AdapterView. (This is the number of data items, which may be * larger than the number of visible views.) */ if (scrollState == SCROLL_STATE_IDLE && getLastVisiblePosition() == (getCount() - 1) && !isLoadingMore) { isLoadingMore=true; footerView.setPadding(0, 0, 0, 0); setSelection(getCount()); if (onRefreshListener!=null){ onRefreshListener.onLoadingMore(); } } } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { } }
这样就可以在布局中使用自己的RefreshListview了:
<com.chenshi.myrefleshview.RefreshListView android:id="@+id/refreshlistview" android:layout_width="match_parent" android:layout_height="match_parent" />
demo下载:demo下载链接
能看到大家的评论,我会很开心的!
相关文章推荐
- Android view手势缩放与移动
- 利用Android studio快速搭建安卓开发环境
- Android音乐编程:管理音频焦点
- 初学android第一章、第二章
- Android 那些你所不知道的Bitmap对象详解
- [Android]实现ListView的删除功能
- android 代码绘制转盘抽奖的实现
- android数据访问模式:档、SharedPreferences
- Android中自定义Adapter的基本原理
- Android开发调试中遇到的Waiting for HOME解决方案
- Android中Menu的基本用法
- android arcelable 传递 boolean值
- android view SurfaceView GLSurfaceView的关系和区别
- android源码编译出错(3)
- android事件分发机制
- Android笔记---LayoutInflater作用
- Android开发相关的Blog推荐——跟随大神的脚步才能成长为大神
- Android-多媒体编程
- Android中Adapter之BaseAdapter使用
- Android Service的使用解析