本文实例讲述了Android开发使用自定义view实现ListView下拉的视差特效功能。分享给大家供大家参考,具体如下:
一、概述:
现在流型的APP如微信朋友圈,QQ空间,微博个人展示都有视差特效的影子。
如图:下拉图片会产生图片拉升的效果,放手后图片有弹回到原处:
那我们如何实现呢?
1)重写ListView控件: 2)重写里面的overScrollBy方法 3)在松手后执行值动画
二、具体实现:
1.创建ParallaListView 自定义ListView
代码语言:javascript复制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)添加到布局里:
代码语言:javascript复制<?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)生成主页,填充数据:
代码语言:javascript复制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)创建头布局:
代码语言:javascript复制<?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里
代码语言:javascript复制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轴方向的各个参数就好了
代码语言:javascript复制@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里
代码语言:javascript复制ImageView iv = (ImageView) findViewById(R.id.iv_head);
mListView.setParallaImage(iv);
2)在parallaListView创建方法setParallaImage
代码语言:javascript复制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)把值赋给图片就能实现拉伸的效果了
代码语言:javascript复制if (isTouchEvent && deltaY < 0) {
mHeight = Math.abs(deltaY);
if (mHeight <= mBitmapHeight) {
mImageView.getLayoutParams().height = mHeight;
mImageView.requestLayout();
}
}
3.松手后图片回弹,这个功能在onTouchEvent里实现:
代码语言:javascript复制@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、动画实现:
代码语言:javascript复制/**
* @描述 使用平移动画实现下拉图片后弹射回去
* @项目名称 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程序设计有所帮助。