package oak.widget;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
/**
* Gallery-esque ViewPager that supports zoom gestures.
*/
public class SwankyGallery extends FrameLayout {
private boolean hasBeenZooming;
private Context mContext;
private SwankyViewPager mViewPager;
private SwankyAdapter mAdapter;
private static final BitmapFactory.Options LO_RES_OPTIONS = new BitmapFactory.Options(),
HI_RES_OPTIONS = new BitmapFactory.Options();
private float xPosPrev;
private float mMaxZoom = 2.5f;
private OnGalleryPageSelectedListener mPageSelectedListener = null;
// unused
static { LO_RES_OPTIONS.inSampleSize = 2; HI_RES_OPTIONS.inSampleSize = 1; }
public SwankyGallery(Context context) {
super(context);
init(context, null);
}
public SwankyGallery(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public SwankyGallery(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
mContext = context;
mViewPager = new SwankyViewPager(context, attrs);
mViewPager.setSaveEnabled(false);
addView(mViewPager);
if (attrs != null) {
// do stuff with attrs
}
}
public void setAdapter(SwankyAdapter adapter) {
mViewPager.setAdapter(mAdapter = adapter);
}
/**
* Sets maximum alpha when buttons fade in
*
* @param item set which item to go to
* @param smoothScroll boolean on whether to smooth scroll or not
*/
public void setCurrentItem(int item, boolean smoothScroll) {
mViewPager.setCurrentItem(item, smoothScroll);
}
/**
* Set the max zoom level
*
* @param maxZoom max zoom level
*/
public void setMaxZoom(float maxZoom) {
mMaxZoom = maxZoom;
}
public void setOffscreenPageLimit(int limit) {
mViewPager.setOffscreenPageLimit(limit);
}
public void setOnGalleryPageSelectedListener(OnGalleryPageSelectedListener listener) {
mPageSelectedListener = listener;
}
/**
* Unused
* @param sampleSize sample size
*/
public void setLowSampleSize(int sampleSize) {
if (sampleSize < HI_RES_OPTIONS.inSampleSize) {
throw new IllegalArgumentException("Low-res sample size may not be less than high-res");
} else {
LO_RES_OPTIONS.inSampleSize = sampleSize;
}
}
/**
* Unused
* @param sampleSize sample size
*/
public void setHighSampleSize(int sampleSize) {
if (sampleSize > LO_RES_OPTIONS.inSampleSize) {
throw new IllegalArgumentException("High-res sample size may not be greater than low-res");
} else {
HI_RES_OPTIONS.inSampleSize = sampleSize;
}
}
@Override
public final boolean onInterceptTouchEvent(MotionEvent event) {
return true;
}
@Override
public final boolean onTouchEvent(MotionEvent event) {
int action = event.getAction() & MotionEvent.ACTION_MASK;
SwankyImageView currentView = mViewPager.getCurrentView();
switch (action) {
case MotionEvent.ACTION_DOWN:
hasBeenZooming = false;
mViewPager.onInterceptTouchEvent(event); // required to initiate ViewPager behavior
mViewPager.onTouchEvent(event);
currentView.onTouchEvent(event);
break;
case MotionEvent.ACTION_POINTER_DOWN:
currentView.onTouchEvent(event);
hasBeenZooming = true;
break;
case MotionEvent.ACTION_POINTER_UP:
currentView.onTouchEvent(event);
break;
case MotionEvent.ACTION_MOVE:
if (event.getPointerCount() >= 2) {
currentView.onTouchEvent(event);
} else if (currentView.getCurrentScale() == 1 && !hasBeenZooming) {
mViewPager.onTouchEvent(event);
} else {
mViewPager.getCurrentView().onTouchEvent(event);
if (!hasBeenZooming) {
if ((xPosPrev < event.getX() && !mViewPager.getCurrentView()
.canScrollLeft()) ||
(xPosPrev > event.getX() && !mViewPager.getCurrentView()
.canScrollRight())) {
mViewPager.onTouchEvent(event);
}
}
}
break;
default:
if (!hasBeenZooming) {
mViewPager.onTouchEvent(event);
}
mViewPager.getCurrentView().onTouchEvent(event);
}
xPosPrev = event.getX();
return true;
}
public static class SwankyAdapter extends PagerAdapter {
private Context mContext;
private int[] mIds;
public SwankyAdapter(Context context, int[] imageIds) {
mContext = context;
mIds = imageIds;
}
public SwankyImageView instantiateItem(ViewGroup container, int position) {
SwankyImageView img = new SwankyImageView(mContext);
img.setImageBitmap(BitmapFactory.decodeResource(mContext.getResources(), mIds[position],
HI_RES_OPTIONS));
container.addView(img);
img.setTag(position);
return img;
}
public int getCount() {
return mIds.length;
}
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
}
private class SwankyViewPager extends ViewPager {
private int currentItem = 0;
private final SimpleOnPageChangeListener pageChangeListener = new SimpleOnPageChangeListener() {
@Override
public void onPageSelected(int i) {
View prev = findViewWithTag(currentItem);
if (prev != null) {
if (((SwankyImageView) prev).getCurrentScale() > 1) {
((SwankyImageView) prev).resetScale();
}
}
currentItem = i;
if (mPageSelectedListener != null) {
mPageSelectedListener.onPageSelected(i);
}
}
};
public SwankyViewPager(Context context) {
super(context);
setOnPageChangeListener(pageChangeListener);
}
public SwankyViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
setOnPageChangeListener(pageChangeListener);
}
@Override
protected void onPageScrolled(int position, float offset, int offsetPixels) {
super.onPageScrolled(position, offset, offsetPixels);
Log.d("SWANK", "page scrolled: " + offsetPixels);
}
public final SwankyImageView getCurrentView() {
return (SwankyImageView) findViewWithTag(getCurrentItem());
}
}
public static interface OnGalleryPageSelectedListener {
public void onPageSelected(int index);
}
}