1、ListView实现下拉刷新三实现下拉刷新 实现下拉刷新该准备的东西都已经准备好了。在这篇文章里,我们就开始实现下拉刷新功能吧。一、大体的逻辑分析我们来简单分析一下需要做的逻辑吧。首先分析头布局有几种状态。不下拉时,为正常状态,此时头布局隐藏。下拉到一定高度,提示信息变为“下拉刷新”,箭头朝下,此为下拉状态。再往下拉,提示信息变为“松开刷新”,箭头朝上,此为提示刷新状态。而此时松开手指,则执行刷新操作,头布局变为进度条显示,箭头消失,此为正在刷新状态。相反的,其他状态下松开手指,都不执行刷新操作,应该将头布局恢复到正常状态。因为可确定头布局的状态有四种。我们根据这四种状态,确定我们要做的事情。
2、要监听ListView的滚动,故要实现OnScrollListener接口。还要监听手指触摸事件,根据手指的下拉移动来改变头布局的显示效果,根据手指的抬起来判断是否进行刷新操作,因为要实现onTouchEvent方法。也就是说,头布局状态的改变应该随着手指的移动而改变,因此在onTouchEvent里面我们要实现上面分析的四种状态的改变。当然,状态改变就意味着头布局显示效果的改变,这里可以嵌套在onTouchEvent方法里面。但考虑到避免方法臃肿,以及其他地方可能也需要改变头布局界面,比如数据加载完成后等情况,因此专门将头布局界面的改变抽取出来,凝聚为一个方法。然后就是数据刷新,刷新操作要在
3、MyListView里执行,但是数据要在MainActivity中获取。老规矩,用接口回调即可。好了,基本上大体的逻辑就这么多了。下面我们将上面的分析转化为代码。二、代码编写废话我就不多说了,上面的分析很清楚了。继续完善MyListView即可。代码如下:package com.fuly.load;import android.content.Context;import android.util.AttributeSet;import android.view.LayoutInflater;import android.view.MotionEvent;import android.view
4、.View;import android.view.ViewGroup;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;public class MyListView extends ListView implements
5、 OnScrollListener private View header;/头布局 private int headerHeight;/头布局自身的高度 private int scrollState;/当前滚动状态 private int firstVisibleItem;/当前可见的第一个item private int startY;/刚开始触摸屏幕时的Y值 private int curState = 0;/当前header状态,默认为0 private final int NORMAL = 0;/正常状态 private final int PULL = 1;/状态下拉 priva
6、te final int RELEASE = 2;/提示刷新状态 private final int RELEASING = 3;/状态正在刷新 private boolean canPull = false;/是否可以执行下拉操作 private refresfListener mListener;/回调接口 /三个构造方法都要重写 public MyListView(Context context) super(context); initView( context); public MyListView(Context context, AttributeSet attrs) super
7、(context, attrs); initView( context); public MyListView(Context context, AttributeSet attrs, int defStyle) super(context, attrs, defStyle); initView( context); /定义回调接口 public interface refresfListener void refresh(); public void setOnRefreshListener(refresfListener listener) this.mListener = listene
8、r; public void initView(Context context) header = LayoutInflater.from(context).inflate(R.layout.header, null); notifyView(header); headerHeight = header.getMeasuredHeight();/获取header的高度/ headerHeight = header.getHeight(); paddingTop(-headerHeight); /将头布局加进去 this.addHeaderView(header); this.setOnScro
9、llListener(this); /* * 该方法为通知父布局,子布局view的宽度和高度 * param view:子布局 */ private void notifyView(View view) ViewGroup.LayoutParams p = view.getLayoutParams(); if(p = null) p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); /spec表示当前子view左右边距,padding表示
10、子view的左右内边距 /childDimension:子view的宽度 int width = ViewGroup.getChildMeasureSpec(0, 0, p.width); int height; int tempHeight = p.height; if(tempHeight0) /子布局高度不为空,需要填充这个布局 height = MeasureSpec.makeMeasureSpec(tempHeight, MeasureSpec.EXACTLY); else /高度为0,则不需要填充 height = MeasureSpec.makeMeasureSpec(0, Me
11、asureSpec.UNSPECIFIED); /然后告诉父布局,子布局的高度和宽度 view.measure(width, height); /该方法设定header的paddingTop private void paddingTop(int pt) header.setPadding(header.getPaddingLeft(), pt, header.getPaddingRight(), header.getPaddingBottom(); header.invalidate(); /* * 监听当前滚动状态 * scrollState:当前滚动状态 */ public void o
12、nScrollStateChanged(AbsListView view, int scrollState) /记录当前的滚动状态 this.scrollState = scrollState; /* * 监听当前滚动的item * firstVisibleItem:当前可见的第一个item * visibleItemCount:当前共有多少个item可见 * totalItemCount:总共有多少个item * */ public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int
13、totalItemCount) this.firstVisibleItem = firstVisibleItem; /触屏事件 public boolean onTouchEvent(MotionEvent ev) switch(ev.getAction() /手指落到屏幕上时 case MotionEvent.ACTION_DOWN: /如果当前可见的第一个item为第0号,说明ListView位于顶端,可以执行下拉刷新 if(firstVisibleItem = 0) canPull = true; startY = (int) ev.getY(); break; /手指在屏幕上拖动时 c
14、ase MotionEvent.ACTION_MOVE: if(canPull) touchMove(ev); break; /手指离开屏幕时 case MotionEvent.ACTION_UP: canPull = false; if(curState = RELEASE) curState = RELEASING; refreshHeaderByState(); /这里添加刷新数据的逻辑 mListener.refresh(); else curState = NORMAL; refreshHeaderByState(); paddingTop(-headerHeight); break
15、; return super.onTouchEvent(ev); /* * 该方法根据触摸屏幕滑动来改变STATE,即改变当前状态 * param ev */ private void touchMove(MotionEvent ev) int tempY = (int) ev.getY(); int space = tempY -startY;/移动的距离 int topdding = space-headerHeight; paddingTop(topdding);/即时设定头布局的隐藏高度 if(spaceheaderHeight&spaceheaderHeight+50) curSta
16、te = RELEASE;/设定为提示刷新状态 refreshHeaderByState(); if(spaceheaderHeight) curState = NORMAL;/设定为正常状态 refreshHeaderByState(); /* * 根据当前状态更改header的显示界面 * */ private void refreshHeaderByState( ) ProgressBar pb = (ProgressBar) header.findViewById(R.id.progress_bar); ImageView img = (ImageView) header.findVi
17、ewById(R.id.img_arrow); TextView tv = (TextView) header.findViewById(R.id.textinfo); switch(curState) case NORMAL: pb.setVisibility(View.GONE); img.setVisibility(View.VISIBLE); img.setImageResource(R.drawable.down_arrow); tv.setText(下拉刷新); break; case PULL: pb.setVisibility(View.GONE); img.setVisibi
18、lity(View.VISIBLE); img.setImageResource(R.drawable.down_arrow); tv.setText(下拉刷新); break; case RELEASE: pb.setVisibility(View.GONE); img.setVisibility(View.VISIBLE); img.setImageResource(R.drawable.up_arrow); tv.setText(松开刷新); break; case RELEASING: pb.setVisibility(View.VISIBLE); img.setVisibility(
19、View.GONE); tv.setText(正在刷新); break; /数据刷新完成后的操作 public void refreshFinish() curState = NORMAL; paddingTop(-headerHeight); refreshHeaderByState(); 接下来就是MainActivity中的代码了。如下:package com.fuly.load;import java.util.ArrayList;import java.util.List;import com.fuly.load.MyListView.refresfListener;import a
20、ndroid.os.Bundle;import android.os.Handler;import android.app.Activity;public class MainActivity extends Activity implements refresfListener private MyListView lv; private List mDatas = new ArrayList(); private MyAdapter mAdapter; protected void onCreate(Bundle savedInstanceState) super.onCreate(sav
21、edInstanceState); setContentView(R.layout.activity_main); initData();/该方法初始化数据 lv = (MyListView) findViewById(R.id.list_view); lv.setOnRefreshListener(this);/设定回调接口 mAdapter = new MyAdapter(this, mDatas); lv.setAdapter(mAdapter); /* * 该方法初始化数据,即提供初始的素材 */ private void initData() for(int i = 0;i12;i+
22、) MyData md = new MyData(你好,我是提前设定的); mDatas.add(md); /* * 提供刷新数据 */ private void getRefreshData() for(int i = 0;i3;i+) MyData md = new MyData(你好,我是刷新进来的); mDatas.add(i, md); /重写回调方法 public void refresh() /在这里之所以使用Handler,是想让操作延迟,这样子效果看起来更 /清晰,实际项目中,是 不需要的 Handler mHandler = new Handler(); mHandler.postDelayed(new Runnable() Override public void run() /获得刷新数据 getRefreshData(); /刷新ListView mAdapter.notifyDataSetChanged(); /lv.setSelection(mDatas.size()-1); /刷新后 lv.refreshFinish(); , 5000 ); 好了,快快运行下程序,体验下拉刷新的效果吧。至此,ListView实现下拉刷新,我们讲解完毕了。
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1