ViewPager的视差背景效果

原创 2015年07月09日 14:32:23

这很的app中都用到了ViewPager滑动背景也跟着变动,最近写了个解锁项目其中也需要实现这个效果自己也写了下,由于锁屏只有2个页面,所有ViewPager只2个页面的滑动,如果想要多个页面可以修改下代码就行了,代码有注释,修改也比较容易.代码如下:

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

@SuppressLint("NewApi")
public class ParallaxViewPager extends ViewPager {

	public static final int FIT_WIDTH = 0;
	public static final int FIT_HEIGHT = 1;
	public static final float OVERLAP_FULL = 1f;
	public static final float OVERLAP_HALF = 0.5f;
	public static final float OVERLAP_QUARTER = 0.25f;
	public Bitmap bitmap;
	private Rect source, destination;
	private int scaleType;
	private Paint paint;
	private OnPageChangeListener secondOnPageChangeListener;

	public ParallaxViewPager(Context context) {
		super(context);
		init();
	}

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

	private void init() {
		paint = new Paint(Paint.ANTI_ALIAS_FLAG);
		source = new Rect();
		destination = new Rect();
		scaleType = FIT_HEIGHT;
		//滑动时会调用这个方法 所以我们就在这个方法了来处理图片的移动
		setOnPageChangeListener(new OnPageChangeListener() {
			@Override
			//position 是ViewPager展示的是第几个位置 positionOffset移动时变化的值(如从第0页移动到1页,它的变化0~1之间变化)
			public void onPageScrolled(int position, float positionOffset,
					int positionOffsetPixels) {
				if (bitmap != null) {
					if (position == 0) {
						//这是从0页滑动第1页
						//source 和destination是图片矩阵,由于后面的背景只有一张source矩阵的移动范围只有getWidth/8,
						//如果太大了ViewPagery移动到第二页的时候背景就感觉不到移动了,
						//而ViewPager有两页,所以destination矩阵的移动范围是两个getWidth那么宽
						source.left = (int) ((getWidth() / 8) * positionOffset);
						source.right = getWidth() + source.left;
						destination.left = (int) ((getWidth() * positionOffset) - getWidth());
						destination.right = (int) (0 + (getWidth() * positionOffset));

					} else {
						//这是从1页滑动第0页移动的范围刚好相反
						source.left = (int) ((getWidth() / 8) - (getWidth() / 8)
								* positionOffset);
						source.right = getWidth() + source.left;
						destination.left = (int) ((0 - getWidth()
								* positionOffset));
						destination.right = (int) (getWidth() - (getWidth() * positionOffset));
					}

					postInvalidate();
				}

				if (secondOnPageChangeListener != null) {
					secondOnPageChangeListener.onPageScrolled(position,
							positionOffset, positionOffsetPixels);
				}
			}

			@Override
			public void onPageSelected(int position) {
				if (secondOnPageChangeListener != null) {
					secondOnPageChangeListener.onPageSelected(position);
				}
			}

			@Override
			public void onPageScrollStateChanged(int state) {
				if (secondOnPageChangeListener != null) {
					secondOnPageChangeListener.onPageScrollStateChanged(state);
				}
			}
		});
	}

	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
		destination.top = 0;
		destination.bottom = h;
		if (getAdapter() != null && bitmap != null)
			calculateParallaxParameters();
	}

	private void calculateParallaxParameters() {
		if (bitmap.getWidth() < getWidth()
				&& bitmap.getWidth() < bitmap.getHeight()
				&& scaleType == FIT_HEIGHT) {
			Log.w(ParallaxViewPager.class.getName(),
					"Invalid bitmap bounds for the current device, parallax effect will not work.");
		}
		source.top = 0;
		source.bottom = bitmap.getHeight();

	}

	/**
	 * Sets the background from a resource file.
	 * 
	 * @param resid
	 */
	@Override
	public void setBackgroundResource(int resid) {
		bitmap = BitmapFactory.decodeResource(getResources(), resid);
	}

	/**
	 * Sets the background from a Drawable.
	 * 
	 * @param background
	 */
	@Override
	public void setBackground(Drawable background) {
		bitmap = ((BitmapDrawable) background).getBitmap();
	}

	/**
	 * Deprecated. Sets the background from a Drawable.
	 * 
	 * @param background
	 */
	@Override
	public void setBackgroundDrawable(Drawable background) {
		bitmap = ((BitmapDrawable) background).getBitmap();
	}

	/**
	 * Sets the background from a bitmap.
	 * 
	 * @param bitmap
	 * @return The ParallaxViewPager object itself.
	 */
	public ParallaxViewPager setBackground(Bitmap bitmap) {
		this.bitmap = bitmap;
		return this;
	}

	//设置图片展示的属性
	public ParallaxViewPager setScaleType(final int scaleType) {
		if (scaleType != FIT_WIDTH && scaleType != FIT_HEIGHT)
			throw new IllegalArgumentException(
					"Illegal argument: scaleType must be FIT_WIDTH or FIT_HEIGHT");
		this.scaleType = scaleType;
		return this;
	}

	/**
	 * Sets the amount of overlapping with the setOverlapPercentage(final float
	 * percentage) method. This is a number between 0 and 1, the smaller it is,
	 * the slower is the background scrolling.
	 * 
	 * @param percentage
	 * @return The ParallaxViewPager object itself.
	 */
	public ParallaxViewPager setOverlapPercentage(final float percentage) {
		if (percentage <= 0 || percentage >= 1)
			throw new IllegalArgumentException(
					"Illegal argument: percentage must be between 0 and 1");
		return this;
	}

	/**
	 * Recalculates the parameters of the parallax effect, useful after changes
	 * in runtime.
	 * 
	 * @return The ParallaxViewPager object itself.
	 */
	public ParallaxViewPager invalidateParallaxParameters() {
		calculateParallaxParameters();
		return this;
	}
	//画背景
	@Override
	protected void onDraw(Canvas canvas) {
		if (bitmap != null) {
			canvas.drawBitmap(bitmap, source, destination, paint);
		}
	}
	//viewPager滑动的监听
	public void addOnPageChangeListener(OnPageChangeListener listener) {
		secondOnPageChangeListener = listener;
	}
}

具体的调用如下:

//初始化
viewPager = (ParallaxViewPager)findViewById(R.id.lock_viewpager);
//设置背景
viewPager.setBackgroundDrawable(new BitmapDrawable());
//ViewPager设置适配器		
viewPager.setAdapter(new MyViewPagerAdapter());
//设置滑动监听
viewPager.addOnPageChangeListener(this);
//跳转到指定的页面
viewPager.setCurrentItem(mList.size());


ViewPager+属性动画 实现炫酷视差动画效果

ViewPager有一个setPageTransform()方法可以实现很多酷炫的动画效果 先来个仿QQ的侧滑面板效果 vp.setPageTransformer(true, new Page...
  • B1ueKid
  • B1ueKid
  • 2016年05月13日 15:02
  • 3944

Android引导界面设计之ParallaxViewPager视差效果

引导界面大多都是利用ViewPager实现,通过左右滑动来展示应用程序的功能、特色、使用方式等。具体的实现也很简单,写几个要展示的xml布局文件,通过ViewPager的Adapter适配给ViewP...
  • shangmingchao
  • shangmingchao
  • 2015年08月17日 10:28
  • 1510

ParallaxViewPager:ViewPager的视差背景效果

源码: import android.annotation.SuppressLint; import android.content.Context; import android.graph...
  • gundumw100
  • gundumw100
  • 2017年04月10日 19:08
  • 261

android viewPager 左右滑动时的错位视差

android viewPager 左右滑动时的错位视差
  • u014608640
  • u014608640
  • 2016年09月22日 09:41
  • 1268

Android的Viewpager视差滑动效果小demo

Android的Viewpager视差滑动效果前言以前下载app,发现有的app的欢迎页做的是动态的视差的那种效果,作为一个比较关心技术的,又有点懒惰的Android开发者我虽然一直对这个效果耿耿于怀...
  • dreamsever
  • dreamsever
  • 2016年10月28日 14:49
  • 1007

用ViewPager为你的APP引导页添加视差滚动(Parallax Scrolling)效果

什么是视差滚动 视差滚动效果是怎样的 如何实现视差滚动效果 1 通过使用ViewPager实现页面的左右滑动 2 ViewPager有办法实现ParallaxScrolling吗 3 ViewPage...
  • sara_loveyou
  • sara_loveyou
  • 2015年03月13日 17:44
  • 2038

类似Launcher壁纸的视差背景效果

转载地址http://mp.weixin.qq.com/s?__biz=MzAxMTI4MTkwNQ==&mid=2650820494&idx=1&sn=1af3e5bd98e347ce9bde72f...
  • scott2017
  • scott2017
  • 2016年06月24日 10:13
  • 719

页面滚动视差效果的实现

0x01今天在http://materializecss.com/发现一个视差滚动的例子,想自己实现一下视差效果。打开例子0x02思路首先呢,我们可以选择监听scroll和mousewheel事件,说...
  • larry011
  • larry011
  • 2016年02月05日 14:44
  • 650

你知道android中的视差特效吗

阻尼效果(视差特效)空间,微博很多地方都有这种下拉出现的”阻尼“效果,这种效果最早在ios上出现,如今android上这种功能也是很常见了。先看效果图:该功能可以分为两个点: 1. 当ListVie...
  • H_Gao
  • H_Gao
  • 2016年12月07日 23:05
  • 975

视差滚动(Parallax Scrolling)效果的原理和实现(转)

视差滚动(Parallax Scrolling)是指让多层背景以不同的速度移动,形成立体的运动效果,带来非常出色的视觉体验。作为今年网页设计的热点趋势,越来越多的网站应用了这项技术。 可以先看看效果:...
  • wangji5850
  • wangji5850
  • 2016年03月29日 13:12
  • 2629
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:ViewPager的视差背景效果
举报原因:
原因补充:

(最多只允许输入30个字)