视差特效

1.视差特效_overScrollBy

1.应用场景: 微信朋友圈, QQ空间, 微博个人展示
    * 功能实现:
    > (1). 之前重写onTouch, 如今重写overScrollBy
    > (2). 松手之后执行动画, 类型估值器.

 

2.src与backgroud区别

3.scaleType

(1)大图

 

(2)小图

 

 

5.重写ListView

(1)对象的传输,新建一个方法,然后再调用-----------应用方法

(2)判断布局是否填充完毕

		mHeaderView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
			
			@Override
			public void onGlobalLayout() {
				// 当布局填充结束之后, 此方法会被调用

				mListView.setParallaxImage(mImage);    //把ImageView传到ListView中
				
				mHeaderView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
			}
		});


(3)获得图片高度  ListView中

	/**
	 * 设置ImageView图片, 拿到引用
	 * @param mImage
	 */
	public void setParallaxImage(ImageView mImage) {
		this.mImage = mImage;
		mOriginalHeight = mImage.getHeight(); // 160
		drawableHeight = mImage.getDrawable().getIntrinsicHeight(); // 488
		
		Log.d(TAG, "height: " + mOriginalHeight + " drawableHeight: " + drawableHeight);
	}


(4)让ImageView变高  ListView

		// 手指拉动 并且 是下拉
		if(isTouchEvent && deltaY < 0){
			// 把拉动的瞬时变化量的绝对值交给Header, 就可以实现放大效果
			if(mImage.getHeight() <= drawableHeight){
				int newHeight = (int) (mImage.getHeight() + Math.abs(deltaY / 3.0f));
			
				// 高度不超出图片最大高度时,才让其生效
				mImage.getLayoutParams().height = newHeight;
				mImage.requestLayout();
			}
		}
		


6.小结,不包括松手动画

   自定义ListView

/**
 * 视差特效ListView
 * overScrollBy
 * @author poplar
 *
 */
public class MyListView extends ListView {

	private static final String TAG = "TAG";
	private int mOriginalHeight;
	private int drawableHeight;
	private ImageView mImage;

	public MyListView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

	public MyListView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public MyListView(Context context) {
		super(context);
	}
	
	/**
	 * 设置ImageView图片, 拿到引用
	 * @param mImage
	 */
	public void setParallaxImage(ImageView mImage) {
		this.mImage = mImage;
		mOriginalHeight = mImage.getHeight(); // 160
		drawableHeight = mImage.getDrawable().getIntrinsicHeight(); // 488
		
		Log.d(TAG, "height: " + mOriginalHeight + " drawableHeight: " + drawableHeight);
	}
	
	@Override
	protected boolean overScrollBy(int deltaX, int deltaY, 
			int scrollX, int scrollY, int scrollRangeX, int scrollRangeY,
			int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
		// deltaY : 竖直方向的瞬时偏移量 / 变化量 dx   顶部滑到头下拉为-, 底部滑到头上拉为+
		// scrollY : 竖直方向的偏移量 / 变化量
		// scrollRangeY : 竖直方向滑动的范围
		// maxOverScrollY : 竖直方向最大滑动范围
		// isTouchEvent : 是否是手指触摸滑动, true为手指, false为惯性
		
		Log.d(TAG, "deltaY: " +deltaY + " scrollY: " + scrollY + " scrollRangeY: " + scrollRangeY
				+ " maxOverScrollY: " + maxOverScrollY + " isTouchEvent: " + isTouchEvent);
		
		// 手指拉动 并且 是下拉
		if(isTouchEvent && deltaY < 0){
			// 把拉动的瞬时变化量的绝对值交给Header, 就可以实现放大效果
			if(mImage.getHeight() <= drawableHeight){
				int newHeight = (int) (mImage.getHeight() + Math.abs(deltaY / 3.0f));
			
				// 高度不超出图片最大高度时,才让其生效
				mImage.getLayoutParams().height = newHeight;
				mImage.requestLayout();
			}
		}
		
		return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX,
				scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);
	}
	
	 
}


    MainActivity使用

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		
		final MyListView mListView = (MyListView) findViewById(R.id.lv);
		mListView.setOverScrollMode(View.OVER_SCROLL_NEVER);

		// 加Header
		final View mHeaderView = View.inflate(MainActivity.this, R.layout.view_header, null);
		final ImageView mImage = (ImageView) mHeaderView.findViewById(R.id.iv);
		mListView.addHeaderView(mHeaderView);
		
		mHeaderView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
			
			@Override
			public void onGlobalLayout() {
				// 当布局填充结束之后, 此方法会被调用

				mListView.setParallaxImage(mImage);    //把ImageView传到ListView中
				
				mHeaderView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
			}
		});
		
		// 填充数据
		mListView.setAdapter(new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, Cheeses.NAMES));
		
	}

}


 

 

 

2.视差特效_回弹动画

 方式一: 属性动画\值动画

1.(1)

/**
 * 视差特效ListView
 * overScrollBy
 * @author poplar
 *
 */
public class MyListView extends ListView {

	private static final String TAG = "TAG";
	private int mOriginalHeight;
	private int drawableHeight;
	private ImageView mImage;

	public MyListView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

	public MyListView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public MyListView(Context context) {
		super(context);
	}
	
	/**
	 * 设置ImageView图片, 拿到引用
	 * @param mImage
	 */
	public void setParallaxImage(ImageView mImage) {
		this.mImage = mImage;
		mOriginalHeight = mImage.getHeight(); // 160
		drawableHeight = mImage.getDrawable().getIntrinsicHeight(); // 488
		
		Log.d(TAG, "height: " + mOriginalHeight + " drawableHeight: " + drawableHeight);
	}
	
	@Override
	protected boolean overScrollBy(int deltaX, int deltaY, 
			int scrollX, int scrollY, int scrollRangeX, int scrollRangeY,
			int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
		// deltaY : 竖直方向的瞬时偏移量 / 变化量 dx   顶部滑到头下拉为-, 底部滑到头上拉为+
		// scrollY : 竖直方向的偏移量 / 变化量
		// scrollRangeY : 竖直方向滑动的范围
		// maxOverScrollY : 竖直方向最大滑动范围
		// isTouchEvent : 是否是手指触摸滑动, true为手指, false为惯性
		
		Log.d(TAG, "deltaY: " +deltaY + " scrollY: " + scrollY + " scrollRangeY: " + scrollRangeY
				+ " maxOverScrollY: " + maxOverScrollY + " isTouchEvent: " + isTouchEvent);
		
		// 手指拉动 并且 是下拉
		if(isTouchEvent && deltaY < 0){
			// 把拉动的瞬时变化量的绝对值交给Header, 就可以实现放大效果
			if(mImage.getHeight() <= drawableHeight){
				int newHeight = (int) (mImage.getHeight() + Math.abs(deltaY / 3.0f));
			
				// 高度不超出图片最大高度时,才让其生效
				mImage.getLayoutParams().height = newHeight;
				mImage.requestLayout();
			}
		}
		
		return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX,
				scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);
	}
	
	//触摸事件
	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		
		switch (ev.getAction()) {
			case MotionEvent.ACTION_UP:
				// 执行回弹动画, 方式一: 属性动画\值动画
				// 从当前高度mImage.getHeight(), 执行动画到原始高度mOriginalHeight
				final int startHeight = mImage.getHeight();
				final int endHeight = mOriginalHeight;
				
 			valueAnimator(startHeight, endHeight);

			 
				
				break;
		}
		return super.onTouchEvent(ev);
	}

	private void valueAnimator(final int startHeight, final int endHeight) {
		ValueAnimator mValueAnim = ValueAnimator.ofInt(1);
		//动画更新的监听,时刻监听
		mValueAnim.addUpdateListener(new AnimatorUpdateListener() {
			
			@Override
			public void onAnimationUpdate(ValueAnimator mAnim) {
				float fraction = mAnim.getAnimatedFraction();
				// percent 0.0 -> 1.0
				Log.d(TAG, "fraction: " +fraction);
				Integer newHeight = evaluate(fraction, startHeight, endHeight);

				mImage.getLayoutParams().height = newHeight;
				mImage.requestLayout();
			}
		});
		
		mValueAnim.setInterpolator(new OvershootInterpolator());//放手回弹有弹性 
		mValueAnim.setDuration(500);
		mValueAnim.start();
	}
	
    public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
        int startInt = startValue;
        return (int)(startInt + fraction * (endValue - startInt));
    }
	
	
}


 

 方式二: 自定义Animation

2.(1)

public class ResetAnimation extends Animation {

	private final ImageView mImage;
	private final int startHeight;
	private final int endHeight;

	public ResetAnimation(ImageView mImage, int startHeight, int endHeight) {
		this.mImage = mImage;
		this.startHeight = startHeight;
		this.endHeight = endHeight;
		
		setInterpolator(new OvershootInterpolator());
		//设置动画执行时长
		setDuration(500);
	}

	@Override
	protected void applyTransformation(float interpolatedTime, Transformation t) {
		// interpolatedTime 0.0f -> 1.0f
		

		Integer newHeight = evaluate(interpolatedTime, startHeight, endHeight);

		mImage.getLayoutParams().height = newHeight;
		mImage.requestLayout();
		
		super.applyTransformation(interpolatedTime, t);
	}
	
	
    /**
     * 类型估值器
     * @param fraction
     * @param startValue
     * @param endValue
     * @return
     */
    public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
        int startInt = startValue;
        return (int)(startInt + fraction * (endValue - startInt));
    }
	
	
	
}


2.(2)

/**
 * 视差特效ListView
 * overScrollBy
 * @author poplar
 *
 */
public class MyListView extends ListView {

	private static final String TAG = "TAG";
	private int mOriginalHeight;
	private int drawableHeight;
	private ImageView mImage;

	public MyListView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

	public MyListView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public MyListView(Context context) {
		super(context);
	}
	
	/**
	 * 设置ImageView图片, 拿到引用
	 * @param mImage
	 */
	public void setParallaxImage(ImageView mImage) {
		this.mImage = mImage;
		mOriginalHeight = mImage.getHeight(); // 160
		drawableHeight = mImage.getDrawable().getIntrinsicHeight(); // 488
		
		Log.d(TAG, "height: " + mOriginalHeight + " drawableHeight: " + drawableHeight);
	}
	
	@Override
	protected boolean overScrollBy(int deltaX, int deltaY, 
			int scrollX, int scrollY, int scrollRangeX, int scrollRangeY,
			int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
		// deltaY : 竖直方向的瞬时偏移量 / 变化量 dx   顶部滑到头下拉为-, 底部滑到头上拉为+
		// scrollY : 竖直方向的偏移量 / 变化量
		// scrollRangeY : 竖直方向滑动的范围
		// maxOverScrollY : 竖直方向最大滑动范围
		// isTouchEvent : 是否是手指触摸滑动, true为手指, false为惯性
		
		Log.d(TAG, "deltaY: " +deltaY + " scrollY: " + scrollY + " scrollRangeY: " + scrollRangeY
				+ " maxOverScrollY: " + maxOverScrollY + " isTouchEvent: " + isTouchEvent);
		
		// 手指拉动 并且 是下拉
		if(isTouchEvent && deltaY < 0){
			// 把拉动的瞬时变化量的绝对值交给Header, 就可以实现放大效果
			if(mImage.getHeight() <= drawableHeight){
				int newHeight = (int) (mImage.getHeight() + Math.abs(deltaY / 3.0f));
			
				// 高度不超出图片最大高度时,才让其生效
				mImage.getLayoutParams().height = newHeight;
				mImage.requestLayout();
			}
		}
		
		return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX,
				scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);
	}
	
	//触摸事件
	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		
		switch (ev.getAction()) {
			case MotionEvent.ACTION_UP:
				// 执行回弹动画, 方式一: 属性动画\值动画
				// 从当前高度mImage.getHeight(), 执行动画到原始高度mOriginalHeight
				final int startHeight = mImage.getHeight();
				final int endHeight = mOriginalHeight;
				
//				valueAnimator(startHeight, endHeight);

				// 执行回弹动画, 方式二: 自定义Animation
				ResetAnimation animation = new ResetAnimation(mImage, startHeight, endHeight);
				startAnimation(animation);
				
				break;
		}
		return super.onTouchEvent(ev);
	}

	 
	
	
}


 

 

 

 

 

 

3.MainActivity

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		
		final MyListView mListView = (MyListView) findViewById(R.id.lv);
		mListView.setOverScrollMode(View.OVER_SCROLL_NEVER);

		// 加Header
		final View mHeaderView = View.inflate(MainActivity.this, R.layout.view_header, null);
		final ImageView mImage = (ImageView) mHeaderView.findViewById(R.id.iv);
		mListView.addHeaderView(mHeaderView);
		
		mHeaderView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
			
			@Override
			public void onGlobalLayout() {
				// 当布局填充结束之后, 此方法会被调用

				mListView.setParallaxImage(mImage);    //把ImageView传到ListView中
				
				mHeaderView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
			}
		});
		
		// 填充数据
		mListView.setAdapter(new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, Cheeses.NAMES));
		
	}

}


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值