Android自定义控件-ListViewForRefresh
2015-05-04 16:28
357 查看
欢迎加入QQ群探讨Android开发技术—>QQ群【软件开发-Android】:314896948
功能描述:支持自定义顶部视图,以视图+ListView方式展示
支持下拉刷新,可选择打开或关闭
支持加载更多,可选择打开或关闭
使用步骤:
调用addCustomHeadView添加顶部视图,如轮播广告图等。[code]mListView.addCustomHeadView(View.inflate(this, R.layout.view_custom, null));
调用enablePullDownRefresh和enableLoadMoreRefresh分别设置打开或关闭下拉刷新、加载更多.
[code]mListView.enablePullDownRefresh(true); mListView.enableLoadMoreRefresh(true);
调用setOnRefreshListener设置监听,在回调接口中实现数据加载,数据加载完成发送消息通知视图刷新.
[code]mListView.setOnRefreshListener(mListener);
监听mListener如下:
[code]private onRefreshListener mListener = new onRefreshListener() { @Override public void onPullDownRefresh() { // 异步加载数据 new Thread(new Runnable() { @Override public void run() { SystemClock.sleep(3000); mData.add(0, "test--data-->newdata"); mHandler.obtainMessage(WHAT_DATA_LOAD_FINISH).sendToTarget(); } }).start(); } @Override public void onLoadMoreRefresh() { // 异步加载数据 new Thread(new Runnable() { @Override public void run() { SystemClock.sleep(3000); mData.add("test--data-->newdata"); mHandler.obtainMessage(WHAT_DATA_LOAD_FINISH).sendToTarget(); } }).start(); } };
接收到消息后关闭刷新视图
[code]private Handler mHandler = new Handler(Looper.getMainLooper()) { public void handleMessage(android.os.Message msg) { switch (msg.what) { case WHAT_DATA_LOAD_FINISH: mListView.FinishRefesh(); mAdapter.notifyDataSetChanged(); break; } }; }
效果图:
下拉刷新
加载更多
直接上代码—>自定义RefreshListView code:
[code]package com.leo.demo; import java.text.SimpleDateFormat; import java.util.Date; import android.annotation.SuppressLint; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.animation.Animation; import android.view.animation.RotateAnimation; import android.widget.AbsListView; import android.widget.AbsListView.OnScrollListener; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; public class RefreshListView extends ListView implements OnScrollListener { private static final String TAG = "RefreshListView"; private static final Boolean DEBUG = false; /** 头控件整个布局(包含下拉刷新和用户自定义需要添加的控件) */ private LinearLayout mHeadView; /** 下拉刷新控件 */ private View mPullDownHeadView; /** 下拉刷新布局高度 */ private int mPullDownHeadViewHeigth; /** 触摸按下的Y坐标 */ private int downY = -1; /** 下拉刷新状态 */ private static final int STATE_PULL_DOWN_REFRESH = 0x000; /** 释放刷新状态 */ private static final int STATE_RELEASE_REFRESH = 0x001; /** 正在刷新状态 */ private static final int STATE_REFRESHING = 0x002; /** 当前刷新状态 */ private int currentState = STATE_PULL_DOWN_REFRESH;// 默认是下拉刷新状态 /** 向上旋转动画 */ private RotateAnimation upRa; /** 向下旋转动画 */ private RotateAnimation downRa; /** 下拉刷新 动画箭头 */ private ImageView mRefreshArrow; /** 下拉刷新 进度环 */ private ProgressBar mRefreshProgressBar; /** 下拉刷新 状态文字显示 */ private TextView mRefreshState; /** 下拉刷新 上次刷新时间 */ private TextView mRefreshDate; /** 用户自定义的需要加在头部的view */ private View mCustomView; /** ListView左上角在屏幕上的位置Y */ private int mListViewHeigthOnScreen = -1; /** 刷新列表回调监听器 */ private onRefreshListener mListener; /** 底部加载更多控件 */ private View mLoadMoreView; /** 底部加载更多控件的测量高度 */ private int mLoadMoreViewHeight; /** 是否加载更多 */ private boolean isLoadMore = false; /** 是否启用下拉刷新 (默认关闭下拉刷新) */ private boolean isEnablePullDownRefresh = false; /** 是否启用加载更多 (默认关闭加载更多) */ private boolean isEnableLoadMoreRefresh = false; public RefreshListView(Context context) { super(context); initHeadView(); initFootView(); } public RefreshListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initHeadView(); initFootView(); } public RefreshListView(Context context, AttributeSet attrs) { super(context, attrs); initHeadView(); initFootView(); } /** 初始化底部加载更多控件 */ private void initFootView() { mLoadMoreView = View.inflate(getContext(), R.layout.refresh_load_more, null); mLoadMoreView.measure(0, 0); mLoadMoreViewHeight = mLoadMoreView.getMeasuredHeight(); mLoadMoreView.setPadding(0, -mLoadMoreViewHeight, 0, 0); this.addFooterView(mLoadMoreView); this.setOnScrollListener(this);// 给当前Listview设置一个滑动的监听事件 } /** 初始化头部下拉刷新控件 */ private void initHeadView() { mHeadView = (LinearLayout) View.inflate(getContext(), R.layout.refresh_pull_down, null); mPullDownHeadView = mHeadView.findViewById(R.id.ll_pull_down_refresh_root); mRefreshArrow = (ImageView) mHeadView.findViewById(R.id.iv_pull_dowd_refresh_arrow); mRefreshProgressBar = (ProgressBar) mHeadView.findViewById(R.id.pb_pull_dowd_refresh_progressbar); mRefreshState = (TextView) mHeadView.findViewById(R.id.tv_pull_dowd_refresh_state_desc); mRefreshDate = (TextView) mHeadView.findViewById(R.id.tv_pull_dowd_refresh_date); mRefreshDate.setText("上次刷新:" + getCurentTime());// 设置默认显示上次刷新时间 mPullDownHeadView.measure(0, 0);// 测量,以获取测量高度 mPullDownHeadViewHeigth = mPullDownHeadView.getMeasuredHeight(); mPullDownHeadView.setPadding(0, -mPullDownHeadViewHeigth, 0, 0);// 默认隐藏头控件 this.addHeaderView(mHeadView);// 添加到头控件中 initAnimation();// 初始化箭头动画 } /** 初始化头部控件中箭头的旋转动画 */ private void initAnimation() { upRa = new RotateAnimation(0, -180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); upRa.setDuration(500); upRa.setFillAfter(true); downRa = new RotateAnimation(-180, -360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); downRa.setDuration(500); downRa.setFillAfter(true); } /** 在头部控件内添加用户自定义的view */ public void addCustomHeadView(View v) { this.mCustomView = v; mHeadView.addView(v); } @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: downY = (int) ev.getY(); break; case MotionEvent.ACTION_MOVE: if (downY == -1) { downY = (int) ev.getY(); } // 如果是没有启用下拉刷新 则跳出循环 if (!isEnablePullDownRefresh) { break; } // 如果当前是正在刷新中,则跳出循环 if (currentState == STATE_REFRESHING) { break; } // 判断添加的顶部View是否完全显示了, 如果没有完全显示,跳出switch语句, 执行父元素的touch事件. if (mCustomView != null) { int[] location = new int[2];// 0位是x轴的值, 1位是y轴的值 // 获取Listview在屏幕中y轴的值. if (mListViewHeigthOnScreen == -1) { this.getLocationOnScreen(location); mListViewHeigthOnScreen = location[1]; showLog("ListView--Y:" + mListViewHeigthOnScreen); } // 获取mCustomHeaderView在屏幕y轴的值. mCustomView.getLocationOnScreen(location); int mCustomViewHeigthOnScreen = location[1]; showLog("mCustomView--Y:" + mCustomViewHeigthOnScreen); if (mCustomViewHeigthOnScreen < mListViewHeigthOnScreen) { break;// 未完全显示自定义的view,jump out } } int moveY = (int) ev.getY(); int dy = moveY - downY; if (dy > 0 && getFirstVisiblePosition() == 0) { // 如果是下拉,并且当前第一个可视条目是列表中的第一个,可以拉出头控件 int paddingTop = -mPullDownHeadViewHeigth + dy; if (paddingTop > 0 && currentState != STATE_RELEASE_REFRESH) { // 完全拉出来了,并且当前状态不是释放刷新,则切换到释放刷新状态 currentState = STATE_RELEASE_REFRESH; changeRefreshState(); } else if (paddingTop < 0 && currentState != STATE_PULL_DOWN_REFRESH) { // 没有完全拉出来,并且当前状态不是下拉刷新,则切换到下拉刷新状态 currentState = STATE_PULL_DOWN_REFRESH; changeRefreshState(); } mPullDownHeadView.setPadding(0, paddingTop, 0, 0); return true; } break; case MotionEvent.ACTION_UP: downY = -1; if (currentState == STATE_PULL_DOWN_REFRESH) { // 如果当前是下拉刷新状态,则直接隐藏 mPullDownHeadView.setPadding(0, -mPullDownHeadViewHeigth, 0, 0); } else if (currentState == STATE_RELEASE_REFRESH) { // 如果当前是释放刷新状态,则切换到正在刷新 currentState = STATE_REFRESHING; changeRefreshState(); mPullDownHeadView.setPadding(0, 0, 0, 0); // 回调用户处理操作 if (mListener != null) { mListener.onPullDownRefresh(); } } break; } return super.onTouchEvent(ev); } /** 切换当前头控件显示的刷新状态 */ private void changeRefreshState() { switch (currentState) { case STATE_PULL_DOWN_REFRESH: // 下拉刷新 mRefreshArrow.startAnimation(downRa); mRefreshState.setText("下拉刷新"); break; case STATE_RELEASE_REFRESH: // 释放刷新 mRefreshArrow.startAnimation(upRa); mRefreshState.setText("释放刷新"); break; case STATE_REFRESHING: // 正在刷新 mRefreshArrow.clearAnimation(); mRefreshArrow.setVisibility(View.INVISIBLE); mRefreshProgressBar.setVisibility(View.VISIBLE); mRefreshState.setText("正在刷新中..."); break; } } /** 当刷新完成后调用此方法,隐藏头部上拉刷新和底部加在更多 */ public void FinishRefesh() { if (isLoadMore) { // 隐藏加载更多,复位变量 isLoadMore = false; mLoadMoreView.setPadding(0, -mLoadMoreViewHeight, 0, 0); } else { // 隐藏上拉刷新,复位变量 mPullDownHeadView.setPadding(0, -mPullDownHeadViewHeigth, 0, 0); currentState = STATE_PULL_DOWN_REFRESH; mRefreshState.setText("下拉刷新"); mRefreshArrow.setVisibility(View.VISIBLE); mRefreshProgressBar.setVisibility(View.INVISIBLE); mRefreshDate.setText("上次刷新:" + getCurentTime()); } } /** 获取当前时间, 格式为: 1990-09-09 09:09:09 */ @SuppressLint("SimpleDateFormat") private String getCurentTime() { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); return format.format(new Date()); } /** 下拉刷新回调接口 */ public interface onRefreshListener { /** 下拉刷新 加载数据处理 */ void onPullDownRefresh(); /** 加载更多 加载数据处理 */ void onLoadMoreRefresh(); } /** 设置下拉刷新回调监听器 */ public void setOnRefreshListener(onRefreshListener listener) { this.mListener = listener; } /** 监听滑动状态,设置加载更多 */ @Override public void onScrollStateChanged(AbsListView view, int scrollState) { if (!isEnableLoadMoreRefresh) { return;// false 关闭加载更多,直接返回 } if (currentState == SCROLL_STATE_IDLE || currentState == SCROLL_STATE_FLING) { if (getLastVisiblePosition() == getCount() - 1 && !isLoadMore) { // 滑动到listview最后一个条目,显示加载更多 isLoadMore = true; mLoadMoreView.setPadding(0, 0, 0, 0);// 显示加载更多控件 setSelection(getCount());// 显示最后一个条目 // 处理用户的回调操作 if (mListener != null) { mListener.onLoadMoreRefresh(); } } } } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { } /** 是否启用下拉刷新 */ public void enablePullDownRefresh(boolean isEnable) { this.isEnablePullDownRefresh = isEnable; } /** 是否启用加载更多 */ public void enableLoadMoreRefresh(boolean isEnable) { this.isEnableLoadMoreRefresh = isEnable; } /** 打印log信息 */ private static void showLog(String msg) { if (DEBUG) { Log.e(TAG, msg); } } }
相关文章推荐
- Android PullToRrefresh 自定义下拉刷新动画 (listview、scrollview等)
- Android自定义控件——ListView的下拉刷新与上拉加载
- android 自定义ListView下拉刷新控件——自定义控件学习(五)
- Android自定义控件——ListView的下拉刷新与上拉加载
- Android使用PullToRefresh完成ListView下拉刷新和左滑删除功能
- ArrayIndexOutOfBoundsException with custom Android Adapter for multiple views in ListView
- Android PullToRefresh 实战(ListView)
- android ListView上拉加载更多 下拉刷新功能实现(采用pull-to-refresh)
- Android 的上下文菜单: Context Menu,registerForContextMenu(getListView())
- Android-自定义控件基础-ListView的加载更多
- Android自定义控件——ListView的下拉刷新与上拉加载
- Android 自定义控件PullToZoomListView
- Android PullToRefresh (ListView GridView 下拉刷新) 使用详解
- Android PullToRefresh (ListView GridView 下拉刷新) 使用详解
- 【Android基础】PullToRefreshListView OnItemLongClickListener长按事件
- “PullToRefreshListView 在Android 4.1 (Jelly Bean)中点击没反应”的解决方法
- 使用Android-PullToRefresh库中的PullToRefreshListView添加header时遇到的问题
- Android自定义控件实战——实现仿IOS下拉刷新上拉加载 PullToRefreshLayout
- android how to deal with data when listview refresh
- Android PullToRrefresh 自定义下拉刷新动画 (listview、scrollview等)