当前位置: 移动技术网 > 移动技术>移动开发>Android > Android开发使用自定义view实现ListView下拉的视差特效功能

Android开发使用自定义view实现ListView下拉的视差特效功能

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

本文实例讲述了android开发使用自定义view实现listview下拉的视差特效功能。分享给大家供大家参考,具体如下:

一、概述:

现在流型的app如微信朋友圈,qq空间,微博个人展示都有视差特效的影子。

如图:下拉图片会产生图片拉升的效果,放手后图片有弹回到原处:

那我们如何实现呢?

1)重写listview控件:
2)重写里面的overscrollby方法
3)在松手后执行值动画

二、具体实现:

1.创建parallalistview 自定义listview

public class parallalistview extends listview {
  private static final string tag = "tag";
  public parallalistview(context context, attributeset attrs, int defstyle) {
    super(context, attrs, defstyle);
  }
  public parallalistview(context context, attributeset attrs) {
    this(context, attrs, 0);
  }
  public parallalistview(context context) {
    this(context, null);
  }
}

2)添加到布局里:

<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical" >
  <com.android.imooc.paralla.parallalistview
    android:id="@+id/lv_paralla"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
  </com.android.imooc.paralla.parallalistview>
</linearlayout>

3)生成主页,填充数据:

public class parallaactivity extends activity {
  private parallalistview mlistview;
  @override
  protected void oncreate(bundle savedinstancestate) {
    super.oncreate(savedinstancestate);
    setcontentview(r.layout.activity_paralla);
    initviews();
  }
  private void initviews() {
    mlistview = (parallalistview) findviewbyid(r.id.lv_paralla);
    mlistview.setadapter(new arrayadapter<string>(parallaactivity.this, android.r.layout.simple_list_item_1, cheeses.names));
  }
}

4)创建头布局:

<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical" >
  <imageview
    android:id="@+id/iv_header"
    android:scaletype="centercrop"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/parallax_img" />
</linearlayout>

图片设成scaletype="centercrop"模式

其它模式说明:

5)在主页里找到头布局并添加到listview里

view mheader = layoutinflater.from(this).inflate(r.layout.view_paralla_header, null);
mlistview = (parallalistview) findviewbyid(r.id.lv_paralla);
mlistview.addheaderview(mheader);

三、功能实现:

1.现在基本能看到效果了,但我们必须要拖动图片,这就要实现这个方法overscrollby

因为拖动是y轴方向,所以只要打印y轴方向的各个参数就好了

@override
protected boolean overscrollby(int deltax, int deltay, int scrollx, int scrolly, int scrollrangex,
  int scrollrangey, int maxoverscrollx, int maxoverscrolly, boolean istouchevent) {
    logger.i(tag, "deltay="+deltay + " scrollx="+scrollx+ " scrollrangey="+scrollrangey + " maxoverscrolly=" +maxoverscrolly + " istouchevent=" +istouchevent);
    return super.overscrollby(deltax, deltay, scrollx, scrolly, scrollrangex, scrollrangey, maxoverscrollx, maxoverscrolly,
        istouchevent);
}

得到数据下拉:deltay=-3 scrollx=0 scrollrangey=0 maxoverscrolly=0 istouchevent=true

得到数据上拉:deltay=4 scrollx=0 scrollrangey=0 maxoverscrolly=0 istouchevent=true

2.如果是下拉,我们把值赋给header,但我们如何获得高度呢?

1)在主页里初始化图片,然后设置到parallalistview里

imageview iv = (imageview) findviewbyid(r.id.iv_head);
mlistview.setparallaimage(iv);

2)在parallalistview创建方法setparallaimage

public void setparallaimage(imageview iv) {
    mimageview = iv;
    //在这个方法里获得高度
    int height = iv.getheight();
    int measureheight = iv.getmeasuredheight();
    int instrinsicheight = iv.getdrawable().getintrinsicheight();
    logger.i(tag, "height="+height + " measureheight="+measureheight+ " instrinsicheight="+instrinsicheight );
}

得到结果:height=0 measureheight=0 instrinsicheight=732

为什么会如此:因为此时的图片还没有初始化

那我们如何得到高度呢?

记得有个方法叫做iv.getviewtreeobserver(),那我们就在这个方法的监听事件里得到高度

iv.getviewtreeobserver().addongloballayoutlistener(new ongloballayoutlistener() {
  @override
  public void ongloballayout() {
    //当布局填充完成后,此方法会被调用
    mlistview.setparallaimage(iv);
    //移除监听
    iv.getviewtreeobserver().removeglobalonlayoutlistener(this);
  }
});

此时得到的高度height=240 measureheight=240 instrinsicheight=732

3)把值赋给图片就能实现拉伸的效果了

if (istouchevent && deltay < 0) {
  mheight += math.abs(deltay);
  if (mheight <= mbitmapheight) {
    mimageview.getlayoutparams().height = mheight;
    mimageview.requestlayout();
  }
}

3.松手后图片回弹,这个功能在ontouchevent里实现:

@override
public boolean ontouchevent(motionevent ev) {
    switch (ev.getaction()) {
    case motionevent.action_up:
      final int startheight = mimageview.getheight();
      final int endheight = mbitmapheight;
      //值动画
      //valueanim(startheight, endheight);
      //竖直移动动画
      resetanimation anim = new resetanimation(mimageview, startheight, endheight);
      anim.setinterpolator(new overshootinterpolator());
      startanimation(anim);
      break;
    default:
      break;
    }
    return super.ontouchevent(ev);
}

4、动画实现:

/**
 * @描述     使用平移动画实现下拉图片后弹射回去
 * @项目名称   app_imooc
 * @包名     com.android.imooc.paralla
 * @类名     resetanimation
 * @author   chenlin
 * @date    2016年5月29日 下午12:27:00
 * @version   1.0
 */
public class resetanimation extends animation {
  private imageview mimageview;
  private int mstartheight;
  private int mendheight;
  public resetanimation(imageview imageview, int startheight, int endheight) {
    this.mimageview = imageview;
    this.mstartheight = startheight;
    this.mendheight = endheight;
    setduration(500);
  }
  @override
  protected void applytransformation(float interpolatedtime, transformation t) {
    int newheight = (int) (valueutil.evalute(interpolatedtime, mstartheight, mendheight) + 0.5f);
    mimageview.getlayoutparams().height = newheight;
    mimageview.requestlayout();
    super.applytransformation(interpolatedtime, t);
  }
}

四、源码下载:

完整实例代码点击此处。

更多关于android相关内容感兴趣的读者可查看本站专题:《android控件用法总结》、《android开发入门与进阶教程》、《android视图view技巧总结》、《android编程之activity操作技巧总结》、《android数据库操作技巧总结》及《android资源操作技巧汇总

希望本文所述对大家android程序设计有所帮助。

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

相关文章:

验证码:
移动技术网