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<ImgOptionEntity> CREATOR = new Creator<ImgOptionEntity>() {
        @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<ImageView> imgDatas = new ArrayList<>();

ArrayList<ImgOptionEntity> 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<PhotoView> 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<ImgOptionEntity> 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啦,大家要多动手哦~ 

顺便打个广告,上图所展示的APP叫惠购,由我独立开发,可以帮你领取到淘宝、京东的大额优惠券,还能返现,各大应用平台都可以下载,记得填我的邀请码哦(HXFNUN)。如果你安装了这个App,使用遇到什么问题,请一定要告诉我,因为我的测试机太少了 emmmm.....

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

斯普润丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值