package com.lzy.ninegrid.preview; import android.animation.Animator; import android.animation.ValueAnimator; import android.app.Activity; import android.content.Intent; import android.graphics.Color; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.support.v4.view.ViewPager; import android.util.DisplayMetrics; import android.view.View; import android.view.ViewTreeObserver; import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.TextView; import com.lzy.ninegrid.ImageInfo; import com.lzy.ninegrid.R; import java.util.List; public class ImagePreviewActivity extends Activity implements ViewTreeObserver.OnPreDrawListener { public static final String IMAGE_INFO = "IMAGE_INFO"; public static final String CURRENT_ITEM = "CURRENT_ITEM"; public static final int ANIMATE_DURATION = 200; private RelativeLayout rootView; private ImagePreviewAdapter imagePreviewAdapter; private List<ImageInfo> imageInfo; private int currentItem; private int imageHeight; private int imageWidth; private int screenWidth; private int screenHeight; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_preview); ViewPager viewPager = (ViewPager) findViewById(R.id.viewPager); final TextView tv_pager = (TextView) findViewById(R.id.tv_pager); rootView = (RelativeLayout) findViewById(R.id.rootView); DisplayMetrics metric = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metric); screenWidth = metric.widthPixels; screenHeight = metric.heightPixels; Intent intent = getIntent(); imageInfo = (List<ImageInfo>) intent.getSerializableExtra(IMAGE_INFO); currentItem = intent.getIntExtra(CURRENT_ITEM, 0); imagePreviewAdapter = new ImagePreviewAdapter(this, imageInfo); viewPager.setAdapter(imagePreviewAdapter); viewPager.setCurrentItem(currentItem); viewPager.getViewTreeObserver().addOnPreDrawListener(this); viewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { @Override public void onPageSelected(int position) { currentItem = position; tv_pager.setText(String.format(getString(R.string.select), currentItem + 1, imageInfo.size())); } }); tv_pager.setText(String.format(getString(R.string.select), currentItem + 1, imageInfo.size())); } @Override public void onBackPressed() { finishActivityAnim(); } /** 绘制前开始动画 */ @Override public boolean onPreDraw() { rootView.getViewTreeObserver().removeOnPreDrawListener(this); final View view = imagePreviewAdapter.getPrimaryItem(); final ImageView imageView = imagePreviewAdapter.getPrimaryImageView(); computeImageWidthAndHeight(imageView); final ImageInfo imageData = imageInfo.get(currentItem); final float vx = imageData.imageViewWidth * 1.0f / imageWidth; final float vy = imageData.imageViewHeight * 1.0f / imageHeight; ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1.0f); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { long duration = animation.getDuration(); long playTime = animation.getCurrentPlayTime(); float fraction = duration > 0 ? (float) playTime / duration : 1f; if (fraction > 1) fraction = 1; view.setTranslationX(evaluateInt(fraction, imageData.imageViewX + imageData.imageViewWidth / 2 - imageView.getWidth() / 2, 0)); view.setTranslationY(evaluateInt(fraction, imageData.imageViewY + imageData.imageViewHeight / 2 - imageView.getHeight() / 2, 0)); view.setScaleX(evaluateFloat(fraction, vx, 1)); view.setScaleY(evaluateFloat(fraction, vy, 1)); view.setAlpha(fraction); rootView.setBackgroundColor(evaluateArgb(fraction, Color.TRANSPARENT, Color.BLACK)); } }); addIntoListener(valueAnimator); valueAnimator.setDuration(ANIMATE_DURATION); valueAnimator.start(); return true; } /** activity的退场动画 */ public void finishActivityAnim() { final View view = imagePreviewAdapter.getPrimaryItem(); final ImageView imageView = imagePreviewAdapter.getPrimaryImageView(); computeImageWidthAndHeight(imageView); final ImageInfo imageData = imageInfo.get(currentItem); final float vx = imageData.imageViewWidth * 1.0f / imageWidth; final float vy = imageData.imageViewHeight * 1.0f / imageHeight; final ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1.0f); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { long duration = animation.getDuration(); long playTime = animation.getCurrentPlayTime(); float fraction = duration > 0 ? (float) playTime / duration : 1f; if (fraction > 1) fraction = 1; view.setTranslationX(evaluateInt(fraction, 0, imageData.imageViewX + imageData.imageViewWidth / 2 - imageView.getWidth() / 2)); view.setTranslationY(evaluateInt(fraction, 0, imageData.imageViewY + imageData.imageViewHeight / 2 - imageView.getHeight() / 2)); view.setScaleX(evaluateFloat(fraction, 1, vx)); view.setScaleY(evaluateFloat(fraction, 1, vy)); view.setAlpha(1 - fraction); rootView.setBackgroundColor(evaluateArgb(fraction, Color.BLACK, Color.TRANSPARENT)); } }); addOutListener(valueAnimator); valueAnimator.setDuration(ANIMATE_DURATION); valueAnimator.start(); } /** 计算图片的宽高 */ private void computeImageWidthAndHeight(ImageView imageView) { // 获取真实大小 Drawable drawable = imageView.getDrawable(); int intrinsicHeight = drawable.getIntrinsicHeight(); int intrinsicWidth = drawable.getIntrinsicWidth(); // 计算出与屏幕的比例,用于比较以宽的比例为准还是高的比例为准,因为很多时候不是高度没充满,就是宽度没充满 float h = screenHeight * 1.0f / intrinsicHeight; float w = screenWidth * 1.0f / intrinsicWidth; if (h > w) h = w; else w = h; // 得出当宽高至少有一个充满的时候图片对应的宽高 imageHeight = (int) (intrinsicHeight * h); imageWidth = (int) (intrinsicWidth * w); } /** 进场动画过程监听 */ private void addIntoListener(ValueAnimator valueAnimator) { valueAnimator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { rootView.setBackgroundColor(0x0); } @Override public void onAnimationEnd(Animator animation) { } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } }); } /** 退场动画过程监听 */ private void addOutListener(ValueAnimator valueAnimator) { valueAnimator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { rootView.setBackgroundColor(0x0); } @Override public void onAnimationEnd(Animator animation) { finish(); overridePendingTransition(0, 0); } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } }); } /** Integer 估值器 */ public Integer evaluateInt(float fraction, Integer startValue, Integer endValue) { int startInt = startValue; return (int) (startInt + fraction * (endValue - startInt)); } /** Float 估值器 */ public Float evaluateFloat(float fraction, Number startValue, Number endValue) { float startFloat = startValue.floatValue(); return startFloat + fraction * (endValue.floatValue() - startFloat); } /** Argb 估值器 */ public int evaluateArgb(float fraction, int startValue, int endValue) { int startA = (startValue >> 24) & 0xff; int startR = (startValue >> 16) & 0xff; int startG = (startValue >> 8) & 0xff; int startB = startValue & 0xff; int endA = (endValue >> 24) & 0xff; int endR = (endValue >> 16) & 0xff; int endG = (endValue >> 8) & 0xff; int endB = endValue & 0xff; return (startA + (int) (fraction * (endA - startA))) << 24// | (startR + (int) (fraction * (endR - startR))) << 16// | (startG + (int) (fraction * (endG - startG))) << 8// | (startB + (int) (fraction * (endB - startB))); } }