欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android自定义渐变式炫酷ListView下拉刷新动画

程序员文章站 2023-12-20 18:01:58
本文实例为大家分享了自定义渐变式炫酷动画的listview下拉刷新,供大家参考,具体内容如下 主要要点 listview刷新过程中主要有三个步骤当前:状态为下拉刷新,当...

本文实例为大家分享了自定义渐变式炫酷动画的listview下拉刷新,供大家参考,具体内容如下

主要要点

listview刷新过程中主要有三个步骤当前:状态为下拉刷新,当前状态为下拉刷新,当前状态为放开刷新,当前状态为正在刷新;主要思路为三个步骤分别对应三个自定义的view;即iburefreshfirststepview,iburefreshsecondstepview,iburefreshthirdstepview。

效果图

Android自定义渐变式炫酷ListView下拉刷新动画

iburefreshfirststepview代码,例如:

 private bitmap initialbitmap;
 private float mcurrentprogress;
 private bitmap scaledbitmap;

 public iburefreshfirststepview(context context, attributeset attrs,
         int defstyle) {
  super(context, attrs, defstyle);
  init(context);
 }

 public iburefreshfirststepview(context context, attributeset attrs) {
  super(context, attrs);
  init(context);
 }

 public iburefreshfirststepview(context context) {
  super(context);
  init(context);
 }

 private void init(context context) {
  //这个就是那个火箭图片
  initialbitmap = bitmap.createbitmap(bitmapfactory.decoderesource(getresources(), r.drawable.img_huojian1));

 }

 /**
  * 重写onmeasure方法主要是设置wrap_content时 view的大小
  * @param widthmeasurespec
  * @param heightmeasurespec
  */
 @override
 protected void onmeasure(int widthmeasurespec, int heightmeasurespec) {
  //根据设置的宽度来计算高度 设置为符合第二阶段娃娃图片的宽高比例
  setmeasureddimension(measurewidth(widthmeasurespec),measurewidth(widthmeasurespec)*initialbitmap.getheight()/initialbitmap.getwidth());
 }

 /**
  * 当wrap_content的时候,宽度即为第二阶段娃娃图片的宽度
  * @param widmeasurespec
  * @return
  */
 private int measurewidth(int widmeasurespec){
  int result = 0;
  int size = measurespec.getsize(widmeasurespec);
  int mode = measurespec.getmode(widmeasurespec);
  if (mode == measurespec.exactly){
   result = size;
  }else{
   result = initialbitmap.getwidth();
   if (mode == measurespec.at_most){
    result = math.min(result,size);
   }
  }
  return result;
  }

 /**
  * 在onlayout里面获得测量后view的宽高
  * @param changed
  * @param left
  * @param top
  * @param right
  * @param bottom
  */
 @override
 protected void onlayout(boolean changed, int left, int top, int right,
   int bottom) {
  super.onlayout(changed, left, top, right, bottom);

  // 给火箭图片进行等比例的缩放
  scaledbitmap = bitmap.createscaledbitmap(initialbitmap,89,110, false);
 }


 @override
 protected void ondraw(canvas canvas) {
  super.ondraw(canvas);
  //这个方法是对画布进行缩放,从而达到椭圆形图片的缩放,第一个参数为宽度缩放比例,第二个参数为高度缩放比例,
//  canvas.scale(mcurrentprogress, mcurrentprogress, measuredwidth/2, measuredheight/2);
  //将等比例缩放后的椭圆形画在画布上面
  canvas.drawbitmap(scaledbitmap,90,dip2px(getcontext(),80*mcurrentprogress),null);

 }
 /**
  * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
  */
 public static int dip2px(context context, float dpvalue) {
  final float scale = context.getresources().getdisplaymetrics().density;
  return (int) (dpvalue * scale + 0.5f);
 }
 /**
  * 设置缩放比例,从0到1 0为最小 1为最大
  * @param currentprogress
  */
 public void setcurrentprogress(float currentprogress){
  mcurrentprogress = currentprogress;
 }


}

iburefreshsecondstepview代码,例如:

 private bitmap endbitmap,scaledbitmap;

 public iburefreshsecondstepview(context context, attributeset attrs,
         int defstyle) {
  super(context, attrs, defstyle);
  init();
 }

 public iburefreshsecondstepview(context context, attributeset attrs) {
  super(context, attrs);
  init();
 }

 public iburefreshsecondstepview(context context) {
  super(context);
  init();
 }

 private void init() {
  endbitmap = bitmap.createscaledbitmap(bitmapfactory.decoderesource(getresources(), r.drawable.img_huojian2), 89, 110, false);
 }

 @override
 protected void onmeasure(int widthmeasurespec, int heightmeasurespec) {
  setmeasureddimension(measurewidth(widthmeasurespec), measurewidth(widthmeasurespec) * endbitmap.getheight() / endbitmap.getwidth());
 }
 @override
 protected void onlayout(boolean changed, int left, int top, int right,
       int bottom) {
  super.onlayout(changed, left, top, right, bottom);
  scaledbitmap = bitmap.createscaledbitmap(endbitmap, 89, 110, false);
 }
 @override
 protected void ondraw(canvas canvas) {
  super.ondraw(canvas);
  canvas.drawbitmap(endbitmap, 90, dip2px(getcontext(), 80 * 1), null);

 }
 /**
  * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
  */
 public static int dip2px(context context, float dpvalue) {
  final float scale = context.getresources().getdisplaymetrics().density;
  return (int) (dpvalue * scale + 0.5f);
 }
 private int measurewidth(int widthmeasurespec){
  int result = 0;
  int size = measurespec.getsize(widthmeasurespec);
  int mode = measurespec.getmode(widthmeasurespec);
  if (mode == measurespec.exactly) {
   result = size;
  }else {
   result = endbitmap.getwidth();
   if (mode == measurespec.at_most) {
    result = math.min(result, size);
   }
  }
  return result;
 }
}

iburefreshthirdstepview代码,例如:

 private bitmap endbitmap,scaledbitmap;

 public iburefreshthirdstepview(context context, attributeset attrs,
         int defstyle) {
  super(context, attrs, defstyle);
  init();
 }

 public iburefreshthirdstepview(context context, attributeset attrs) {
  super(context, attrs);
  init();
 }

 public iburefreshthirdstepview(context context) {
  super(context);
  init();
 }

 private void init() {
  endbitmap = bitmap.createscaledbitmap(bitmapfactory.decoderesource(getresources(), r.drawable.img_huojian3), 89, 170, false);
 }

 @override
 protected void ondraw(canvas canvas) {
  super.ondraw(canvas);
  canvas.drawbitmap(endbitmap, 90, dip2px(getcontext(), 40 * 1), null);
 }
 /**
  * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
  */
 public static int dip2px(context context, float dpvalue) {
  final float scale = context.getresources().getdisplaymetrics().density;
  return (int) (dpvalue * scale + 0.5f);
 }

 @override
 protected void onmeasure(int widthmeasurespec, int heightmeasurespec) {
  setmeasureddimension(measurewidth(widthmeasurespec), measurewidth(widthmeasurespec)*endbitmap.getheight()/endbitmap.getwidth());
 }

 private int measurewidth(int widthmeasurespec){
  int result = 0;
  int size = measurespec.getsize(widthmeasurespec);
  int mode = measurespec.getmode(widthmeasurespec);
  if (mode == measurespec.exactly) {
   result = size;
  }else {
   result = endbitmap.getwidth();
   if (mode == measurespec.at_most) {
    result = math.min(result, size);
   }
  }
  return result;
 }

代码块

ibulistview 代码,例如:

 private static final int done = 0;
 private static final int pull_to_refresh = 1;
 private static final int release_to_refresh = 2;
 private static final int refreshing = 3;
 private static final int ratio = 3;
 private relativelayout headerview;
 private int headerviewheight;
 private float starty;
 private float offsety;
 private textview tv_pull_to_refresh;
 private onmeituanrefreshlistener monrefreshlistener;
 private int state;
 private int mfirstvisibleitem;
 private boolean isrecord;
 private boolean isend;
 private boolean isrefreable;
 private framelayout manimcontainer;
// private animation animation;
 private simpledateformat format;
 private iburefreshfirststepview mfirstview;
 private iburefreshsecondstepview msecondview;
 private animationdrawable secondanim;
 private iburefreshthirdstepview mthirdview;
 private animationdrawable thirdanim;

 public ibulistview(context context) {
  super(context);
  init(context);
 }

 public ibulistview(context context, attributeset attrs) {
  super(context, attrs);
  init(context);
 }

 public ibulistview(context context, attributeset attrs, int defstyleattr) {
  super(context, attrs, defstyleattr);
  init(context);
 }

 public interface onmeituanrefreshlistener{
  void onrefresh();
 }

 /**
  * 回调接口,想实现下拉刷新的listview实现此接口
  * @param onrefreshlistener
  */
 public void setonmeituanrefreshlistener(onmeituanrefreshlistener onrefreshlistener){
  monrefreshlistener = onrefreshlistener;
  isrefreable = true;
 }

 /**
  * 刷新完毕,从主线程发送过来,并且改变headerview的状态和文字动画信息
  */
 public void setonrefreshcomplete(){
  //一定要将isend设置为true,以便于下次的下拉刷新
  isend = true;
  state = done;

  changeheaderbystate(state);
 }

 private imageview imageviewback,imageview_b;
 private void init(context context) {
  setoverscrollmode(view.over_scroll_never);
  setonscrolllistener(this);

  headerview = (relativelayout) layoutinflater.from(context).inflate(r.layout.ibu_item, null, false);
  imageviewback= (imageview) headerview.findviewbyid(r.id.icon_back);
  imageview_b= (imageview) headerview.findviewbyid(r.id.image_b);
  mfirstview = (iburefreshfirststepview) headerview.findviewbyid(r.id.first_view);
  tv_pull_to_refresh = (textview) headerview.findviewbyid(r.id.tv_pull_to_refresh);
  msecondview = (iburefreshsecondstepview) headerview.findviewbyid(r.id.second_view);

  mthirdview = (iburefreshthirdstepview) headerview.findviewbyid(r.id.third_view);


  measureview(headerview);
  addheaderview(headerview);
  headerviewheight = headerview.getmeasuredheight();
  headerview.setpadding(0, -headerviewheight, 0, 0);
  log.i("zhangqi","headerviewheight="+headerviewheight);

  state = done;
  isend = true;
  isrefreable = false;
 }




 @override
 public void onscrollstatechanged(abslistview abslistview, int i) {
 }
 @override
 public void onscroll(abslistview abslistview, int firstvisibleitem, int visibleitemcount, int totalitemcount) {
  mfirstvisibleitem = firstvisibleitem;
 }

 @override
 public boolean ontouchevent(motionevent ev) {
  if (isend) {//如果现在时结束的状态,即刷新完毕了,可以再次刷新了,在onrefreshcomplete中设置
   if (isrefreable) {//如果现在是可刷新状态 在setonmeituanlistener中设置为true
    switch (ev.getaction()){
     //用户按下
    case motionevent.action_down:
     //如果当前是在listview顶部并且没有记录y坐标
     if (mfirstvisibleitem == 0 && !isrecord) {
      //将isrecord置为true,说明现在已记录y坐标
      isrecord = true;
      //将当前y坐标赋值给starty起始y坐标
      starty = ev.gety();
     }
     imageview_b.setvisibility(visible);
     break;
    //用户滑动
    case motionevent.action_move:
     //再次得到y坐标,用来和starty相减来计算offsety位移值
     float tempy = ev.gety();
     //再起判断一下是否为listview顶部并且没有记录y坐标
     if (mfirstvisibleitem == 0 && !isrecord) {
      isrecord = true;
      starty = tempy;
     }
     //如果当前状态不是正在刷新的状态,并且已经记录了y坐标
     if (state!=refreshing && isrecord ) {
      //计算y的偏移量
      offsety = tempy - starty;
      //计算当前滑动的高度
      float currentheight = (-headerviewheight+offsety/3);
      //用当前滑动的高度和头部headerview的总高度进行比 计算出当前滑动的百分比 0到1
      float currentprogress = 1+currentheight/headerviewheight;
      //如果当前百分比大于1了,将其设置为1,目的是让第一个状态的椭圆不再继续变大
      if (currentprogress>=1) {
       currentprogress = 1;
      }
      //如果当前的状态是放开刷新,并且已经记录y坐标
      if (state == release_to_refresh && isrecord) {
       setselection(0);
       //如果当前滑动的距离小于headerview的总高度
       if (-headerviewheight+offsety/ratio<0) {
        //将状态置为下拉刷新状态
        state = pull_to_refresh;
        //根据状态改变headerview,主要是更新动画和文字等信息
        changeheaderbystate(state);
        //如果当前y的位移值小于0,即为headerview隐藏了
       }else if (offsety<=0) {
        //将状态变为done
        state = done;
        //根据状态改变headerview,主要是更新动画和文字等信息
        changeheaderbystate(state);
       }
      }
      //如果当前状态为下拉刷新并且已经记录y坐标
      if (state == pull_to_refresh && isrecord) {
       setselection(0);
       //如果下拉距离大于等于headerview的总高度
       if (-headerviewheight+offsety/ratio>=0) {
        //将状态变为放开刷新
        state = release_to_refresh;
        //根据状态改变headerview,主要是更新动画和文字等信息
        changeheaderbystate(state);
        //如果当前y的位移值小于0,即为headerview隐藏了
       }else if (offsety<=0) {
        //将状态变为done
        state = done;
        //根据状态改变headerview,主要是更新动画和文字等信息
        changeheaderbystate(state);
       }
      }
      //如果当前状态为done并且已经记录y坐标
      if (state == done && isrecord) {
       //如果位移值大于0
       if (offsety>=0) {
        //将状态改为下拉刷新状态
        state = pull_to_refresh;
       }
      }
      //如果为下拉刷新状态
      if (state == pull_to_refresh) {
       //则改变headerview的padding来实现下拉的效果
       headerview.setpadding(0,(int)(-headerviewheight+offsety/ratio) ,0,0);
       //给第一个状态的view设置当前进度值
       mfirstview.setcurrentprogress(currentprogress);
       //重画
       mfirstview.postinvalidate();
      }
      //如果为放开刷新状态
      if (state == release_to_refresh) {
       //改变headerview的padding值
       headerview.setpadding(0,(int)(-headerviewheight+offsety/ratio) ,0, 0);
       //给第一个状态的view设置当前进度值
       mfirstview.setcurrentprogress(currentprogress);
       //重画
       mfirstview.postinvalidate();
      }
     }
     break;
    //当用户手指抬起时
    case motionevent.action_up:
     //如果当前状态为下拉刷新状态
     if (state == pull_to_refresh) {
      //平滑的隐藏headerview
      this.smoothscrollby((int)(-headerviewheight+offsety/ratio)+headerviewheight, 500);
      //根据状态改变headerview
      changeheaderbystate(state);
     }
     //如果当前状态为放开刷新
     if (state == release_to_refresh) {
      //平滑的滑到正好显示headerview
      this.smoothscrollby((int)(-headerviewheight+offsety/ratio), 500);
      //将当前状态设置为正在刷新
      state = refreshing;
      //回调接口的onrefresh方法
      monrefreshlistener.onrefresh();
      //根据状态改变headerview
      changeheaderbystate(state);
     }
     //这一套手势执行完,一定别忘了将记录y坐标的isrecord改为false,以便于下一次手势的执行
     isrecord = false;
     break;
    }

   }
  }
  return super.ontouchevent(ev);
 }

 private animation animation;
 /**
  * 根据状态改变headerview的动画和文字显示
  * @param state
  */
 private void changeheaderbystate(int state){
  switch (state) {
  case done://如果的隐藏的状态
   //设置headerview的padding为隐藏
   headerview.setpadding(0, -headerviewheight, 0, 0);
   //第一状态的view显示出来
   mfirstview.setvisibility(view.visible);


   imageview_b.setvisibility(visible);
   tv_pull_to_refresh.settext("下拉刷新");
   //第二状态的view隐藏起来
   msecondview.setvisibility(view.gone);
   //停止第二状态的动画
   secondanim.stop();
   //第三状态的view隐藏起来
   mthirdview.setvisibility(view.gone);
   //停止第三状态的动画
   thirdanim.stop();
   break;
  case release_to_refresh://当前状态为放开刷新
   //文字显示为放开刷新
   tv_pull_to_refresh.settext("放开刷新");
   //第一状态view隐藏起来
   mfirstview.setvisibility(view.gone);
   //第二状态view显示出来
   msecondview.setvisibility(view.visible);
   //播放第二状态的动画
  secondanim.start();
   //第三状态view隐藏起来
   mthirdview.setvisibility(view.gone);
   //停止第三状态的动画
  thirdanim.stop();
   break;
  case pull_to_refresh://当前状态为下拉刷新
   imageview_b.setvisibility(visible);
   //设置文字为下拉刷新
   tv_pull_to_refresh.settext("下拉刷新");
   //第一状态view显示出来
   mfirstview.setvisibility(view.visible);
   //第二状态view隐藏起来
   msecondview.setvisibility(view.gone);
   //第二状态动画停止
   secondanim.stop();
   //第三状态view隐藏起来
   mthirdview.setvisibility(view.gone);
   //第三状态动画停止
   thirdanim.stop();
   break;
  case refreshing://当前状态为正在刷新
   //文字设置为正在刷新
   tv_pull_to_refresh.settext("正在刷新");
   //第一状态view隐藏起来
   mfirstview.setvisibility(view.gone);
   //第三状态view显示出来
   mthirdview.setvisibility(view.visible);
   //第二状态view隐藏起来
   msecondview.setvisibility(view.gone);
   //停止第二状态动画
   secondanim.stop();
   //启动第三状态view
   thirdanim.start();
   imageview_b.setvisibility(gone);
    animation = new translateanimation(0, 0, 0, 600);
   animation.setduration(3000);
   imageviewback.setanimation(animation);
   break;
  default:
   break;
  }
 }


 private void measureview(view child) {
  viewgroup.layoutparams p = child.getlayoutparams();
  if (p == null) {
   p = new viewgroup.layoutparams(viewgroup.layoutparams.match_parent,
     viewgroup.layoutparams.wrap_content);
  }
  int childwidthspec = viewgroup.getchildmeasurespec(0, 0 + 0, p.width);
  int lpheight = p.height;
  int childheightspec;
  if (lpheight > 0) {
   childheightspec = measurespec.makemeasurespec(lpheight,
     measurespec.exactly);
  } else {
   childheightspec = measurespec.makemeasurespec(0,
     measurespec.unspecified);
  }
  child.measure(childwidthspec, childheightspec);
 }


}

github代码:

项目代码下载(https://github.com/molu0007/ibu_listview)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

上一篇:

下一篇: