Android仿微信朋友圈图片打开退出过渡动画

大家好,最近又是不断地改需求,终于闲下来了。看到微信朋友圈的图片打开退出的过渡动画,正好我们项目中也有类似功能,但是转换效果干巴巴的,麻麻赖赖的,一点都不圆润。没关系,盘他!先来看我实现的效果:

实现大致原理就是将当前点击的ImageView 在屏幕中的位置以及宽高传入到大图界面,在大图界面加了一个放大动画。同理,退出动画获取大图界面选中的position所对应外面的当前position的ImageView的位置及宽高设置一个缩小动画。
首先获取所有ImageView的位置及宽高,一个也是如此,在这里我新建了一个模型实现了Parcelable接口,用来存所有的ImageView位置宽高并进行传递。期初我本来想将所有的ImageView 用Intent传递,却不知道怎么传。。。如果有知道的可以告知我一下。

package com.kairui.discounts.bean; import android.os.Parcel; import android.os.Parcelable; /** * Created by fySpring * Date : 2019-03-19 * To do : */public class ImgOptionEntity implements Parcelable{ private int left; private int top; private int width; private int height; private String imgUrl; public ImgOptionEntity() {}public ImgOptionEntity(int left,int top, int width, int height) { this.left = left; this.top = top; this.width = width; this.height = height; }protected ImgOptionEntity(Parcel in) { top = in.readInt(); left = in.readInt(); width = in.readInt(); height = in.readInt(); imgUrl = in.readString(); }public static final Creator CREATOR = new Creator() { @Override public ImgOptionEntity createFromParcel(Parcel in) { return new ImgOptionEntity(in); }@Override public ImgOptionEntity[] newArray(int size) { return new ImgOptionEntity[size]; } }; public int getTop() { return top; }public void setTop(int top) { this.top = top; }public int getLeft() { return left; }public void setLeft(int left) { this.left = left; }public int getWidth() { return width; }public void setWidth(int width) { this.width = width; }public int getHeight() { return height; }public void setHeight(int height) { this.height = height; }public String getImgUrl() { return imgUrl; }public void setImgUrl(String imgUrl) { this.imgUrl = imgUrl; }@Override public int describeContents() { return 0; }@Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(top); dest.writeInt(left); dest.writeInt(width); dest.writeInt(height); dest.writeString(imgUrl); } }

遍历获取所有宽高进行跳转
//这里就是当前获取到的所有ImageVIew 的 list,换成你的即可 ArrayList imgDatas = new ArrayList<>(); ArrayList optionEntities = new ArrayList<>(); int[] screenLocationS = new int[2]; for (int i = 0; i < imgDatas.size(); i++) { ImageView img = imgDatas.get(i); //获取当前ImageView 在屏幕中的位置 宽高 img.getLocationOnScreen(screenLocationS); ImgOptionEntity entity = new ImgOptionEntity(screenLocationS[0],screenLocationS[1],img.getWidth(),img.getHeight()); optionEntities.add(entity); }Intent bIntent = new Intent(this, BigImgViewActivity.class); bIntent.putExtra(ConstantCode.imgPosition, curPosition); bIntent.putParcelableArrayListExtra(ConstantCode.optionEntities, optionEntities); startActivity(bIntent); //取消原有默认的Activity到Activity的过渡动画 overridePendingTransition(0, 0);

接下来关键的代码都在大图界面了,这里我用了ViewPager + PhotoView,你可以只有ImageView来查看也可以。注释都在代码里了,无用的代码我都删除,只留下了和功能相关的代码
/** * Created by fySpring * Date : 2019-03-19 * To do :全屏查看大图页面 */public class BigImgViewActivity extends BaseActivity implements ViewPager.OnPageChangeListener {private static final int DURATION = 250; @Bind(R.id.big_image_list_vp) private ViewPager imgListVp; @Bind(R.id.big_image_num_tv) private TextView imageNumTv; @Bind(R.id.big_image_bg_rl) private RelativeLayout bgRl; private int imgPosition; private List photoViewList; //开始的坐标值 private int startY; private int startX; //开始的宽高 private int startWidth; private int startHeight; //X、Y的移动距离 private int xDelta; private int yDelta; //X、Y的缩放比例 private float mWidthScale; private float mHeightScale; //背景色 private ColorDrawable colorDrawable; //当前选中的photoView private PhotoView curPhotoView; //所有图片的位置大小参数 private ArrayList optionEntities; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_show_big_image); initView(); initData(); }@Override protected void initView() { //修改状态栏颜色 StatusBarUtil.setColorNoTranslucent(this, Color.BLACK); //全屏 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); //设置背景色,后面需要为其设置渐变动画 colorDrawable = new ColorDrawable(ContextCompat.getColor(this, R.color.black)); bgRl.setBackground(colorDrawable); }@Override protected void initData() { photoViewList = new ArrayList<>(); imgPosition = getIntent().getIntExtra(ConstantCode.imgPosition, 0); //获取到当前所有ImageView对应的位置 optionEntities = getIntent().getParcelableArrayListExtra(ConstantCode.optionEntities); if (optionEntities != null && !optionEntities.isEmpty()) { //设置选中的位置来初始化动画 ImgOptionEntity entity = optionEntities.get(imgPosition); startY = entity.getTop(); startX = entity.getLeft(); startWidth = entity.getWidth(); startHeight = entity.getHeight(); imageNumTv.setText(imgPosition + 1 + "/" + optionEntities.size()); for (int i = 0; i < optionEntities.size(); i++) { addItemPhotoView(optionEntities.get(i).getImgUrl()); } if (optionEntities.size() == 1) imageNumTv.setVisibility(View.GONE); else imageNumTv.setVisibility(View.VISIBLE); }ImageListAdapter imageListAdapter = new ImageListAdapter(); imgListVp.setAdapter(imageListAdapter); imgListVp.setOnPageChangeListener(this); imgListVp.setCurrentItem(imgPosition); if (!photoViewList.isEmpty()) { curPhotoView = photoViewList.get(imgPosition); //注册一个回调函数,当一个视图树将要绘制时调用这个回调函数。 ViewTreeObserver observer = curPhotoView.getViewTreeObserver(); observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { curPhotoView.getViewTreeObserver().removeOnPreDrawListener(this); int[] screenLocation = new int[2]; curPhotoView.getLocationOnScreen(screenLocation); //动画需要移动的距离 xDelta = startX - screenLocation[0]; yDelta = startY - screenLocation[1]; //计算缩放比例 mWidthScale = (float) startWidth / curPhotoView.getWidth(); mHeightScale = (float) startHeight / curPhotoView.getHeight(); enterAnimation(new Runnable() { @Override public void run() { //开始动画之后要做的操作 } }); //返回 true 继续绘制,返回false取消。 return true; } }); } }private void enterAnimation(final Runnable enterAction) { //放大动画 curPhotoView.setPivotX(0); curPhotoView.setPivotY(0); curPhotoView.setScaleX(mWidthScale); curPhotoView.setScaleY(mHeightScale); curPhotoView.setTranslationX(xDelta); curPhotoView.setTranslationY(yDelta); TimeInterpolator sDecelerator = new DecelerateInterpolator(); curPhotoView.animate().setDuration(DURATION).scaleX(1).scaleY(1). translationX(0).translationY(0).setInterpolator(sDecelerator).withEndAction(enterAction); //设置背景渐变成你设置的颜色 ObjectAnimator bgAnim = ObjectAnimator.ofInt(colorDrawable, "alpha", 0, 255); bgAnim.setDuration(DURATION); bgAnim.start(); }private void exitAnimation(final Runnable endAction) { //缩小动画 curPhotoView.setPivotX(0); curPhotoView.setPivotY(0); curPhotoView.setScaleX(1); curPhotoView.setScaleY(1); curPhotoView.setTranslationX(0); curPhotoView.setTranslationY(0); TimeInterpolator sInterpolator = new AccelerateInterpolator(); curPhotoView.animate().setDuration(DURATION).scaleX(mWidthScale).scaleY(mHeightScale). translationX(xDelta).translationY(yDelta).setInterpolator(sInterpolator).withEndAction(endAction); //设置背景渐透明 ObjectAnimator bgAnim = ObjectAnimator.ofInt(colorDrawable, "alpha", 0); bgAnim.setDuration(DURATION); bgAnim.start(); }@Override public void onBackPressed() { int[] screenLocation = new int[2]; curPhotoView.getLocationOnScreen(screenLocation); xDelta = startX - screenLocation[0]; yDelta = startY - screenLocation[1]; mWidthScale = (float) startWidth / curPhotoView.getWidth(); mHeightScale = (float) startHeight / curPhotoView.getHeight(); exitAnimation(new Runnable() { public void run() { //结束动画要做的操作 finish(); overridePendingTransition(0, 0); } }); }private void addItemPhotoView(String imgUrlStr) { PhotoView photoView = new PhotoView(this); Glide.with(this) .load(imgUrlStr) .diskCacheStrategy(DiskCacheStrategy.SOURCE) .crossFade() .into(photoView); photoView.setOnPhotoTapListener(new PhotoViewAttacher.OnPhotoTapListener() { @Override public void onPhotoTap(View view, float x, float y) { onBackPressed(); } }); photoViewList.add(photoView); }@Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}@Override public void onPageSelected(int position) { //当ViewPager滚动时重置成position对应外面的ImageView的位置信息 curPhotoView = photoViewList.get(position); if (optionEntities != null && !optionEntities.isEmpty()) { ImgOptionEntity entity = optionEntities.get(position); startY = entity.getTop(); startX = entity.getLeft(); startWidth = entity.getWidth(); startHeight = entity.getHeight(); imageNumTv.setText(position + 1 + "/" + optionEntities.size()); } }@Override public void onPageScrollStateChanged(int state) {}public class ImageListAdapter extends PagerAdapter {@Override public int getCount() { return photoViewList.size(); }@Override public boolean isViewFromObject(View arg0, Object arg1) { return arg0 == arg1; }/** * 载入图片进去,用当前的position 除以 图片数组长度取余数是关键 */ public Object instantiateItem(android.view.ViewGroup container, int position) { container.addView(photoViewList.get(position)); return photoViewList.get(position); }public void destroyItem(android.view.ViewGroup container, int position, Object object) { container.removeView(photoViewList.get(position)); }} }

以上的代码就是全部了,由于是写在项目里,就没有Demo啦,大家要多动手哦~
【Android仿微信朋友圈图片打开退出过渡动画】顺便打个广告,上图所展示的APP叫惠购,由我独立开发,可以帮你领取到淘宝、京东的大额优惠券,还能返现,各大应用平台都可以下载,记得填我的邀请码哦(HXFNUN)。如果你安装了这个App,使用遇到什么问题,请一定要告诉我,因为我的测试机太少了 emmmm.....

    推荐阅读