Android开发使用自定义view实现ListView下拉的视差特效功能
本文实例讲述了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程序设计有所帮助。
上一篇: APP怎么推广更省钱?