当前位置: 移动技术网 > 移动技术>移动开发>Android > Android自定义渐变式炫酷ListView下拉刷新动画

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

2019年07月24日  | 移动技术网移动技术  | 我要评论

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

主要要点

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

效果图

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)

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网