ListView的下拉刷新和上拉加载
来源:互联网 发布:php源码 虚拟股票 编辑:程序博客网 时间:2024/05/24 01:40
我们公司以前有道面试题,让开发人员当场写一个ListView的下拉刷新和上拉加载,时间2个小时左右,允许有微量Bug。
自己想一想,也不知道能不能写的出来,所以今天有时间,参考了网上的一些资料,先写一个练手下。先看下效果图:
实现原理
ListView有一个addHeaderView()和addFooterView()方法,就是添加一个头布局和一个脚布局。主要通过这两个方法来实现。
初始化的时候,添加头布局和脚布局。然后把头布局的paddingTop设置为负的头布局高度,这样头布局就会看不见了。脚布局同样处理。
在手指滑动的时候,不断的去改变paddingTop的值,这样,就形成下拉的效果了。
注意:对于ListView判断滑动到顶部和底部的监听
ListView自带一个setOnScrollListener()监听器,主要用来监听它的滑动时间的。
@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) { switch (scrollState) { case OnScrollListener.SCROLL_STATE_IDLE: //空闲状态,停止滚动 break; case OnScrollListener.SCROLL_STATE_FLING: // 手指快速滚动 break; case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL: // 正在滚动 break; }}@Overridepublic void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {}
调用方法
- 直接引用PullToRefreshListView类到你的工程,copy布局文件。
- 由于下拉刷新的头布局和上拉加载的布局是固定的,没有提供接口动态加载。所有如果要引用的话,得去修改xml文件。
- 可以禁止下拉刷新或者上拉加载,通过setNeedPullToRefresh()和setNeedLoadMore()方法。
- 每次刷新完毕,请调用refreshComplete()方法。
- setOnRefreshListener()设置下拉和上拉的监听回调。
package com.geek.widget;import java.text.SimpleDateFormat;import java.util.Locale;import com.zhou.customviewone.R;import android.annotation.SuppressLint;import android.content.Context;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.widget.AbsListView;import android.widget.AbsListView.OnScrollListener;import android.widget.ImageView;import android.widget.ListView;import android.widget.ProgressBar;import android.widget.TextView;/** * * 下拉刷新和上拉加载的ListView * * @author LeeShenzhou * */public class PullToRefreshListView extends ListView implements OnScrollListener { // 头布局 private View mHeaderView; private ImageView mImageArrow; private ProgressBar mProgressBar; private TextView mTxtState; private TextView mTxtUpdateTime; // 脚布局 private View mFooterView; // 头布局的高度 private int headerHeight; // 脚布局的高度 private int footerHeight; private int mDownY; // 下拉刷新 private final int DOWN_REFRESH = 0; // 松开刷新 private final int RELEASE_REFRESH = 1; // 正在刷新中 private final int REFRESHING = 2; private int currentState = DOWN_REFRESH; private boolean isLoadMore; // 是否需要下拉刷新 private boolean isNeedPullToRefresh; // 是否需要上拉加载更多 private boolean isNeedLoadMore; /** * 是否需要下拉刷新 */ public void setNeedPullToRefresh(boolean need) { this.isNeedPullToRefresh = need; } /** * 是否需要上拉加载更多 */ public void setNeedLoadMore(boolean need) { this.isNeedLoadMore = need; } /** * 刷新完成 */ public void refreshComplete() { isLoadMore = false; currentState = DOWN_REFRESH; mHeaderView.setPadding(0, -headerHeight, 0, 0); mFooterView.setPadding(0, -footerHeight, 0, 0); } private OnRefreshListener listener; public void setOnRefreshListener(OnRefreshListener listener) { this.listener = listener; } public PullToRefreshListView(Context context) { super(context); init(); } public PullToRefreshListView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public PullToRefreshListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } private void init() { isNeedLoadMore = true; isNeedPullToRefresh = true; isLoadMore = false; // 初始化头布局 mHeaderView = View.inflate(getContext(), R.layout.layout_pull_to_refresh_header, null); mImageArrow = (ImageView) mHeaderView.findViewById(R.id.header_image_arrow); mProgressBar = (ProgressBar) mHeaderView.findViewById(R.id.header_pb); mTxtState = (TextView) mHeaderView.findViewById(R.id.header_state); mTxtUpdateTime = (TextView) mHeaderView.findViewById(R.id.header_update_time); mHeaderView.measure(0, 0); // 系统会帮我们测量出HeaderView的高度 headerHeight = mHeaderView.getMeasuredHeight(); mHeaderView.setPadding(0, -headerHeight, 0, 0); addHeaderView(mHeaderView); // 初始化脚布局 mFooterView = View.inflate(getContext(), R.layout.layout_pull_to_refresh_footer, null); mFooterView.measure(0, 0); footerHeight = mFooterView.getMeasuredHeight(); mFooterView.setPadding(0, -footerHeight, 0, 0); addFooterView(mFooterView); // 设置最后刷新时间 setLastUpdateTime(); setOnScrollListener(this); } private void setLastUpdateTime() { SimpleDateFormat sdf = new SimpleDateFormat("HH:mm", Locale.getDefault()); String time = sdf.format(System.currentTimeMillis()); if (mTxtUpdateTime != null) { mTxtUpdateTime.setText("最新更新: " + time); } } @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouchEvent(MotionEvent ev) { if (!isNeedPullToRefresh) { return super.onTouchEvent(ev); } switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: mDownY = (int) ev.getY(); break; case MotionEvent.ACTION_MOVE: int moveY = (int) ev.getY(); final int offset = (moveY - mDownY) / 2; int paddingTop = -headerHeight + offset; if (getFirstVisiblePosition() == 0 && paddingTop > -headerHeight) { if (currentState != REFRESHING) { if (offset > headerHeight && currentState == DOWN_REFRESH) { // 完全显示了 currentState = RELEASE_REFRESH; changeHeaderView(); } else if (offset < headerHeight && currentState == RELEASE_REFRESH) { // 没有显示完全 currentState = DOWN_REFRESH; changeHeaderView(); } } if (currentState == REFRESHING) { mHeaderView.setPadding(0, offset, 0, 0); } else { mHeaderView.setPadding(0, paddingTop, 0, 0); } } break; case MotionEvent.ACTION_UP: if (currentState == REFRESHING) { mHeaderView.setPadding(0, 0, 0, 0); setSelection(0); return super.onTouchEvent(ev); } // 判断当前的状态是松开刷新还是下拉刷新 if (currentState == RELEASE_REFRESH) { mHeaderView.setPadding(0, 0, 0, 0); currentState = REFRESHING; changeHeaderView(); setSelection(0); if (listener != null) { listener.onPullToRefresh(); } } else if (currentState == DOWN_REFRESH) { mHeaderView.setPadding(0, -headerHeight, 0, 0); } break; default: break; } return super.onTouchEvent(ev); } private void changeHeaderView() { switch (currentState) { case DOWN_REFRESH: // 下拉刷新 mTxtState.setText("下拉刷新"); mProgressBar.setVisibility(View.GONE); mImageArrow.setVisibility(View.VISIBLE); mImageArrow.setImageResource(R.drawable.arrow_down); break; case RELEASE_REFRESH: // 松开刷新 mTxtState.setText("释放立即刷新"); mProgressBar.setVisibility(View.GONE); mImageArrow.setVisibility(View.VISIBLE); mImageArrow.setImageResource(R.drawable.arrow_pull); break; case REFRESHING: // 正在刷新 mImageArrow.setVisibility(View.GONE); mProgressBar.setVisibility(View.VISIBLE); mTxtState.setText("正在刷新..."); break; default: break; } } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { if (!isNeedLoadMore || isLoadMore) { return; } if (scrollState == SCROLL_STATE_IDLE || scrollState == SCROLL_STATE_FLING) { // 判断当前是否已经到了底部 if (getLastVisiblePosition() == (getCount() - 1)) { isLoadMore = true; mFooterView.setPadding(0, 0, 0, 0); setSelection(getCount()); if (listener != null) { listener.onLoadMore(); } } } } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if (firstVisibleItem != 0) { // 重置刷新状态 if (currentState != REFRESHING) { currentState = DOWN_REFRESH; } } } public interface OnRefreshListener { /** * 下拉刷新 */ void onPullToRefresh(); /** * 上拉加载更多 */ void onLoadMore(); }}
源码下载:https://git.oschina.net/nszKnife/AndroidView
0 0
- ListView的上拉加载和下拉刷新的使用
- 下拉刷新+上拉加载的listview
- listview的上拉刷新,下拉加载
- listview的上拉加载,下拉刷新
- 下拉刷新和上拉加载的ListView-MutilListView
- 关于ListView的下拉刷新和上拉加载功能
- listview的下拉刷新和上拉加载更多
- listview的上拉加载更多和下拉刷新
- ListView的下拉刷新和上拉加载
- 自定义控件-下拉刷新和上拉加载的listView
- 自定义listview的下拉刷新和上拉加载
- ListView,GridView的下拉刷新和上拉加载。
- 自定义ListView的下拉刷新和上拉加载更多
- ListView的下拉刷新和上拉加载(一)
- ListView的下拉刷新和上拉加载
- ListView下拉刷新和上拉加载更多的实现
- 实现ListView的下拉刷新和上拉加载
- 实现ListView的上拉刷新和下拉加载
- 爬虫初体验,解析网页Table
- 【转帖】OpenGL的版本历史和发展 (2013-07-24 14:57:28)
- 299. Bulls and Cows#2(Done)
- Ubuntu16.04 LTS 版安装VMwareTools的步骤和没法挂载目录问题的解决
- 201612-1 试题名称:最大波动(100分)ccf认证
- ListView的下拉刷新和上拉加载
- 配置文件类 Properties
- 在Kali Linux下实战Nmap的秘诀
- java - 继承 ,重写
- 水表项目 水表数字识别率分析
- Nao机器人学习(二)
- 从C到C++(二)
- 机器学习算法学习计划
- 总结