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

Android仿QQ好友详情页下拉顶部图片缩放效果

程序员文章站 2022-04-12 11:36:11
今天已经是这个星期连续加班的第四天了,趁着现在后台在处理逻辑问题,将前几天写的一个小例子整理下来。 效果图 效果分析 1 向下滑动,头部的图片随着手指滑动不断...

今天已经是这个星期连续加班的第四天了,趁着现在后台在处理逻辑问题,将前几天写的一个小例子整理下来。

效果图

Android仿QQ好友详情页下拉顶部图片缩放效果

效果分析

1 向下滑动,头部的图片随着手指滑动不断变大
2 向上滑动,不断的向上移动图片,直到图片不可见
3 当顶部图片不可见时,向上滑动,滑动listview

实现思路

1 由于这个view分上下两部分,垂直排列,可以通过继承linearlayout实现::自定义一个dragimageview,该view继承linearlayout

public dragimageview(context context, attributeset attrs) {
 super(context, attrs);
 // 默认该view垂直排列
 setorientation(linearlayout.vertical);
 // 用于配合处理该view的惯性滑动
 mscroller = new overscroller(context);
 mtouchslop = viewconfiguration.get(context).getscaledtouchslop();
 mmaximumvelocity = viewconfiguration.get(context)
    .getscaledmaximumflingvelocity();
 mminimumvelocity = viewconfiguration.get(context)
    .getscaledminimumflingvelocity();
 }

2 onmeasure中设置内容视图的高度

@override
protected void onmeasure(int widthmeasurespec, int heightmeasurespec) {
 super.onmeasure(widthmeasurespec, heightmeasurespec);
 layoutparams params = (layoutparams) getchildat(1).getlayoutparams();
 // 头部可以全部隐藏,所以内容视图的高度即为该控件的高度
 params.height = getmeasuredheight();
}

3 设置imageview的scaletype属性

@override
protected void onfinishinflate() {
 super.onfinishinflate();
 imageview = (imageview) getchildat(0);
 // 随着手指滑动,图片不断放大(宽高都大于或者等于imageview的大小),并居中显示:
 // 根据上边的分析,center_crop:可以使用均衡的缩放图像(保持图像原始比例),使图片的两个坐标(宽、高)都大于等于 相应的视图坐标(负的内边距),图像则位于视图的*
 imageview.setscaletype(scaletype.center_crop);
 listview = (listview) getchildat(1);
}

4 事件拦截

@override
public boolean onintercepttouchevent(motionevent ev) {
 if (ev.getaction() == motionevent.action_down) {
  downx = (int) ev.getx();
  downy = (int) ev.gety();
 }
 if (ev.getaction() == motionevent.action_move) {
  int currentx = (int) ev.getx();
  int currenty = (int) ev.gety();
  // 确保是垂直滑动
  if (math.abs(currenty - downy) > math.abs(currentx - downx)) {
   view childview = listview.getchildat(listview
     .getfirstvisibleposition());
   // 有两种情况需要拦截:
   // 1 图片没有完全隐藏
   // 2 图片完全隐藏,但是向下滑动,并且listview滑动到顶部
   if (getscrolly() != imageheight
     || (getscrolly() == imageheight && currenty - downy > 0
       && childview != null && childview.gettop() == 0)) {
    initvelocitytrackerifnotexists();
    mvelocitytracker.addmovement(ev);
    return true;
   }
  }

 }
 if (ev.getaction() == motionevent.action_up) {
  recyclevelocitytracker();
 }
 return super.onintercepttouchevent(ev);
}

5 ontouchevent的action_move处理

if (ev.getaction() == motionevent.action_move) {
  int currentx = (int) ev.getx();
  int currenty = (int) ev.gety();
  int deltyx = currentx - downx;
  int deltyy = currenty - downy;
  if (math.abs(deltyy) > math.abs(deltyx)) {
   if (deltyy > 0) {
    if (getscrolly() > 0) {
     if (getscrolly() - deltyy < 0) {
      scrollby(0, -getscrolly());
      return true;
     }
     // 当图片没有完全显示,并且向下滑动时,继续整个view使图片可见
     scrollby(0, -deltyy);
    } else {
    // 当图片完全显示,并且向下滑动时,则不断的放大图片(通过改变imageview)的高度
     layoutparams layoutparams = (layoutparams) getchildat(0)
       .getlayoutparams();
     layoutparams.height = layoutparams.height + deltyy / 2;
     getchildat(0).setlayoutparams(layoutparams);
    }
   } else {
   // 当图片还处于放大状态,并且向上滑动时,继续不断的缩小图片的高度,使图片缩小
    if (getchildat(1).gettop() > imageheight) {
     layoutparams layoutparams = (layoutparams) getchildat(0)
       .getlayoutparams();
     layoutparams.height = layoutparams.height + deltyy / 2;
     getchildat(0).setlayoutparams(layoutparams);
    } else {
    // 当图片处于正常状态,并且向上滑动时,移动整个view,缩小图片的可见范围
     if (getscrolly() - deltyy > imageheight) {
      scrollby(0, imageheight - getscrolly());
      return true;
     }
     scrollby(0, -deltyy);
    }
   }
   downy = currenty;
   downx = currentx;
   return true;
  }
 }

5 ontouchevent的action_up处理

if (ev.getaction() == motionevent.action_up) {
 // 当图片处于放大状态时松手,使图片缓慢的缩回到原来的状态
 if (getchildat(1).gettop() > imageheight) {
  isanimating = true;
  valueanimator valueanimator = valueanimator.ofint(getchildat(1)
    .gettop(), imageheight);
  valueanimator.setduration(300);
  valueanimator.addupdatelistener(new animatorupdatelistener() {
   @override
   public void onanimationupdate(valueanimator animation) {
    int value = (integer) animation.getanimatedvalue();
    layoutparams layoutparams = (layoutparams) getchildat(0)
      .getlayoutparams();
    layoutparams.height = value;
    getchildat(0).setlayoutparams(layoutparams);
   }
  });
  valueanimator.addlistener(new animatorlisteneradapter() {
   @override
   public void onanimationend(animator animation) {
    super.onanimationend(animation);
    isanimating = false;
   }
  });
  valueanimator.start();
 }
 // 当现在图片处于正常状态,并且图片没有完全隐藏,并且松手时滑动的速度大于可惯性滑动的最小值,让view产生惯性滑动效果
 if (getchildat(1).gettop() == imageheight
   && getscrolly() != imageheight) {
  mvelocitytracker.computecurrentvelocity(1000, mmaximumvelocity);
  int velocityy = (int) mvelocitytracker.getyvelocity();
  if (math.abs(velocityy) > mminimumvelocity) {
   fling(-velocityy);
  }
  recyclevelocitytracker();
 }

总结

这里主要有两个学习的点

1 图片缩放的处理,事件的拦截

2 view的惯性滑动:主要是结合overscroller的使用

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