package com.ody.photopicker.fragment;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import com.nineoldandroids.animation.Animator;
import com.nineoldandroids.animation.ObjectAnimator;
import com.nineoldandroids.view.ViewHelper;
import com.nineoldandroids.view.ViewPropertyAnimator;
import com.ody.photopicker.R;
import com.ody.photopicker.adapter.PhotoPagerAdapter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Created by Samuel on 15/6/21.
*/
public class ImagePagerFragment extends Fragment {
public final static String ARG_PATH = "PATHS";
public final static String ARG_CURRENT_ITEM = "ARG_CURRENT_ITEM";
private ArrayList<String> paths;
private ViewPager mViewPager;
private PhotoPagerAdapter mPagerAdapter;
public final static long ANIM_DURATION = 200L;
public final static String ARG_THUMBNAIL_TOP = "THUMBNAIL_TOP";
public final static String ARG_THUMBNAIL_LEFT = "THUMBNAIL_LEFT";
public final static String ARG_THUMBNAIL_WIDTH = "THUMBNAIL_WIDTH";
public final static String ARG_THUMBNAIL_HEIGHT = "THUMBNAIL_HEIGHT";
public final static String ARG_HAS_ANIM = "HAS_ANIM";
private int thumbnailTop = 0;
private int thumbnailLeft = 0;
private int thumbnailWidth = 0;
private int thumbnailHeight = 0;
private boolean hasAnim = false;
private final ColorMatrix colorizerMatrix = new ColorMatrix();
private int currentItem = 0;
public static ImagePagerFragment newInstance(List<String> paths, int currentItem) {
ImagePagerFragment f = new ImagePagerFragment();
Bundle args = new Bundle();
args.putStringArray(ARG_PATH, paths.toArray(new String[paths.size()]));
args.putInt(ARG_CURRENT_ITEM, currentItem);
args.putBoolean(ARG_HAS_ANIM, false);
f.setArguments(args);
return f;
}
public static ImagePagerFragment newInstance(List<String> paths, int currentItem, int[] screenLocation, int thumbnailWidth, int thumbnailHeight) {
ImagePagerFragment f = newInstance(paths, currentItem);
f.getArguments().putInt(ARG_THUMBNAIL_LEFT, screenLocation[0]);
f.getArguments().putInt(ARG_THUMBNAIL_TOP, screenLocation[1]);
f.getArguments().putInt(ARG_THUMBNAIL_WIDTH, thumbnailWidth);
f.getArguments().putInt(ARG_THUMBNAIL_HEIGHT, thumbnailHeight);
f.getArguments().putBoolean(ARG_HAS_ANIM, true);
return f;
}
public void setPhotos(List<String> paths, int currentItem) {
this.paths.clear();
this.paths.addAll(paths);
this.currentItem = currentItem;
mViewPager.setCurrentItem(currentItem);
mViewPager.getAdapter().notifyDataSetChanged();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
paths = new ArrayList<>();
Bundle bundle = getArguments();
if (bundle != null) {
String[] pathArr = bundle.getStringArray(ARG_PATH);
paths.clear();
if (pathArr != null) {
paths = new ArrayList<>(Arrays.asList(pathArr));
}
hasAnim = bundle.getBoolean(ARG_HAS_ANIM);
currentItem = bundle.getInt(ARG_CURRENT_ITEM);
thumbnailTop = bundle.getInt(ARG_THUMBNAIL_TOP);
thumbnailLeft = bundle.getInt(ARG_THUMBNAIL_LEFT);
thumbnailWidth = bundle.getInt(ARG_THUMBNAIL_WIDTH);
thumbnailHeight = bundle.getInt(ARG_THUMBNAIL_HEIGHT);
}
mPagerAdapter = new PhotoPagerAdapter(paths);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.__picker_picker_fragment_image_pager, container, false);
mViewPager = (ViewPager) rootView.findViewById(R.id.vp_photos);
mViewPager.setAdapter(mPagerAdapter);
mViewPager.setCurrentItem(currentItem);
mViewPager.setOffscreenPageLimit(5);
// Only run the animation if we're coming from the parent activity, not if
// we're recreated automatically by the window manager (e.g., device rotation)
if (savedInstanceState == null && hasAnim) {
ViewTreeObserver observer = mViewPager.getViewTreeObserver();
observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
mViewPager.getViewTreeObserver().removeOnPreDrawListener(this);
// Figure out where the thumbnail and full size versions are, relative
// to the screen and each other
int[] screenLocation = new int[2];
mViewPager.getLocationOnScreen(screenLocation);
thumbnailLeft = thumbnailLeft - screenLocation[0];
thumbnailTop = thumbnailTop - screenLocation[1];
runEnterAnimation();
return true;
}
});
}
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
hasAnim = currentItem == position;
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
return rootView;
}
/**
* The enter animation scales the picture in from its previous thumbnail
* size/location, colorizing it in parallel. In parallel, the background of the
* activity is fading in. When the pictue is in place, the text description
* drops down.
*/
private void runEnterAnimation() {
final long duration = ANIM_DURATION;
// Set starting values for properties we're going to animate. These
// values scale and position the full size version down to the thumbnail
// size/location, from which we'll animate it back up
ViewHelper.setPivotX(mViewPager, 0);
ViewHelper.setPivotY(mViewPager, 0);
ViewHelper.setScaleX(mViewPager, (float) thumbnailWidth / mViewPager.getWidth());
ViewHelper.setScaleY(mViewPager, (float) thumbnailHeight / mViewPager.getHeight());
ViewHelper.setTranslationX(mViewPager, thumbnailLeft);
ViewHelper.setTranslationY(mViewPager, thumbnailTop);
// Animate scale and translation to go from thumbnail to full size
ViewPropertyAnimator.animate(mViewPager)
.setDuration(duration)
.scaleX(1)
.scaleY(1)
.translationX(0)
.translationY(0)
.setInterpolator(new DecelerateInterpolator());
// Fade in the black background
ObjectAnimator bgAnim = ObjectAnimator.ofInt(mViewPager.getBackground(), "alpha", 0, 255);
bgAnim.setDuration(duration);
bgAnim.start();
// Animate a color filter to take the image from grayscale to full color.
// This happens in parallel with the image scaling and moving into place.
ObjectAnimator colorizer = ObjectAnimator.ofFloat(ImagePagerFragment.this,
"saturation", 0, 1);
colorizer.setDuration(duration);
colorizer.start();
}
/**
* The exit animation is basically a reverse of the enter animation, except that if
* the orientation has changed we simply scale the picture back into the center of
* the screen.
*
* @param endAction This action gets run after the animation completes (this is
* when we actually switch activities)
*/
public void runExitAnimation(final Runnable endAction) {
if (!getArguments().getBoolean(ARG_HAS_ANIM, false) || !hasAnim) {
endAction.run();
return;
}
final long duration = ANIM_DURATION;
// Animate image back to thumbnail size/location
ViewPropertyAnimator.animate(mViewPager)
.setDuration(duration)
.setInterpolator(new AccelerateInterpolator())
.scaleX((float) thumbnailWidth / mViewPager.getWidth())
.scaleY((float) thumbnailHeight / mViewPager.getHeight())
.translationX(thumbnailLeft)
.translationY(thumbnailTop)
.setListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
endAction.run();
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
// Fade out background
ObjectAnimator bgAnim = ObjectAnimator.ofInt(mViewPager.getBackground(), "alpha", 0);
bgAnim.setDuration(duration);
bgAnim.start();
// Animate a color filter to take the image back to grayscale,
// in parallel with the image scaling and moving into place.
ObjectAnimator colorizer =
ObjectAnimator.ofFloat(ImagePagerFragment.this, "saturation", 1, 0);
colorizer.setDuration(duration);
colorizer.start();
}
/**
* This is called by the colorizing animator. It sets a saturation factor that is then
* passed onto a filter on the picture's drawable.
*
* @param value saturation
*/
public void setSaturation(float value) {
colorizerMatrix.setSaturation(value);
ColorMatrixColorFilter colorizerFilter = new ColorMatrixColorFilter(colorizerMatrix);
mViewPager.getBackground().setColorFilter(colorizerFilter);
}
public ViewPager getViewPager() {
return mViewPager;
}
public ArrayList<String> getPaths() {
return paths;
}
public int getCurrentItem() {
return mViewPager.getCurrentItem();
}
@Override
public void onDestroy() {
super.onDestroy();
paths.clear();
paths = null;
if (mViewPager != null) {
mViewPager.setAdapter(null);
}
}
}