自定义控件之视差效果ParallaxEffect

1.定义一个类继承ListView

主要用到的是越界滚动 overScrollBy()

 onTouchEvent() 中松开手后自动回滚到原来的高度,用到了属性动画和插补器

public class ParallaxEffectView extends ListView {
	private ImageView imageView;
	private int intrinsicHeight;
	private int originalHeight;
	private ValueAnimator va;

	public ParallaxEffectView(Context context) {
		this(context, null);
	}

	public ParallaxEffectView(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public ParallaxEffectView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		init();
	}

	private void init() {

	}

	//重写方法overScrollBy

	/**
	 * 超过边界滚动
	 *
	 * @param deltaX
	 * @param deltaY         系统每隔一段时间,检测手指移动的距离
	 * @param scrollX
	 * @param scrollY        视图滚动的距离
	 * @param scrollRangeX
	 * @param scrollRangeY   滚动的y的范围
	 * @param maxOverScrollX
	 * @param maxOverScrollY 最大超过滚动的距离
	 * @param isTouchEvent   是否到达边界,尝试越过边界滑动.不包含惯性到达的边界
	 * @return
	 */
	@Override
	protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
		Log.i("test", "deltaY:" + deltaY + ",scrollY:" + scrollY + ", scrollRangeY:" + scrollRangeY + ", maxOverScrollY:" + maxOverScrollY + ", isTouchEvent:" + isTouchEvent);
		if (isTouchEvent) {//是否越过边界滚动
			//向下拉
			if (deltaY < 0) {//系统每隔一段时间,检测手指移动的距离
				//让图片的高度增加
				int oldHeight = imageView.getLayoutParams().height;
				int newHeight = oldHeight + Math.abs(deltaY);
				if (newHeight > intrinsicHeight * 0.5f) {
					newHeight = (int) (intrinsicHeight * 0.5f);
				}
				imageView.getLayoutParams().height = newHeight;
				//让更改后的布局参数生效
				imageView.requestLayout();
			}
		}
		return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);
	}

	public void setImageView(ImageView imageView) {
		this.imageView = imageView;
		//获取图片源的真实高度
		intrinsicHeight = imageView.getDrawable().getIntrinsicHeight();
		Log.i("test", "intrinsicHeight:" + intrinsicHeight);
		//获取ImageView最初的高度
		originalHeight = imageView.getLayoutParams().height;//就是在布局中设置的高度
	}

	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		switch (ev.getAction()) {
			case MotionEvent.ACTION_DOWN:
				//在down的时候,如果动画在执行,取消动画
				if(va!=null){
					if(va.isRunning()){
						va.cancel();
					}
				}
				break;
			case MotionEvent.ACTION_UP:
				va = ValueAnimator.ofInt(imageView.getLayoutParams().height,originalHeight);//从现在的高度减小到原始的高度
				//添加动画改变的监听
				va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
					@Override
					public void onAnimationUpdate(ValueAnimator animation) {
						//实时获取变化的高度,设置到ImageView上,刷新
						int height = (int) animation.getAnimatedValue();
						imageView.getLayoutParams().height=height;
						imageView.requestLayout();;
					}
				});
				//动画执行到终点,超过执行一段距离再回调终点
				va.setInterpolator(new OvershootInterpolator(5));
				va.setDuration(300);
				va.start();
				break;

		}
		return super.onTouchEvent(ev);
	}
}

2.布局文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.itheima.parallaxeffecthm91.ParallaxEffectView
        android:id="@+id/pev"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></com.itheima.parallaxeffecthm91.ParallaxEffectView>
</RelativeLayout>


3.activity

给ListView添加头条目并通过适配器展示数据

public class MainActivity extends AppCompatActivity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		ArrayAdapter<String> adapter=new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,Cheeses.NAMES);
		ParallaxEffectView pev= (ParallaxEffectView) findViewById(R.id.pev);

		//图片
		View view = View.inflate(this, R.layout.header, null);
		ImageView iv_head= (ImageView) view.findViewById(R.id.iv_head);
		pev.setImageView(iv_head);

		//将图片视图添加到头条目
		pev.addHeaderView(view);
		pev.setAdapter(adapter);
	}
}

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_head"
        android:layout_width="match_parent"
        android:layout_height="160dp"
        android:scaleType="centerCrop"
        android:src="@drawable/parallax_img" />

</LinearLayout>


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值