ViewPager实现图片切换特效

2018/08/20 Android

实现要点 - ViewPager,显示左右两边,并留出一定间距,整个viewpger响应触摸事件 - 利用PageTransformer给viewpager添加切换动画,透明度及图片大小过渡变化的效果

实现如下效果

实现

### ViewPager显示左右两边 利用View的android:clipChildren属性 clipChildren:父View是否束缚子View的显示范围,如果父View有 padding, 那么子View则在padding区域是不能显示内容的, 但是如果设置android:clipChildren为false时,则子View就可以在 父View的padding区域显示内容 布局如下 ```

外层的RelativeLayout及ViewPager同时设置android:clipChildren 为false
在ViewPager中的前一页及后一页的内容即可在layout_marginLeft及
layout_marginRight的范围内显示

### viewpager页面间设置间距

viewPagerPhoto.setPageMargin(ScreenUtil.dip2px(12)); 传入的参数单位为px ### 设置触摸响应区域 以上方法实现后,只有中间的item可以触发左右滑动效果,使整个viewpager均可左右滑动需做以下设置 rlViewPagerBox.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return viewPagerPhoto.dispatchTouchEvent(event); } }); ### 设置adapter public class PhotoViewPagerAdapter extends PagerAdapter { private Context mContext; private List mImages; private OnItemClickListener onItemClickListener;

public PhotoViewPagerAdapter(Context context, List<String> mImages) {
    this.mContext = context;
    this.mImages = mImages;
}

public void setData(List<String> mImages) {
    this.mImages = mImages;
    notifyDataSetChanged();
}

@Override
public int getCount() {
    return this.mImages.size();
}

@Override
public boolean isViewFromObject(View arg0, Object arg1) {
    return arg0 == arg1;
}

@Override
public void destroyItem(View container, int position, Object object) {
    ((ViewPager) container).removeView((View) object);
}

@Override
public Object instantiateItem(View container, int position) {
    ImageView image = new ImageView(mContext);
    GlideUtils.INSTANCE.setRoundImageByUrl(mContext, image, mImages.get(position), R.drawable.loading_image_default, R.drawable.loading_image_default);
    image.setScaleType(ImageView.ScaleType.CENTER_CROP);
    image.setCropToPadding(true);
    image.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (onItemClickListener != null) {
                onItemClickListener.onItemClick();
            }
        }
    });
    ((ViewPager) container).addView(image);
    return image;
}

public interface OnItemClickListener {
    void onItemClick();
}

public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
    this.onItemClickListener = onItemClickListener;
} } ``` ### viewpager切换增加动画效果 #### 实现PhotoPageTransformer implements ViewPager.PageTransformer ``` public class PhotoPageTransformer implements ViewPager.PageTransformer {
private static final float MIN_SCALE = 0.9f;

private float mMinAlpha = 0.3f;
private float leftScaleY = 0.9f;
private float rightScaleY = 0.5f;
private float leftTransY = 0.05f; //(1-0.9)/2
private float rightTransY = 0.25f;

public void transformPage(View view, float position) {
    int pageHeight = view.getHeight();
    LogUtils.e("transformPage position: " + view + "," + position);
    if (position < -1) { // [-Infinity,-1)  This page is way off-screen to the left.
        view.setAlpha(mMinAlpha);
        view.setScaleY(leftScaleY);
        view.setTranslationY(pageHeight * leftTransY);
    } else if (position <= 1) {
        if (position <= 0) { //[-1,0) 左滑  a页滑动至b页:a页从 0.0~-1,b页从1 ~ 0.0
            //1到mMinAlpha
            float factor = mMinAlpha + (1 - mMinAlpha) * (1 + position);
            view.setAlpha(factor);
            view.setScaleY(leftScaleY + (1 - leftScaleY) * (1 + position));
            //0到leftTransY的变化
            view.setTranslationY(-pageHeight * (leftTransY * position));
        } else //[0,1]  1~0
        {
            //minAlpha到1的变化
            float factor = mMinAlpha + (1 - mMinAlpha) * (1 - position);
            view.setAlpha(factor);
            view.setScaleY(rightScaleY + (1 - rightScaleY) * (1 - position));
            //rightTransY到0的变化
            view.setTranslationY(pageHeight * (rightTransY * position));
        }
    } else {  // (1,+Infinity]
        // This page is way off-screen to the right.
        view.setAlpha(mMinAlpha);
        view.setScaleY(rightScaleY);
        view.setTranslationY(pageHeight * rightTransY);
    }
} } ``` postion:
  • [-Infinity,-1):左边的页面
  • (1,+Infinity]:右边的页面
  • [-1,1]:中间显示的页面

对于左边及右边的页面,直接设置页面的最终效果的状态值即可,这里设置了透明度及Y轴缩放,因为Y轴缩放是以中心进行缩放,因此对其进行了向下的平移操作使其底部对齐。

假设a为当前中间显示页面,b为右边下一个页面 a页滑动至b页即左滑,positon的变化范围:a页从0.0~-1,b页从1 ~ 0.0。

  • a到左边,对应alpha应该是:1到minAlpha,setScaleY:1到leftScaleY,TranslationY:0到leftTransY
  • b到中间,对应alpha应该是:minAlpha到1,setScaleY:rightScaleY到1,TranslationY:rightTransY到0

对于a页,计算1到minAlpha过程:

  • position:0~-1
  • 1+position:1~0
  • (1-mMinAlpha)*(1+position):(1 - mMinAlpha)~0
  • mMinAlpha+(1-mMinAlpha)*(1 + position):1~minAlpha 其他以此类推

viewPager.setPageTransformer

photoViewPagerAdapter = new PhotoViewPagerAdapter(this, mImageViews);
viewPagerPhoto.setPageTransformer(true, new PhotoPageTransformer());

## 总结 ok,至此便完成整个切换效果 ## 参考文章 Android 实现个性的ViewPager切换动画

Search

    Table of Contents