Listview pull-down refresh

Source: Internet
Author: User

public class MyListView extends ListView implements OnScrollListener {private static final int STATE_NORMAL = 0;  // 正常状态private static final int STATE_PULL = 1;    // 下来状态private static final int STATE_RELEASE = 2; // 释放状态private static final int STATE_LOADING = 3; // 数据加载状态 private View mHeaderView;   // listview的headerviewprivate ImageView mImage;   // headerview中图片private ProgressBar mProgress; // headerview中的progressbarprivate TextView mText;      // headerview中的文本 private RotateAnimation mAnim1;  // headerview中图片的旋转动画private RotateAnimation mAnim2;  // 同上private boolean isNowAtUp;  // 判断当前是不是在listview的最上面 private int mHeaderHeight;  // headerview的高度private int mFirstVisibleItem;  // 保存listview中第一个可见项private int mScrollState;  // 保存listview滑动的状态private int mState;  // 保存判断的状态,同上面的常量进行比较,private int mStartY; // 开始下拉的y值private OnPullRefreshListener mListener;  // 回调接口 public MyListView(Context context, AttributeSet attrs) {super(context, attrs);initView();} public MyListView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);initView();} // 初始化viewprivate void initView() {// 加载headerviewmHeaderView = LayoutInflater.from(getContext()).inflate(R.layout.header_layout, null);//获取headerview中组件mImage = (ImageView) mHeaderView.findViewById(R.id.image);mProgress = (ProgressBar) mHeaderView.findViewById(R.id.progress);mText = (TextView) mHeaderView.findViewById(R.id.text);// 初始化动画initAnimation();// 因为下面要用到headerview的高度,但在处理化的时候还没有进行onMeasure// 所以要手工进行测量measureView(mHeaderView);// 获取headerview的高度mHeaderHeight = mHeaderView.getMeasuredHeight();// 设置headerview的上padding// 为负的高度,则隐藏掉headerviewsetPaddingTop(-mHeaderHeight);// 将headerview添加到listview中addHeaderView(mHeaderView); // 监听滚动setOnScrollListener(this);} // 初始化动画private void initAnimation() {mAnim1 = new RotateAnimation(180, 0,RotateAnimation.RELATIVE_TO_SELF, 0.5f,RotateAnimation.RELATIVE_TO_SELF, 0.5f); mAnim2 = new RotateAnimation(0, 180,RotateAnimation.RELATIVE_TO_SELF, 0.5f,RotateAnimation.RELATIVE_TO_SELF, 0.5f);mAnim1.setDuration(500);mAnim2.setDuration(500);mAnim1.setFillAfter(true);mAnim2.setFillAfter(true);} // 设置headerview的paddingprivate void setPaddingTop(int top) {mHeaderView.setPadding(mHeaderView.getPaddingLeft(),top,mHeaderView.getPaddingRight(),mHeaderView.getPaddingBottom()); invalidate();} // 测量viewprivate void measureView(View view) {// 先获取LayoutParamsViewGroup.LayoutParams lp = view.getLayoutParams();if (null == lp) {lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);} // 第一个参数是spec// 第二个参数是padding// 第三个参数是我期望的大小// 如果第三个参数小于0// 则返回的结果是第一个参数减去第二个参数// 如果第三个参数不小于0// 则返回第三个参数int widthMeasureSpec = ViewGroup.getChildMeasureSpec(0, 0, lp.width);int height = lp.height;int heightMeasureSpec; // 生成height的Specif (height > 0) {heightMeasureSpec = MeasureSpec.makeMeasureSpec(height,MeasureSpec.EXACTLY);} else {heightMeasureSpec = MeasureSpec.makeMeasureSpec(0,MeasureSpec.UNSPECIFIED);} // 测量view,这样就可以获取headerview的高度了// 否则headerview的高度获取出来为0// MATCH_PARENT=-1, WRAP_CONTENT=-2view.measure(widthMeasureSpec, heightMeasureSpec);} // 滑动状态该类@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {// 保存下当前的状态mScrollState = scrollState;} @Overridepublic void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {// 保存当前第一个可见项mFirstVisibleItem = firstVisibleItem;} // 监听touch事件@Overridepublic boolean onTouchEvent(MotionEvent ev) {switch (ev.getAction()) {case MotionEvent.ACTION_DOWN:// 如果是按下操作// 并且现在第一个可见项是listview的第一项// 即:现在在最上面if (mFirstVisibleItem == 0) {isNowAtUp = true;  // 记录现在是在最上面mStartY = (int) ev.getY(); // 获取点击的y坐标}break;case MotionEvent.ACTION_MOVE:onMove(ev);  // 在onMove中处理移动事件break;case MotionEvent.ACTION_UP:// 如果当前状态是可释放状态if(mState == STATE_RELEASE) {// 那个up后, 修改状态为数据加载状态mState = STATE_LOADING;// 刷新界面refreshView();// 调用回调接口中的方法// 具体实现在activity中mListener.onPull();}else if(mState == STATE_PULL){  // 如果是下拉状态mState = STATE_NORMAL; // 则更改状态为正常状态,因为还没有拉到加载数据的程度refreshView(); // 刷新界面}break;}return super.onTouchEvent(ev);} // 刷新界面,其实是更改headerview中子view的状态private void refreshView() {switch (mState) {case STATE_NORMAL:setPaddingTop(-mHeaderHeight);  // 如果是正常状态,则将headerview隐藏了break;case STATE_PULL:  // 如果是下拉状态mProgress.setVisibility(View.GONE); // 隐藏progressbarmImage.setVisibility(View.VISIBLE); // 将图片显示出来mImage.clearAnimation(); // 清除动画mImage.startAnimation(mAnim1); // 设置旋转动画mText.setText("下拉刷新!");  // 更新textview的文本break;case STATE_RELEASE:  // 释放状态mProgress.setVisibility(View.GONE);  // 隐藏progressbarmImage.setVisibility(View.VISIBLE);  // 将图片显示出来mImage.clearAnimation(); // 清除动画mImage.startAnimation(mAnim2); // 设置旋转动画mText.setText("释放加载新数据!"); // 更新textview的文本break;case STATE_LOADING:  // 数据加载状态setPaddingTop(mHeaderHeight);  // 设置paddingtop为headerview的高度mProgress.setVisibility(View.VISIBLE); // 显示progressbarmImage.clearAnimation(); // 清除动画mImage.setVisibility(View.GONE); // 隐藏imageviewmText.setText("正在加载数据..."); // 更新文本break;}} // 处理action_move事件private void onMove(MotionEvent ev) {// 如果当前不是在顶部,直接返回if (!isNowAtUp) {return;} int nowY = (int) ev.getY();  // 记录当前的y坐标int space = nowY - mStartY;  // 计算下拉的程度int top = space - mHeaderHeight; // 计算top的值 switch (mState) {case STATE_NORMAL:  // 如果是正常状态if (space > 0) {  // 如果下拉了mState = STATE_PULL; // 则 修改状态为下拉refreshView(); // 并刷新headerview}break;case STATE_PULL:  // 如果是下来状态setPaddingTop(top); // 不断修改headerview的paddingtop// 如果达到条件,并且还是在下拉中if (space >= mHeaderHeight + 30&& mScrollState == OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {mState = STATE_RELEASE;  // 修改状态为可释放状态refreshView(); // 刷新headerview}break;case STATE_RELEASE:  // 如果是可释放状态setPaddingTop(top); // 不断修改headerview的paddingtop// 如果下拉程度在STATE_PULL区间if (space > 0 && space <= mHeaderHeight + 30) {mState = STATE_PULL; // 则修改状态为下来状态,这样是又慢慢拉回去了refreshView(); // 刷新headerview} else if (space <= 0) {  // 如果没有下拉的空间了mState = STATE_NORMAL; // 修改状态为正常状态,拉了一圈又回退回去了isNowAtUp = false; // 还原默认值refreshView(); // 刷新headerview}break;}}// 外部调用的方法// 通知我新数据加载完毕// 还原状态为正常状态public void endToRefresh() {mState = STATE_NORMAL;refreshView();}// 设置加载数据的回调接口public void setOnPullRefreshListener(OnPullRefreshListener l) {mListener = l;}// 定义一个回调接口public interface OnPullRefreshListener {public void onPull();}}


Header_layout.xml file used in mylistview:

<?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:background="@android:color/darker_gray"    android:orientation="vertical" >    <RelativeLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:paddingBottom="10dip"        android:paddingLeft="30dip"        android:paddingRight="30dip"        android:paddingTop="10dip" >        <LinearLayout            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_centerInParent="true"            android:orientation="horizontal" >            <ImageView                android:id="@+id/image"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:layout_gravity="center"                android:src="@drawable/arrow" />            <ProgressBar                android:id="@+id/progress"                style="?android:attr/progressBarStyleSmall"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:layout_gravity="center"                android:visibility="gone" />            <TextView                android:id="@+id/text"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:layout_gravity="center"                android:text="下拉可以刷新" />        </LinearLayout>    </RelativeLayout></LinearLayout>



Usage:

In the layout file:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context=".MainActivity" >    <org.load.listview.MyListView        android:id="@+id/list"        android:layout_width="match_parent"        android:layout_height="wrap_content" /></RelativeLayout>


In mainactivity:

public class MainActivity extends Activity {private MyListView mListView;// 模拟数据private String[] mData = { "aaa", "bbb", "ccc", "ddd", "eee", "fff", "ggg","hhh", "iii" };@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mListView = (MyListView) findViewById(R.id.list);// 数据适配器final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, mData);// 设置适配器mListView.setAdapter(adapter);// 这里就用到了回调接口// 表示当可以加载新数据时干什么mListView.setOnPullRefreshListener(new OnPullRefreshListener() {@Overridepublic void onPull() {// 模拟获取新数据// 延迟2s后更新前两个数据Handler handler = new Handler();handler.postDelayed(new Runnable() {@Overridepublic void run() {for (int i = 0; i < 2; i++) {mData[i] = "new data " + new Random().nextInt(100);adapter.notifyDataSetChanged();mListView.endToRefresh();  // 通知MyListView数据加载完毕了}}}, 2000);}});}}






Listview pull-down refresh

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.