android 开发笔记 自定义可下拉刷新上拉加载的ListView
2016-11-22 18:16
465 查看
后续可以根据自己需求更改头布局和尾布局,不多说直接上代码
这是我们自定义的ListView
下面是头和尾的布局文件,根据需求更改
Activity调用代码
这是我们自定义的ListView
public class MyPullToRefreshListView extends ListView implements AbsListView.OnScrollListener,ValueAnimator.AnimatorUpdateListener { private int index = 0;//当前listview处于的位置 0代表头部,1代表中间,2代表尾部 private View headerView,footerView; private TextView headerTv,footerTv; private int mode = 0;//0代表完成 1代表下拉刷新 2代表释放立即刷新 3代表正在刷新 4代表上拉加载 5代表释放立即加载 6代表正在加载 private final int DONE = 0; private final int DOWN_TO_REFRESH = 1; private final int RELEASE_TO_REFRESH = 2; private final int REFRESHING = 3; private final int UP_TO_LOAD = 4; private final int RELEASE_TO_LOAD = 5; private final int LOADING = 6; private ValueAnimator animator; private PointF p; private int layoutHeight; //头的高度 private int lineHeight = 50; //释放刷新的高度 private int rote = 3;//设置刷新的距离比较缓慢 //加载和刷新的监听事件 public interface OnRefreshListener{ //正在加载 void onLoad(); //正在刷新 void onRefresh(); } private OnRefreshListener listener; public void setOnRefreshListener(OnRefreshL 4000 istener listener) { this.listener = listener; } public MyPullToRefreshListView(Context context) { super(context); init(); } public MyPullToRefreshListView(Context context, AttributeSet attrs) { super(context, attrs); init(); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { switch (ev.getAction()){ case MotionEvent.ACTION_DOWN: //按下 p = new PointF(); p.x = ev.getX(); p.y = ev.getY(); break; case MotionEvent.ACTION_MOVE: //获取现在的位置 PointF m = new PointF(); m.x = ev.getX(); m.y = ev.getY(); int disx = (int) (m.y - p.y)/rote; //如果在头部 if(index == 0){ if(disx<=0){ return super.dispatchTouchEvent(ev);//事件向下分发 } //处理下拉的操作,如果正在刷新数据或者正在加载,就不处理 if(mode != REFRESHING && mode != LOADING){ //设置现在的状态是下拉刷新 mode = DOWN_TO_REFRESH; selectMode(); //慢慢地看到头 headerView.setPadding(0,-layoutHeight+disx,0,0); //判断是否达到临界值 if(-layoutHeight+disx >=lineHeight){ //设置现在状态是释放立即刷新 mode = RELEASE_TO_REFRESH; selectMode(); } return true;//事件在此进行处理 } } //尾部 else if(index == 2){ if(disx >= 0){ return super.dispatchTouchEvent(ev);//事件向下进行分发 } //处理上拉的操作,如果正在刷新数据或者正在加载,就不处理 if(mode != REFRESHING && mode != LOADING){ //将listview定位到尾部 ListAdapter adapter = getAdapter(); setSelection(adapter.getCount()-1); //设置现在的状态上拉加载 mode = UP_TO_LOAD; selectMode(); disx = Math.abs(disx); //慢慢地看到尾部 footerView.setPadding(0,0,0,-layoutHeight+disx); //到达临界值 if(-layoutHeight+disx >= lineHeight){ //设置现在的状态释放立即加载 mode = RELEASE_TO_LOAD; selectMode(); } return true;//事件在此进行处理 } }else{ //改变开始的位置 p = m; } break; case MotionEvent.ACTION_UP: //如果不是正在加载或者正在刷新 if(mode != REFRESHING && mode != LOADING){ //判断是否已经到达临界点 if(mode == RELEASE_TO_REFRESH){ //释放立即刷新 //显示正在刷新 mode = REFRESHING; selectMode(); if(listener!=null){ listener.onRefresh(); } animator.setIntValues(headerView.getPaddingTop(),0); animator.start(); }else if(mode == RELEASE_TO_LOAD){ //释放立即加载 mode = LOADING; selectMode(); if(listener!=null){ listener.onLoad(); } animator.setIntValues(footerView.getPaddingBottom(),0); animator.start(); }else if(mode == DOWN_TO_REFRESH){ //下拉刷新 //隐藏头部 animator.setIntValues(headerView.getPaddingTop(),-layoutHeight); animator.start(); }else if(mode == UP_TO_LOAD){ //上拉加载 //隐藏尾部 animator.setIntValues(footerView.getPaddingBottom(),-layoutHeight); animator.start(); } } break; } return super.dispatchTouchEvent(ev); //事件向下分发 } //设置刷新完成 public void complete(){ animator.setIntValues(0,-layoutHeight); animator.start(); //设置完成 mode = DONE; selectMode(); } //根据状态设置Listview的位置 public void selectMode(){ switch (mode){ case DONE: //隐藏头和尾 headerView.setPadding(0,-layoutHeight,0,0); footerView.setPadding(0,0,0,-layoutHeight); break; case DOWN_TO_REFRESH: //下拉刷新 headerTv.setText(R.string.DownToRefresh); break; case UP_TO_LOAD: //上拉加载 footerTv.setText(R.string.UpToLoad); break; case RELEASE_TO_REFRESH: //释放立即刷新 headerTv.setText(R.string.UpToRefresh); break; case RELEASE_TO_LOAD: //释放立即加载 footerTv.setText(R.string.DownToLoad); break; case REFRESHING: //正在刷新 headerTv.setText(R.string.Refreshing); break; case LOADING: //正在加载 footerTv.setText(R.string.Loading); break; } } //初始化信息 public void init(){ //获取头和尾的高度 layoutHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 60, getContext().getResources().getDisplayMetrics()); //设置listview的滑动监听事件 setOnScrollListener(this); //加头和加尾部 headerView = View.inflate(getContext(), R.layout.refresh,null); footerView = View.inflate(getContext(),R.layout.refresh,null); headerTv = (TextView) headerView.findViewById(R.id.refresh_tv); footerTv = (TextView) footerView.findViewById(R.id.refresh_tv); //设置头部隐藏 //设置尾部隐藏 selectMode(); addHeaderView(headerView); addFooterView(footerView); animator = new ValueAnimator(); animator.setDuration(500); animator.addUpdateListener(this); } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { } /** * * @param view * @param firstVisibleItem 当前可见的第一个item的位置 * @param visibleItemCount 当前可见item的总个数 * @param totalItemCount //listview的总个数 */ @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if(firstVisibleItem == 0){ //处于头部 index = 0; }else if(firstVisibleItem + visibleItemCount == totalItemCount){ //处于尾部 index = 2; }else{ //处于中间 index = 1; } } @Override public void onAnimationUpdate(ValueAnimator animation) { //改变header的pading if(mode == REFRESHING || mode == DOWN_TO_REFRESH){ headerView.setPadding(0,(Integer)animation.getAnimatedValue(),0,0); } if(mode == LOADING || mode == UP_TO_LOAD){ footerView.setPadding(0,0,0,(Integer)animation.getAnimatedValue()); } } }
下面是头和尾的布局文件,根据需求更改
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="60dp"> <TextView android:id="@+id/refresh_tv" android:layout_width="match_parent" android:layout_height="60dp" android:textSize="22sp" android:text="@string/Done" android:gravity="center"/> </LinearLayout>
Activity调用代码
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listView = (MyPullToRefreshListView) findViewById(R.id.mylist); datas = new ArrayList<>(); for (int i = 0; i < 15; i++) { datas.add("测试数据"+i); } ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,datas); listView.setAdapter(adapter); listView.setOnRefreshListener(new MyPullToRefreshListView.OnRefreshListener() { @Override public void onLoad() { //模拟加载数据 listView.postDelayed(new Runnable() { @Override public void run() { listView.complete(); } },2000); } @Override public void onRefresh() { //模拟刷新数据 listView.postDelayed(new Runnable() { @Override public void run() { listView.complete(); } },2000); } }); }
相关文章推荐
- Android开发笔记之ListView下拉刷新和上拉加载
- Android 自定义下拉刷新上拉加载更多Listview
- android下拉刷新和滑动到底部加载更多,自定义listview
- Android开发笔记之ListView下拉刷新实现机制
- 【Android开发笔记】pulltorefresh实现下拉刷新和上拉加载更多
- Android中自定义ListView实现上拉加载更多和下拉刷新
- Android UI自定义ListView实现下拉刷新和加载更多效果
- Android 自定义下拉刷新上拉加载更多Listview
- Android自定义PullListView下拉刷新,上拉加载更多分页数据
- Android UI--自定义ListView(实现下拉刷新+加载更多)
- android :自定义listview,下拉刷新,上拉加载
- Android UI--自定义ListView(实现下拉刷新+加载更多)
- Android开发笔记-下拉刷新上拉加载控件,对所有View通用!
- Android UI--自定义ListView(实现下拉刷新+加载更多)
- Android开发 ListView下拉刷新和上拉加载
- Android 自定义Listview下拉刷新上拉加载
- android 自定义ListView实现下拉刷新、分页加载、点击事件——自定义控件学习(七)
- android ListView下拉刷新及上拉加载 (自定义ListView,可直接使用)
- Android开发ListView中下拉刷新上拉加载及带列的横向滚动实现方法
- Android仿XListView支持下拉刷新和上划加载更多的自定义RecyclerView