Android中ListView下拉刷新的实现代码
程序员文章站
2023-12-09 20:41:51
android中listview下拉刷新
实现效果图:
listview中的下拉刷新是非常常见的,也是经常使用的,看到有很多同学想要,那我就整理一下,供大家参考。那...
android中listview下拉刷新
实现效果图:
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, 0); // 重绘一下 headerview.invalidate(); // 将下拉刷新的布局加入listview的顶部 addheaderview(headerview, null, false); // 设置滚动监听事件 setonscrolllistener(this); // 设置旋转动画事件 animation = new rotateanimation(0, -180, rotateanimation.relative_to_self, 0.5f, rotateanimation.relative_to_self, 0.5f); animation.setinterpolator(new linearinterpolator()); animation.setduration(250); animation.setfillafter(true); reverseanimation = new rotateanimation(-180, 0, rotateanimation.relative_to_self, 0.5f, rotateanimation.relative_to_self, 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, 0); } // 更新headview的paddingtop if (state == release_to_refresh) { headerview.setpadding(0, (tempy - starty) / ratio - headercontentheight, 0, 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, 0, 0); lvheaderprogressbar.setvisibility(view.visible); lvheaderarrowiv.clearanimation(); lvheaderarrowiv.setvisibility(view.gone); lvheadertipstv.settext("正在刷新..."); lvheaderlastupdatedtv.setvisibility(view.visible); break; case done: headerview.setpadding(0, -1 * headercontentheight, 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" style="?android:attr/progressbarstylesmall" 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, 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在OnCreate中获取控件的宽度和高度的实现代码
-
Android中利用App实现消息推送机制的代码
-
Android实现下拉刷新的视图和图标的旋转
-
Android开发使用自定义view实现ListView下拉的视差特效功能
-
android中SwipeRefresh实现各种上拉,下拉刷新示例
-
Android中显示GIF动画的实现代码
-
Android中ListView下拉刷新的实现方法实例分析
-
android中ListView多次刷新重复执行getView的解决方法
-
Android 中通过ViewDragHelper实现ListView的Item的侧拉划出效果