ListView实现下拉刷新-3-将顶部布局动态的显示出来

在第二篇中主要讨论了将顶部布局加载到ListView中,重点分析了init,measureView和topping三个方法的实现;

这一篇主要是收尾部分,即判断状态,加载相应的函数并实现函数回调机制;

onTouchEvent:判断手势动作的方法:

public boolean onTouchEvent(MotionEvent ev) {

         // TODO Auto-generated method stub

         switch (ev.getAction()) {

         case MotionEvent.ACTION_DOWN:    ///当前是在下拉;

             if (firstVisibleItem == 0) { ///根据  当前可见的第一个的编号判断是不是在顶部;

                 isRemark = true;        ///设置在顶部下拉的标志

                 startY = (int) ev.getY();///记录开始时手指的位置高度;

             }

             break;

 

         case MotionEvent.ACTION_MOVE:

             onMove(ev);            ///判断是否还在移动;

             break;

         case MotionEvent.ACTION_UP:///

             if (state == RELESE) {

                 state = REFLASHING;

                 // 加载最新数据;

                 reflashViewByState();

                 iReflashListener.onReflash();///响应事件;

             else if (state == PULL) {

                 state = NONE;

                 isRemark = false;

                 reflashViewByState();

             }

             break;

         }

         return super.onTouchEvent(ev);

     }

首先调用移动事件对象的getAction方法获得动作,并用case来和MotionEvent的静态常量做比较,判断具体的动作类型。 (MotionEvent类是继承自抽象类InputEvent的,官方描述类的作用是:用于报告运动(鼠标、笔、手指,轨迹球)事件。运动事件可能持有 绝对或相对运动和其他数据,根据设备的类型)

动作类型:

MotionEvent.ACTION_DOWN:下拉动作,判断 当前的第一个Item的标号是不是0,firstVisibleItem在onScroll函数中就被赋好值了,并且这是由系统自动调用的。不是0的话, 就表示还没有到顶部;如果是0的话表示到了顶部,就要设置一个标志(isRemark)用来通知后面的相关函数,可以对顶部的距离进行调整,从而将顶部布 局显示出来。还要设置一个startY,记录当前手指所在的Y坐标位置,从而在下一次记录位置时,计算手指移动的距离,据此来显示顶部要显示的部分。

MotionEvent.ACTION_MOVE: 直接调用onMove函数,如果isRemark是true的话,表明已经到了顶部,onMove就会做相关的处理;如果是false的话,表明还未到顶 部,onMove就会直接返回。具体的onMove函数会在下面部分讨论,现在只要了解到onMove的调用时机和所起到的作用就可以了。

MotionEvent.ACTION_UP:根据状态state来判断:

ReflashListView定义了几种状态:

     final int NONE = 0;// 正常状态;

     final int PULL = 1;// 提示下拉状态;

     final int RELESE = 2;// 提示释放状态;

     final int REFLASHING = 3;// 刷新状态;

如果state是正常状态的话,上拉对顶部布局是不起作用的;

如果state是下拉状态的话,顶部布局还没有完全展开,说明你现在是想放弃刷新的操作,那么此时就将state置为正常状态,将isRemark置为false,表明还未到顶部;并调用reflashViewByState方法来重新显示顶部布局;

如果state是提示释放状态,现在上拉表示要刷新,调用reflashViewByState方法来重新显示顶部布局,并调用接口的函数,用接口回调机制,在Activity中实现函数体部分;

onMove:判断移动的距离和绘制顶部布局

private void onMove(MotionEvent ev) {

         if (!isRemark) {   ///不是顶部下拉则直接返回;

             return;

         }

         int tempY = (int) ev.getY(); ///记录当前手指的高度;

         int space = tempY - startY; ///计算出移动的距离;

         int topPadding = space - headerHeight;///和顶部的高度作比较;

         switch (state) {

         case NONE:

             if (space > 0) {     ///说明此时开始下拉,可以设置状态为下拉;

                 state = PULL;

                 reflashViewByState();

             }

             break;

         case PULL:

             topPadding(topPadding);

             if (space > headerHeight + 30 ///说明此时下拉距离超过高度30了,不能再拉了;

                     && scrollState == SCROLL_STATE_TOUCH_SCROLL) {

                 state = RELESE;

                 reflashViewByState();

             }

             break;

         case RELESE:           ///表示已经到头了,不能下拉了,松开就可以刷新;

             topPadding(topPadding);

             if (space < headerHeight + 30) {///到头了,但手指向上移动了,但还是可以看见头部的

                 state = PULL;

                 reflashViewByState();

             else if (space <= 0) {///到头了,手指移出顶部;

                 state = NONE;

                 isRemark = false;

                 reflashViewByState();

             }

             break;

         }

     }

首先isRemark是false表示还没有到达顶部布局,就直接返回;

之后记录当前手指的位置(tempY),与在onTouchEvent中记录的手指位置做减,得到手指移动的相对距离(space)。将距离与顶部布局的 高度做比较,得到一个新的tapping,作用是如果传入到第二篇中介绍的tapping函数中,就可以实时显示出顶部布局;

接着根据之前的状态和距离的大小,对布局的显示和新的状态做相应的调整:

如果state为NULL,并且spcae>0,就表示开始下移了,将state设置为PULL即下移状态,并调用reflashViewByState()重新加载布局;

如果state为PULL,调用topping,将顶部布局重新绘制。之后再判断space > headerHeight + 30  && scrollState == SCROLL_STATE_TOUCH_SCROLL:条件成立的话说明此时下拉距离超过高度30了并且手指此时是静止的,那么就将state状态置为 RELESE,表示释放可以刷新,并调用reflashViewByState()重新加载布局;

如果state为PULL,调用 topping,将顶部布局重新绘制。之后再判断space < headerHeight + 30,表示到头了,但手指向上移动了,但还是可以看见头部的,这时就要将state置为PULL,因为没有一下子移动到头,并调用 reflashViewByState;或者else space <= 0到头了,手指移出顶部,就要state = NONE,isRemark = false并调用reflashViewByState;

reflashViewByState:设置顶部布局的控件内容;

private void reflashViewByState() {

         TextView tip = (TextView) header.findViewById(R.id.tip);

         ImageView arrow = (ImageView) header.findViewById(R.id.arrow);

         ProgressBar progress = (ProgressBar) header.findViewById(R.id.progress);

         RotateAnimation anim = new RotateAnimation(0180,

                 RotateAnimation.RELATIVE_TO_SELF, 0.5f,

                 RotateAnimation.RELATIVE_TO_SELF, 0.5f);

         anim.setDuration(500);

         anim.setFillAfter(true);

         RotateAnimation anim1 = new RotateAnimation(1800,

                 RotateAnimation.RELATIVE_TO_SELF, 0.5f,

                 RotateAnimation.RELATIVE_TO_SELF, 0.5f);

         anim1.setDuration(500);

         anim1.setFillAfter(true);

         switch (state) {

         case NONE:

             arrow.clearAnimation();

             topPadding(-headerHeight);

             break;

 

         case PULL:

             arrow.setVisibility(View.VISIBLE);

             progress.setVisibility(View.GONE);

             tip.setText("下拉可以刷新!");

             arrow.clearAnimation();

             arrow.setAnimation(anim1);

             break;

         case RELESE:

             arrow.setVisibility(View.VISIBLE);

             progress.setVisibility(View.GONE);

             tip.setText("松开可以刷新!");

             arrow.clearAnimation();

             arrow.setAnimation(anim);

             break;

         case REFLASHING:

             topPadding(50);

             arrow.setVisibility(View.GONE);

             progress.setVisibility(View.VISIBLE);

             tip.setText("正在刷新...");

             arrow.clearAnimation();

             break;

         }

     }

在switch之前的部分是获得顶部布局的控件,和设置动画(其实个人感觉可以在初始化的时候就设置,这样就不要每次都重新设置一遍);

之后根据状态来显示顶部布局:

如果state是NONE:隐藏顶部布局;

如果state是PULL:下拉;

如果state是RELESE:松开刷新;

如果state是REFLASHING:正在刷新;

reflashComplete:获取完数据;

 public void reflashComplete() {

         state = NONE;

         isRemark = false;

         reflashViewByState();

         TextView lastupdatetime = (TextView) header

                 .findViewById(R.id.lastupdate_time);

         SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss");

         Date date = new Date(System.currentTimeMillis());

         String time = format.format(date);

         lastupdatetime.setText(time);

     }

主要是状态和标志的设置,记录刷新的时间,以便下次刷新时查看;

最后是接口的回调机制:

public interface IReflashListener{

         public void onReflash();

 }

 public void setInterface(IReflashListener iReflashListener){

         this.iReflashListener = iReflashListener;

 }

在Activity中,实现了接口IReflashListener,并重写了onReflash函数

public void onReflash() {

         Handler handler = new Handler();

         handler.postDelayed(new Runnable() {

             public void run() {

                 //获取最新数据

                 setReflashData();

                 //通知界面显示

                 showList(apk_list);

                 //通知listview 刷新数据完毕;

                 listview.reflashComplete();

             }

         }, 2000);

         

     }

关于函数回调机制,因为篇幅有限,就不具体讨论,可以看看我的博客: 常用但忽略的anroid知识2-回调问题

就这样,我们把用ListView来实现下拉刷新给全部分析了一遍,说说我在学习过程中的收获:不在惧怕developer的api文档了,看见一个常用的类我会去了解他与其他类的继承关系。对接口回调机制也有了比较深刻的理解;真心希望这三篇会给你带来一些新的理解。

接下来的几天中,我会开始学习自定义VIewGroup,也希望自己可以有比较深刻的体会,和大家一起分享!

一直在路上...

时间: 2024-08-13 15:31:17

ListView实现下拉刷新-3-将顶部布局动态的显示出来的相关文章

Android listview的下拉刷新

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">好久没有写博客了,今天我就写一个listview的下拉刷新分享给大家,希望对大家学习或者工作上有所帮助,其实呢,大家都知道,在现在的app当中,下拉刷新是比较常用的功能,用到的地方太多了,所以,今天我也就结合自己的思想给家真理一下,那么好,接下来,让我们一起学习,让你分分钟写出自己想要的

Android自定义控件——ListView的下拉刷新与上拉加载

转载请注明出处:http://blog.csdn.net/allen315410/article/details/39965327 1.简介 无疑,在Android开发中,ListView是使用非常频繁的控件之一,ListView提供一个列表的容易,允许我们以列表的形式将数据展示到界面上,但是Google给我们提供的原生ListView的控件,虽然在功能上很强大,但是在用户体验和动态效果上,还是比较差劲的.为了改善用户体验,市面上纷纷出现了各种各样的自定义的ListView,他们功能强大,界面美

android 安卓自定义listview实现下拉刷新

[1].重写listView 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

Android UI--自定义ListView(实现下拉刷新+加载更多)

http://blog.csdn.net/wwj_748/article/details/12512885 Android UI--自定义ListView(实现下拉刷新+加载更多) 关于实现ListView下拉刷新和加载更多的实现,我想网上一搜就一堆.不过我就没发现比较实用的,要不就是实现起来太复杂,要不就是不健全的.因为小巫近期要开发新浪微博客户端,需要实现ListView的下拉刷新,所以就想把这个UI整合到项目当中去,这里只是一个demo,可以根据项目的需要进行修改. 就不要太在乎界面了哈:

ListView实现下拉刷新(一)建立头布局

一.效果演示 ListView实现下拉刷新,是很常见的功能.下面是一个模拟的效果,如下图:                                   效果说明:当往下拉ListView的时候,顶部就会有一个“下拉刷新”的标识被拉 出来,再往下拉的时候,标识就会变成”松开刷新“,期间还伴随一个箭头的变化.此时松开手指,则会变成进度条提示正在刷新,刷新完成后,则加载进来刷新的数据.如此反复,就是下拉刷新的功能. 二.准备Demo 其实本质上,ListView实现下拉刷新和实现分页加载都是一

ListView实现下拉刷新-1-实现ListView

即使你不是需要这个项目,但通过这个项目,你会知道android的一些基础知识,对初学者的话帮助会比较大! ListView做下拉刷新的源码为例,代码是有慕课网的老师提供的,真心感谢慕课网! 源码下载   (注意源码中,有两个类He,MyAdapter是为了测试而创建的,没有实际作用) 不是打广告(注意在边看解释的时候最好是边看代码) 综述:(分多篇的原因是:一起讲完的话,不一定能接受,而不是故意为了积分) 第一篇:实现LIstView:重点在MyAdapter的实现上和convertView回收

ListView的下拉刷新上拉加载以及带列的横向滚动

相信有很人做的项目估计都用的到这个.就是ListView的下拉刷新上拉加载还有就是列的横向滚动; PS:横向滚动带表头与固定列(相信蛮多人都有这样的需求吧?就是在ListView上支持很多列,然而设备屏幕宽度有限) PS:这是我个人在网上找的两个示例demo结合而成的一个示例demo,还可以继续拓展,后续有时间就会更新,大家互相学习 ListView下拉刷新上拉加载示例demo原文出处: http://blog.csdn.net/limb99/article/details/18901513 L

Listview嵌套Viewpager实现仿淘宝搜狐广告主页,并实现listview的下拉刷新

Android实现功能:Listview嵌套viewpager仿淘宝搜狐视频主页面,和listview的下拉刷新. 什么都不说了:直接上图说效果 listview嵌套viewpager实现仿淘宝的广告滑动主页面 源码连接:(http://download.csdn.net/detail/qq_30000411/9528977) APK下载连接:(http://download.csdn.net/detail/qq_30000411/9528973) 下面给出我源码的主要文件构成: MyListV

重写ListView实现下拉刷新上拉加载

安卓本身的ListView没有刷新功能,要想实现这一功能,就得继承ListView并重写它的方法.同时也要实现其OnScrollListener这一接口. 下拉刷新,需要在原本的ListView上部添加一个Head,ListView本身提供了addHeadView()这一方法,但是没有实现刷新的功能,我们可以自定义Head的内容,并加上刷新的功能. 上拉加载更多数据与下拉刷新类似,是在ListView的下部添加一个Footer.具体实现代码如下: import java.text.SimpleD