From 76fc2c28792817a7cd204caf486f3c0d5f9b779a Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Sat, 13 Oct 2012 23:59:03 +0400 Subject: archive: allow zip files comic: enable pinch to zoom & scrolling --- src/org/fox/ttcomics/ComicFragment.java | 14 +- src/org/fox/ttcomics/ComicListFragment.java | 2 +- src/org/fox/ttcomics/ComicPager.java | 1 - src/org/fox/ttcomics/TouchImageView.java | 259 ++++++++++++++++++++++++++++ src/org/fox/ttcomics/ViewPager.java | 37 ++++ 5 files changed, 309 insertions(+), 4 deletions(-) create mode 100644 src/org/fox/ttcomics/TouchImageView.java create mode 100644 src/org/fox/ttcomics/ViewPager.java (limited to 'src/org') diff --git a/src/org/fox/ttcomics/ComicFragment.java b/src/org/fox/ttcomics/ComicFragment.java index e1a753b..1fa585e 100644 --- a/src/org/fox/ttcomics/ComicFragment.java +++ b/src/org/fox/ttcomics/ComicFragment.java @@ -9,6 +9,7 @@ import android.graphics.BitmapFactory; import android.os.Bundle; import android.preference.PreferenceManager; import android.support.v4.app.Fragment; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -34,7 +35,7 @@ public class ComicFragment extends Fragment { View view = inflater.inflate(R.layout.fragment_comic, container, false); - ImageView image = (ImageView) view.findViewById(R.id.comic_image); + TouchImageView image = (TouchImageView) view.findViewById(R.id.comic_image); if (savedInstanceState != null) { m_comic = savedInstanceState.getParcelable("comic"); @@ -42,8 +43,17 @@ public class ComicFragment extends Fragment { if (m_comic != null) { image.setImageBitmap(m_comic); + image.setMaxZoom(4f); + image.setOnScaleChangedListener(new TouchImageView.OnScaleChangedListener() { + + public void onScaleChanged(float scale) { + ViewPager pager = (ViewPager) getActivity().findViewById(R.id.comics_pager); + + pager.setPagingEnabled(scale - 1.0f < 0.01); + } + }); } - + return view; } diff --git a/src/org/fox/ttcomics/ComicListFragment.java b/src/org/fox/ttcomics/ComicListFragment.java index 5a28714..3330ba8 100644 --- a/src/org/fox/ttcomics/ComicListFragment.java +++ b/src/org/fox/ttcomics/ComicListFragment.java @@ -235,7 +235,7 @@ public class ComicListFragment extends Fragment implements OnItemClickListener { for (File archive : archives) { String fileName = archive.getName(); - if (fileName.indexOf(".cbz") != -1 && isAdded() && m_activity != null) { + if (fileName.toLowerCase().matches(".*\\.(cbz|zip)") && isAdded() && m_activity != null) { try { CbzComicArchive cba = new CbzComicArchive(comicsDir + "/" + fileName); diff --git a/src/org/fox/ttcomics/ComicPager.java b/src/org/fox/ttcomics/ComicPager.java index 89287b6..cd49c83 100644 --- a/src/org/fox/ttcomics/ComicPager.java +++ b/src/org/fox/ttcomics/ComicPager.java @@ -11,7 +11,6 @@ import android.preference.PreferenceManager; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentStatePagerAdapter; -import android.support.v4.view.ViewPager; import android.util.Log; import android.view.LayoutInflater; import android.view.View; diff --git a/src/org/fox/ttcomics/TouchImageView.java b/src/org/fox/ttcomics/TouchImageView.java new file mode 100644 index 0000000..5390216 --- /dev/null +++ b/src/org/fox/ttcomics/TouchImageView.java @@ -0,0 +1,259 @@ +/* + * TouchImageView.java + * By: Michael Ortiz + * Updated By: Patrick Lackemacher + * ------------------- + * Extends Android ImageView to include pinch zooming and panning. + */ + +package org.fox.ttcomics; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Matrix; +import android.graphics.PointF; +import android.util.AttributeSet; +import android.util.Log; +import android.view.MotionEvent; +import android.view.ScaleGestureDetector; +import android.view.View; +import android.widget.ImageView; + +public class TouchImageView extends ImageView { + + public interface OnScaleChangedListener { + public void onScaleChanged(float scale); + } + + OnScaleChangedListener mScaleChangedListener; + + Matrix matrix = new Matrix(); + + // We can be in one of these 3 states + static final int NONE = 0; + static final int DRAG = 1; + static final int ZOOM = 2; + int mode = NONE; + + // Remember some things for zooming + PointF last = new PointF(); + PointF start = new PointF(); + float minScale = 1f; + float maxScale = 3f; + float[] m; + + float redundantXSpace, redundantYSpace; + + float width, height; + static final int CLICK = 3; + float saveScale = 1f; + float right, bottom, origWidth, origHeight, bmWidth, bmHeight; + + ScaleGestureDetector mScaleDetector; + + Context context; + + public TouchImageView(Context context) { + super(context); + sharedConstructing(context); + } + + public TouchImageView(Context context, AttributeSet attrs) { + super(context, attrs); + sharedConstructing(context); + } + + private void sharedConstructing(Context context) { + super.setClickable(true); + this.context = context; + mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); + matrix.setTranslate(1f, 1f); + m = new float[9]; + setImageMatrix(matrix); + setScaleType(ScaleType.MATRIX); + + setOnTouchListener(new OnTouchListener() { + + public boolean onTouch(View v, MotionEvent event) { + mScaleDetector.onTouchEvent(event); + + matrix.getValues(m); + float x = m[Matrix.MTRANS_X]; + float y = m[Matrix.MTRANS_Y]; + PointF curr = new PointF(event.getX(), event.getY()); + + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + last.set(event.getX(), event.getY()); + start.set(last); + mode = DRAG; + break; + case MotionEvent.ACTION_MOVE: + if (mode == DRAG) { + float deltaX = curr.x - last.x; + float deltaY = curr.y - last.y; + float scaleWidth = Math.round(origWidth * saveScale); + float scaleHeight = Math.round(origHeight * saveScale); + if (scaleWidth < width) { + deltaX = 0; + if (y + deltaY > 0) + deltaY = -y; + else if (y + deltaY < -bottom) + deltaY = -(y + bottom); + } else if (scaleHeight < height) { + deltaY = 0; + if (x + deltaX > 0) + deltaX = -x; + else if (x + deltaX < -right) + deltaX = -(x + right); + } else { + if (x + deltaX > 0) + deltaX = -x; + else if (x + deltaX < -right) + deltaX = -(x + right); + + if (y + deltaY > 0) + deltaY = -y; + else if (y + deltaY < -bottom) + deltaY = -(y + bottom); + } + matrix.postTranslate(deltaX, deltaY); + last.set(curr.x, curr.y); + } + break; + + case MotionEvent.ACTION_UP: + mode = NONE; + int xDiff = (int) Math.abs(curr.x - start.x); + int yDiff = (int) Math.abs(curr.y - start.y); + if (xDiff < CLICK && yDiff < CLICK) + performClick(); + break; + + case MotionEvent.ACTION_POINTER_UP: + mode = NONE; + break; + } + setImageMatrix(matrix); + invalidate(); + return true; // indicate event was handled + } + + }); + } + + @Override + public void setImageBitmap(Bitmap bm) { + super.setImageBitmap(bm); + if(bm != null) { + bmWidth = bm.getWidth(); + bmHeight = bm.getHeight(); + } + } + + public void setMaxZoom(float x) + { + maxScale = x; + } + + private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { + @Override + public boolean onScaleBegin(ScaleGestureDetector detector) { + mode = ZOOM; + return true; + } + + @Override + public boolean onScale(ScaleGestureDetector detector) { + float mScaleFactor = detector.getScaleFactor(); + float origScale = saveScale; + saveScale *= mScaleFactor; + if (saveScale > maxScale) { + saveScale = maxScale; + mScaleFactor = maxScale / origScale; + } else if (saveScale < minScale) { + saveScale = minScale; + mScaleFactor = minScale / origScale; + } + right = width * saveScale - width - (2 * redundantXSpace * saveScale); + bottom = height * saveScale - height - (2 * redundantYSpace * saveScale); + if (origWidth * saveScale <= width || origHeight * saveScale <= height) { + matrix.postScale(mScaleFactor, mScaleFactor, width / 2, height / 2); + if (mScaleFactor < 1) { + matrix.getValues(m); + float x = m[Matrix.MTRANS_X]; + float y = m[Matrix.MTRANS_Y]; + if (mScaleFactor < 1) { + if (Math.round(origWidth * saveScale) < width) { + if (y < -bottom) + matrix.postTranslate(0, -(y + bottom)); + else if (y > 0) + matrix.postTranslate(0, -y); + } else { + if (x < -right) + matrix.postTranslate(-(x + right), 0); + else if (x > 0) + matrix.postTranslate(-x, 0); + } + } + } + } else { + matrix.postScale(mScaleFactor, mScaleFactor, detector.getFocusX(), detector.getFocusY()); + matrix.getValues(m); + float x = m[Matrix.MTRANS_X]; + float y = m[Matrix.MTRANS_Y]; + if (mScaleFactor < 1) { + if (x < -right) + matrix.postTranslate(-(x + right), 0); + else if (x > 0) + matrix.postTranslate(-x, 0); + if (y < -bottom) + matrix.postTranslate(0, -(y + bottom)); + else if (y > 0) + matrix.postTranslate(0, -y); + } + } + + if (mScaleChangedListener != null) { + mScaleChangedListener.onScaleChanged(saveScale); + } + + return true; + + } + } + + @Override + protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) + { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + width = MeasureSpec.getSize(widthMeasureSpec); + height = MeasureSpec.getSize(heightMeasureSpec); + //Fit to screen. + float scale; + float scaleX = (float)width / (float)bmWidth; + float scaleY = (float)height / (float)bmHeight; + scale = Math.min(scaleX, scaleY); + matrix.setScale(scale, scale); + setImageMatrix(matrix); + saveScale = 1f; + + // Center the image + redundantYSpace = (float)height - (scale * (float)bmHeight) ; + redundantXSpace = (float)width - (scale * (float)bmWidth); + redundantYSpace /= (float)2; + redundantXSpace /= (float)2; + + matrix.postTranslate(redundantXSpace, redundantYSpace); + + origWidth = width - 2 * redundantXSpace; + origHeight = height - 2 * redundantYSpace; + right = width * saveScale - width - (2 * redundantXSpace * saveScale); + bottom = height * saveScale - height - (2 * redundantYSpace * saveScale); + setImageMatrix(matrix); + } + + public void setOnScaleChangedListener(OnScaleChangedListener listener) { + mScaleChangedListener = listener; + } +} diff --git a/src/org/fox/ttcomics/ViewPager.java b/src/org/fox/ttcomics/ViewPager.java new file mode 100644 index 0000000..3915eaf --- /dev/null +++ b/src/org/fox/ttcomics/ViewPager.java @@ -0,0 +1,37 @@ +package org.fox.ttcomics; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; + +public class ViewPager extends android.support.v4.view.ViewPager { + + private boolean enabled; + + public ViewPager(Context context, AttributeSet attrs) { + super(context, attrs); + this.enabled = true; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (this.enabled) { + return super.onTouchEvent(event); + } + + return false; + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent event) { + if (this.enabled) { + return super.onInterceptTouchEvent(event); + } + + return false; + } + + public void setPagingEnabled(boolean enabled) { + this.enabled = enabled; + } +} \ No newline at end of file -- cgit v1.2.3