下拉刷新ListView讲解,自定义PullToRefreshListView
2016-04-08 18:54
441 查看
思路
关于下拉刷新的ListView的实现,思路主要有两种:1 . 用LinearLayout包裹一个refreshHeadView和一个listView , 触摸时通过改变refreshHeadView的LayoutParams参数的 topMargin来隐藏和显示refreshHeadView,lp.topMargin = - refreshHeadHeight 时,头部隐藏,lp.topMargin = 0 时,头部恰好完全出现。我的另外一篇博客实现了这个思路 :
[ http://blog.csdn.net/u010335298/article/details/50956995 ]
2 . 用ListView的addHeaderView方法,为ListView设置一个headView作为下拉刷新的view ,通过设置headView的topPadding来显示和隐藏headView , topPadding = - headHeight的时候,headView隐藏,topPadding = 0 时 ,头部恰好完全出现 。这篇博客就是用这种思路实现的。
效果
流程
为了方便讲解,我画了图来描述我的实现思路。代码
下面是激动人心的代码啦~package com.example.myapp.view; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.animation.AccelerateInterpolator; import android.view.animation.DecelerateInterpolator; import android.widget.AbsListView; import android.widget.ListView; import android.widget.Scroller; import android.widget.TextView; import com.example.myapp.R; /** * Created by zyr * DATE: 16-4-6 * Time: 下午4:02 * Email: yanru.zhang@renren-inc.com * * 通过listview addHeaderView来实现下拉刷新 */ public class CustomPullToRefreshListView2 extends ListView implements AbsListView.OnScrollListener { private Context mContext; private View headerView; private TextView headerTv; private int headerHeight; private Scroller mScroller; public static final int STATE_NONE = 0; public static final int STATE_PULL_TO_REFRESH = 1; //下拉去刷新 public static final int STATE_RELEASE_TO_REFRESH = 2; // 释放进行刷新 public static final int STATE_REFRESHING = 3; // 正在刷新 private int state = STATE_NONE; private int downY; public static final int DURATION = 500; private OnRefreshListener mOnRefreshListener; public interface OnRefreshListener{ void onDownPullRefresh(); } /************************ 构造****************************************/ public CustomPullToRefreshListView2(Context context) { this(context, null); } public CustomPullToRefreshListView2(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CustomPullToRefreshListView2(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mContext = context; initScroller(); initHeaderView(); setOnScrollListener(this); } private void initScroller() { mScroller = new Scroller(getContext(), new DecelerateInterpolator()); } @Override public void computeScroll() { super.computeScroll(); if(mScroller.computeScrollOffset()){ headerView.setPadding(0, mScroller.getCurrY(), 0, 0); } } private void initHeaderView() { headerView = View.inflate(getContext(), R.layout.header_listview, null); headerTv = (TextView) headerView.findViewById(R.id.tvHead); headerView.measure(0, 0); // 系统会帮我们测量出headerView的高度 headerHeight = headerView.getMeasuredHeight(); Log.d("zyr", "--------------------headerHeight :" + headerHeight); headerView.setPadding(0, -headerHeight, 0, 0); invalidate(); Log.d("zyr", "----------------------headerPaddingTop :" + headerView.getPaddingTop()); super.addHeaderView(headerView, null, false); } /************************** Scroll******************************/ @Override public void onScrollStateChanged(AbsListView view, int scrollState) { } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { } /*************************** Touch***************************************/ @Override public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN : downY = (int) ev.getY(); break; case MotionEvent.ACTION_MOVE : int moveY = (int) ev.getY(); // 移动中的y - 按下的y = 间距. int diff = (moveY - downY) / 2; // -头布局的高度 + 间距 = paddingTop int paddingTop = -headerHeight + diff; // 如果: 第一个可见,向下拉 if (getFirstVisiblePosition() == 0 && diff > 0) { if (paddingTop > 0 ) { // 完全显示了. Log.i("zyr", "松开刷新"); state = STATE_RELEASE_TO_REFRESH; refreshHeaderView(); } else if (paddingTop < 0 ) { // 没有显示完全 Log.i("zyr", "下拉刷新"); state = STATE_PULL_TO_REFRESH; refreshHeaderView(); } // 下拉头布局 Log.d("zyr","--------------paddingTop:" + paddingTop); headerView.setPadding(0, paddingTop, 0, 0); return true; } break; case MotionEvent.ACTION_UP : // 判断当前的状态是松开刷新还是下拉刷新 if (state == STATE_RELEASE_TO_REFRESH) { Log.i("zyr", "刷新数据."); // 把头布局设置为完全显示状态 mScroller.startScroll(0,headerView.getPaddingTop(),0,0-headerView.getPaddingTop(),DURATION); postInvalidate(); // 进入到正在刷新中状态 state = STATE_REFRESHING; refreshHeaderView(); if (mOnRefreshListener != null) { mOnRefreshListener.onDownPullRefresh(); // 调用使用者的监听方法 } } else if (state == STATE_PULL_TO_REFRESH) { // 隐藏头布局 mScroller.startScroll(0,headerView.getPaddingTop(),0,- headerHeight -headerView.getPaddingTop(),DURATION); postInvalidate(); } break; default : break; } return super.onTouchEvent(ev); } /** * 根据currentState刷新头布局的状态 */ private void refreshHeaderView() { switch (state) { case STATE_PULL_TO_REFRESH : // 下拉刷新状态 headerTv.setText("下拉刷新"); break; case STATE_RELEASE_TO_REFRESH : // 松开刷新状态 headerTv.setText("松开刷新"); break; case STATE_REFRESHING : // 正在刷新中状态 headerTv.setText("正在刷新中..."); break; default : break; } } /** * 隐藏头布局 */ public void hideHeaderView() { post(new Runnable() { @Override public void run() { mScroller.startScroll(0,headerView.getPaddingTop(),0,- headerHeight -headerView.getPaddingTop(),DURATION); postInvalidate(); headerTv.setText("下拉刷新"); state = STATE_NONE; } }); } /** * 设置刷新监听事件 * * @param listener */ public void setOnRefreshListener(OnRefreshListener listener) { mOnRefreshListener = listener; } }
header_listiew.xml
<?xml version="1.0" encoding="utf-8"?><!-- ListView的头部 --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical"> <!-- 内容 --> <RelativeLayout android:id="@+id/head_contentLayout" android:layout_width="fill_parent" android:layout_height="50dp" android:gravity="center"> <TextView android:id="@+id/tvHead" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/pull_to_refresh_pull_label" android:textColor="@color/black" android:textSize="15.5sp" android:textStyle="bold" /> </RelativeLayout> </LinearLayout>
activity调用
listView = (CustomPullToRefreshListView2) findViewById(R.id.listview); for(int i=0;i<20;i++){ strings.add("zyr" + i); } commonAdapter = new CommonAdapter(this,strings); listView.setAdapter(commonAdapter); listView.setOnRefreshListener(new CustomPullToRefreshListView2.OnRefreshListener() { @Override public void onDownPullRefresh() { new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } listView.hideHeaderView(); } }).start(); } });
相关文章推荐
- 完美实现Android ListView中的TextView的跑马灯效果
- android上改变listView的选中颜色
- Delphi7中Listview的常用功能汇总
- Delphi控件ListView的属性及使用方法详解
- android中ListView数据刷新时的同步方法
- Android提高之ListView实现自适应表格的方法
- Android中实现水平滑动(横向滑动)ListView示例
- C#实现ListView选中项向上或向下移动的方法
- Listview加载的性能优化是如何实现的
- C#实现listview Group收缩扩展的方法
- C# listview添加combobox到单元格的实现代码
- ListView 百分比进度条(delphi版)
- Android listview多视图嵌套多视图
- ListView Adapter优化 实例
- Android用ListView显示SDCard文件列表的小例子
- Adapter实现ListView带多选框等状态的自定义控件的注意事项
- asp.net ListView 数据绑定
- Android之ScrollView嵌套ListView和GridView冲突的解决方法
- android ListView和ProgressBar(进度条控件)的使用方法
- Android实现ListView异步加载图片的方法