ViewPager的视差背景效果

这很的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());


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
parallaxviewpager是一个具有视差滚动效果ViewPager。所谓视差滚动(Parallax Scrolling)是指让多层背景以不同的速度移动,形成立体的运动效果,带来非常出色的视觉体验。parallaxviewpager通过设置一个背景图片,使原有的ViewPager页面与这个背景图片间实现视差效果。这就要求你的背景图片的高宽比要大于屏幕的高宽比。效果非常不错。项目地址:https://github.com/andraskindler/parallaxviewpager 效果图:如何使用:parallaxviewpager是扩展了ViewPager,所有基本使用二者是相同的。在xml中布局中创建ParallaxViewPager<com.andraskindler.parallaxviewpager.ParallaxViewPager          android:id="@ id/viewPager"          android:layout_width="match_parent"          android:layout_height="match_parent"/>2. 创建了ParallaxViewPager之后,可以使用下面的方法来设置背景,或者也可以xml设置:1) setBackgroundResource(int resid)2) setBackground(Drawable background) or setBackgroundDrawable(Drawable background)3) setBackground(Bitmap bitmap)这就好了,你现在可以使用ParallaxViewPager的全部功能了。你可以修改背景的滚动效果来优化用户体验。你也可以使用setScaleType(final int scaleType)方法来配置视图的图像缩放方式。这个方法只能和FIT_HEIGHT搭配使用,从下面的参数中进行选择:FIT_HEIGHT表示缩放图像的高度以便适配视图的高度,同时缩放图像的宽度以便保持宽高比。bitmap的不可见部分被划分成相同的区域,每个区域插入到合适的位置。FIT_HEIGHT是默认值。FIT_WIDTH表示背景图像的宽度被划分成相同的块,每一块占满整个屏幕的宽度。这个模式不适用于视差效果,因为背景和视图的滚动速度一样。你也可以使用setOverlapPercentage(final float percentage) 方法来设置重叠的程度。重叠程度值介于0到1之间,这个值越小背景就滚动地越慢,默认值是50%。ParallaxViewPager viewPager = (ParallaxViewPager)this.findViewById(R.id.viewPager); viewPager.setBackgroundResource(R.drawable.bg); viewPager.setOverlapPercentage(0.75f); PageAdapter adapter = new PageAdapter(getSupportFragmentManager()); viewPager.setAdapter(adapter);项目作者并没有提供demo,完整实例可点击上面的"下载源码"获得。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值