ListVIEw中的下拉刷新是非常常见的,也是经常使用的,看到有很多同学想要,那我就整理一下,供大家参考。那我就不解释,直接上代码了。
这里需要自己重写一下ListVIEw,重写代码如下:
package net.loonggg.ListvIEw; import java.util.Date; import androID.content.Context; import androID.util.AttributeSet; import androID.vIEw.LayoutInflater; import androID.vIEw.MotionEvent; import androID.vIEw.VIEw; import androID.vIEw.VIEwGroup; import androID.vIEw.animation.linearInterpolator; import androID.vIEw.animation.RotateAnimation; import androID.Widget.AbsListVIEw; import androID.Widget.AbsListVIEw.OnScrollListener; import androID.Widget.ImageVIEw; import androID.Widget.linearLayout; import androID.Widget.ListVIEw; import androID.Widget.Progressbar; import androID.Widget.TextVIEw; public class MyListVIEw extends ListVIEw implements OnScrollListener { private final static int RELEASE_To_REFRESH = 0;// 下拉过程的状态值 private final static int PulL_To_REFRESH = 1; // 从下拉返回到不刷新的状态值 private final static int REFRESHING = 2;// 正在刷新的状态值 private final static int DONE = 3; private final static int LOADING = 4; // 实际的padding的距离与界面上偏移距离的比例 private final static int RATIO = 3; private LayoutInflater inflater; // ListVIEw头部下拉刷新的布局 private linearLayout headerVIEw; private TextVIEw lvheaderTipsTv; private TextVIEw lvheaderLastUpdatedTv; private ImageVIEw lvheaderArrowIv; private Progressbar lvheaderProgressbar; // 定义头部下拉刷新的布局的高度 private int headerContentHeight; private RotateAnimation animation; private RotateAnimation reverseAnimation; private int startY; private int state; private boolean isBack; // 用于保证startY的值在一个完整的touch事件中只被记录一次 private boolean isRecored; private OnRefreshListener refreshListener; private boolean isRefreshable; public MyListVIEw(Context context) { super(context); init(context); } public MyListVIEw(Context context,AttributeSet attrs) { super(context,attrs); init(context); } private voID init(Context context) { setCachecolorHint(context.getResources().getcolor(R.color.transparent)); inflater = LayoutInflater.from(context); headerVIEw = (linearLayout) inflater.inflate(R.layout.lv_header,null); lvheaderTipsTv = (TextVIEw) headerVIEw .findVIEwByID(R.ID.lvheaderTipsTv); lvheaderLastUpdatedTv = (TextVIEw) headerVIEw .findVIEwByID(R.ID.lvheaderLastUpdatedTv); lvheaderArrowIv = (ImageVIEw) headerVIEw .findVIEwByID(R.ID.lvheaderArrowIv); // 设置下拉刷新图标的最小高度和宽度 lvheaderArrowIv.setMinimumWIDth(70); lvheaderArrowIv.setMinimumHeight(50); lvheaderProgressbar = (Progressbar) headerVIEw .findVIEwByID(R.ID.lvheaderProgressbar); measureVIEw(headerVIEw); headerContentHeight = headerVIEw.getMeasuredHeight(); // 设置内边距,正好距离顶部为一个负的整个布局的高度,正好把头部隐藏 headerVIEw.setpadding(0,-1 * headerContentHeight,0); // 重绘一下 headerVIEw.invalIDate(); // 将下拉刷新的布局加入ListVIEw的顶部 addheaderVIEw(headerVIEw,null,false); // 设置滚动监听事件 setonScrollListener(this); // 设置旋转动画事件 animation = new RotateAnimation(0,-180,RotateAnimation.relative_TO_SELF,0.5f,0.5f); animation.setInterpolator(new linearInterpolator()); animation.setDuration(250); animation.setFillAfter(true); reverseAnimation = new RotateAnimation(-180,0.5f); reverseAnimation.setInterpolator(new linearInterpolator()); reverseAnimation.setDuration(200); reverseAnimation.setFillAfter(true); // 一开始的状态就是下拉刷新完的状态,所以为DONE state = DONE; // 是否正在刷新 isRefreshable = false; } @OverrIDe public voID onScrollStateChanged(AbsListVIEw vIEw,int scrollState) { } @OverrIDe public voID onScroll(AbsListVIEw vIEw,int firstVisibleItem,int visibleItemCount,int totalitemCount) { if (firstVisibleItem == 0) { isRefreshable = true; } else { isRefreshable = false; } } @OverrIDe public boolean ontouchEvent(MotionEvent ev) { if (isRefreshable) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: if (!isRecored) { isRecored = true; startY = (int) ev.getY();// 手指按下时记录当前位置 } break; case MotionEvent.ACTION_UP: if (state != REFRESHING && state != LOADING) { if (state == PulL_To_REFRESH) { state = DONE; changeheaderVIEwByState(); } if (state == RELEASE_To_REFRESH) { state = REFRESHING; changeheaderVIEwByState(); onLvRefresh(); } } isRecored = false; isBack = false; break; case MotionEvent.ACTION_MOVE: int tempY = (int) ev.getY(); if (!isRecored) { isRecored = true; startY = tempY; } if (state != REFRESHING && isRecored && state != LOADING) { // 保证在设置padding的过程中,当前的位置一直是在head,否则如果当列表超出屏幕的话,当在上推的时候,列表会同时进行滚动 // 可以松手去刷新了 if (state == RELEASE_To_REFRESH) { setSelection(0); // 往上推了,推到了屏幕足够掩盖head的程度,但是还没有推到全部掩盖的地步 if (((tempY - startY) / RATIO < headerContentHeight)// 由松开刷新状态转变到下拉刷新状态 && (tempY - startY) > 0) { state = PulL_To_REFRESH; changeheaderVIEwByState(); } // 一下子推到顶了 else if (tempY - startY <= 0) {// 由松开刷新状态转变到done状态 state = DONE; changeheaderVIEwByState(); } } // 还没有到达显示松开刷新的时候,DONE或者是PulL_To_REFRESH状态 if (state == PulL_To_REFRESH) { setSelection(0); // 下拉到可以进入RELEASE_TO_REFRESH的状态 if ((tempY - startY) / RATIO >= headerContentHeight) {// 由done或者下拉刷新状态转变到松开刷新 state = RELEASE_To_REFRESH; isBack = true; changeheaderVIEwByState(); } // 上推到顶了 else if (tempY - startY <= 0) {// 由DOne或者下拉刷新状态转变到done状态 state = DONE; changeheaderVIEwByState(); } } // done状态下 if (state == DONE) { if (tempY - startY > 0) { state = PulL_To_REFRESH; changeheaderVIEwByState(); } } // 更新headVIEw的size if (state == PulL_To_REFRESH) { headerVIEw.setpadding(0,-1 * headerContentHeight + (tempY - startY) / RATIO,0); } // 更新headVIEw的paddingtop if (state == RELEASE_To_REFRESH) { headerVIEw.setpadding(0,(tempY - startY) / RATIO - headerContentHeight,0); } } break; default: break; } } return super.ontouchEvent(ev); } // 当状态改变时候,调用该方法,以更新界面 private voID changeheaderVIEwByState() { switch (state) { case RELEASE_To_REFRESH: lvheaderArrowIv.setVisibility(VIEw.VISIBLE); lvheaderProgressbar.setVisibility(VIEw.GONE); lvheaderTipsTv.setVisibility(VIEw.VISIBLE); lvheaderLastUpdatedTv.setVisibility(VIEw.VISIBLE); lvheaderArrowIv.clearanimation();// 清除动画 lvheaderArrowIv.startAnimation(animation);// 开始动画效果 lvheaderTipsTv.setText("松开刷新"); break; case PulL_To_REFRESH: lvheaderProgressbar.setVisibility(VIEw.GONE); lvheaderTipsTv.setVisibility(VIEw.VISIBLE); lvheaderLastUpdatedTv.setVisibility(VIEw.VISIBLE); lvheaderArrowIv.clearanimation(); lvheaderArrowIv.setVisibility(VIEw.VISIBLE); // 是由RELEASE_To_REFRESH状态转变来的 if (isBack) { isBack = false; lvheaderArrowIv.clearanimation(); lvheaderArrowIv.startAnimation(reverseAnimation); lvheaderTipsTv.setText("下拉刷新"); } else { lvheaderTipsTv.setText("下拉刷新"); } break; case REFRESHING: headerVIEw.setpadding(0,0); lvheaderProgressbar.setVisibility(VIEw.VISIBLE); lvheaderArrowIv.clearanimation(); lvheaderArrowIv.setVisibility(VIEw.GONE); lvheaderTipsTv.setText("正在刷新..."); lvheaderLastUpdatedTv.setVisibility(VIEw.VISIBLE); break; case DONE: headerVIEw.setpadding(0,0); lvheaderProgressbar.setVisibility(VIEw.GONE); lvheaderArrowIv.clearanimation(); lvheaderArrowIv.setimageResource(R.drawable.arrow); lvheaderTipsTv.setText("下拉刷新"); lvheaderLastUpdatedTv.setVisibility(VIEw.VISIBLE); break; } } // 此方法直接照搬自网络上的一个下拉刷新的demo,此处是“估计”headVIEw的wIDth以及height private voID measureVIEw(VIEw child) { VIEwGroup.LayoutParams params = child.getLayoutParams(); if (params == null) { params = new VIEwGroup.LayoutParams( VIEwGroup.LayoutParams.FILL_PARENT,VIEwGroup.LayoutParams.WRAP_CONTENT); } int chilDWIDthSpec = VIEwGroup.getChildMeasureSpec(0,0 + 0,params.wIDth); int lpHeight = params.height; int childHeightSpec; if (lpHeight > 0) { childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight,MeasureSpec.EXACTLY); } else { childHeightSpec = MeasureSpec.makeMeasureSpec(0,MeasureSpec.UnspecIFIED); } child.measure(chilDWIDthSpec,childHeightSpec); } public voID setonRefreshListener(OnRefreshListener refreshListener) { this.refreshListener = refreshListener; isRefreshable = true; } public interface OnRefreshListener { public voID onRefresh(); } public voID onRefreshComplete() { state = DONE; lvheaderLastUpdatedTv.setText("最近更新:" + new Date().tolocaleString()); changeheaderVIEwByState(); } private voID onLvRefresh() { if (refreshListener != null) { refreshListener.onRefresh(); } } public voID setAdapter(LvAdapter adapter) { lvheaderLastUpdatedTv.setText("最近更新:" + new Date().tolocaleString()); super.setAdapter(adapter); } }
重写完ListVIEw之后,在布局文件中是这么使用的,头部下拉刷新的布局文件lv_header.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:background="#000000" > <!-- 内容 --> <relativeLayout androID:ID="@+ID/head_contentLayout" androID:layout_wIDth="fill_parent" androID:layout_height="wrap_content" androID:paddingleft="30dp" > <!-- 箭头图像、进度条 --> <FrameLayout androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:layout_alignParentleft="true" androID:layout_centerVertical="true" > <!-- 箭头 --> <ImageVIEw androID:ID="@+ID/lvheaderArrowIv" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:layout_gravity="center" androID:src="@drawable/arrow" /> <!-- 进度条 --> <Progressbar androID:ID="@+ID/lvheaderProgressbar" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:layout_gravity="center" androID:visibility="gone" /> </FrameLayout> <!-- 提示、最近更新 --> <linearLayout androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:layout_centerHorizontal="true" androID:gravity="center_horizontal" androID:orIEntation="vertical" > <!-- 提示 --> <TextVIEw androID:ID="@+ID/lvheaderTipsTv" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:text="下拉刷新" androID:textcolor="@color/white" androID:textSize="20sp" /> <!-- 最近更新 --> <TextVIEw androID:ID="@+ID/lvheaderLastUpdatedTv" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:text="上次更新" androID:textcolor="@color/gold" androID:textSize="10sp" /> </linearLayout> </relativeLayout> </linearLayout>
在Main.xml中进行设置,代码如下:
<?xml version="1.0" enCoding="utf-8"?> <linearLayout xmlns:androID="http://schemas.androID.com/apk/res/androID" androID:layout_wIDth="fill_parent" androID:layout_height="fill_parent" androID:background="#000000" androID:orIEntation="vertical" > <net.loonggg.ListvIEw.MyListVIEw androID:ID="@+ID/lv" androID:layout_wIDth="fill_parent" androID:layout_height="fill_parent" /> </linearLayout>
然后就是在MainActivity中实现,代码如下:
package net.loonggg.ListvIEw; import java.util.ArrayList; import java.util.List; import net.loonggg.ListvIEw.MyListVIEw.OnRefreshListener; import androID.app.Activity; import androID.os.AsyncTask; import androID.os.Bundle; import androID.vIEw.VIEw; public class MainActivity extends Activity { private List<String> List; private MyListVIEw lv; private LvAdapter adapter; @OverrIDe protected voID onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentVIEw(R.layout.activity_main); lv = (MyListVIEw) findVIEwByID(R.ID.lv); List = new ArrayList<String>(); List.add("loonggg"); List.add("我们都是开发者"); List.add("我们都是开发者"); List.add("我们都是开发者"); List.add("我们都是开发者"); List.add("我们都是开发者"); List.add("我们都是开发者"); List.add("我们都是开发者"); List.add("我们都是开发者"); List.add("我们都是开发者"); List.add("我们都是开发者"); List.add("我们都是开发者"); List.add("我们都是开发者"); List.add("我们都是开发者"); List.add("我们都是开发者"); List.add("我们都是开发者"); List.add("我们都是开发者"); adapter = new LvAdapter(List,this); lv.setAdapter(adapter); lv.setonRefreshListener(new OnRefreshListener() { @OverrIDe public voID onRefresh() { new AsyncTask<VoID,VoID,VoID>() { protected VoID doInBackground(VoID... params) { try { Thread.sleep(1000); } catch (Exception e) { e.printstacktrace(); } List.add("刷新后添加的内容"); return null; } @OverrIDe protected voID onPostExecute(VoID result) { adapter.notifyDataSetChanged(); lv.onRefreshComplete(); } }.execute(null,null); } }); } }
这里还需要为ListVIEw设置一下Adapter,自定义的Adapter如下:
package net.loonggg.ListvIEw; import java.util.List; import androID.content.Context; import androID.vIEw.VIEw; import androID.vIEw.VIEwGroup; import androID.Widget.BaseAdapter; import androID.Widget.TextVIEw; public class LvAdapter extends BaseAdapter { private List<String> List; private Context context; public LvAdapter(List<String> List,Context context) { this.List = List; this.context = context; } @OverrIDe public int getCount() { return List.size(); } @OverrIDe public Object getItem(int position) { return List.get(position); } @OverrIDe public long getItemID(int position) { return position; } @OverrIDe public VIEw getVIEw(int position,VIEw convertVIEw,VIEwGroup parent) { TextVIEw tv = new TextVIEw(context.getApplicationContext()); tv.setText(List.get(position)); return tv; } }
如果想针对AndroID ListVIEw进行深入研究的同学,可以参考专题《Android listview使用方法汇总》。
到这里就完了,代码中的解释非常详细,具体的我就不多说了,也不解释了,自己看看并研究吧!
总结以上是内存溢出为你收集整理的Android中ListView下拉刷新的实现方法全部内容,希望文章能够帮你解决Android中ListView下拉刷新的实现方法所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)