Skip to content

Instantly share code, notes, and snippets.

@tony1223
Created June 7, 2013 21:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tony1223/5732622 to your computer and use it in GitHub Desktop.
Save tony1223/5732622 to your computer and use it in GitHub Desktop.
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ViewTreeObserver;
import android.widget.ImageView;
public class SmartImageView extends ImageView implements android.view.GestureDetector.OnGestureListener,
android.view.GestureDetector.OnDoubleTapListener {
private android.widget.ImageView imageView = this;
private int screenHeight;
private float screenScale;
private float minScale;
private int screenWidth;
private GestureDetector detector;
private PointF imageLocation;
private PointF moveStartPoint;
private TouchMode touchMode;
private float diff1;
private float diff2;
private SizePreDrawListenter sizelistenter;
public SmartImageView(Context context) {
super(context);
init();
}
public SmartImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public SmartImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
moveStartPoint = new PointF();
imageLocation = new PointF();
// isNextPageRaady = true;
// isPreviousPageRaady = true;
touchMode = TouchMode.NON_MODE;
sizelistenter = new SizePreDrawListenter();
}
public void setScreenSize(int i, int j) {
screenWidth = i;
screenHeight = j;
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
detector = new GestureDetector(getContext(), this);
ViewTreeObserver vto = getViewTreeObserver();
vto.removeOnPreDrawListener(sizelistenter);
vto.addOnPreDrawListener(sizelistenter);
}
@Override
public void setImageDrawable(Drawable drawable) {
super.setImageDrawable(drawable);
updateScreenResolutionScale();
}
private void scaleByScreenHeight() {
int imageHeight = getDrawableHeight();
int imageWidth = getDrawableWidth();
minScale = (float) screenWidth / (float) imageWidth;
screenScale = (float) screenHeight / (float) imageHeight;
setScale(screenScale, screenScale, 0.0F, 0.0F);
}
private void scaleByScreenWidth() {
int imageWidth = getDrawableWidth();
int imageHeight = getDrawableHeight();
screenScale = (float) screenWidth / (float) imageWidth;
if (screenScale == 1.0F) {
screenScale = 0.001F + screenScale;
}
minScale = (float) screenHeight / (float) imageHeight;
setScale(screenScale, screenScale, 0.0F, 0.0F);
}
public void checkScreenBoundary() {
Matrix matrix = imageView.getImageMatrix();
float matrixValues[] = new float[9];
matrix.getValues(matrixValues);
float transX = matrixValues[Matrix.MTRANS_X];
float transY = matrixValues[Matrix.MTRANS_Y];
if (transX > 0.0F) { // clear trans_x
matrixValues[Matrix.MTRANS_X] = 0.0F;
matrix.setValues(matrixValues);
imageView.setImageMatrix(matrix);
imageView.invalidate();
}
float imageWidth = getDrawableWidth();
float ViewWidthDiff = (float) screenWidth - imageWidth;
if (transX < ViewWidthDiff) {
matrixValues[Matrix.MTRANS_X] = ViewWidthDiff;
matrix.setValues(matrixValues);
imageView.setImageMatrix(matrix);
imageView.invalidate();
}
if (transY > 0.0F) {
matrixValues[Matrix.MTRANS_Y] = 0.0F;
matrix.setValues(matrixValues);
imageView.setImageMatrix(matrix);
imageView.invalidate();
}
int totalHeight = imageView.getHeight();
int heightDiff = screenHeight - totalHeight;
int otherSpace = screenHeight - heightDiff;
float imageHeight = getDrawableHeight();
float new_trans_y;
if (imageHeight > (float) otherSpace) {
new_trans_y = (float) otherSpace - imageHeight;
} else {
new_trans_y = 0.0F;
}
if (transY < new_trans_y) {
matrixValues[Matrix.MTRANS_Y] = new_trans_y;
matrix.setValues(matrixValues);
imageView.setImageMatrix(matrix);
imageView.invalidate();
}
}
public boolean checkScreenLeftBoundary() {
android.graphics.Matrix matrix = imageView.getImageMatrix();
float af[] = new float[9];
matrix.getValues(af);
return af[2] < 0.0F;
}
public boolean checkScreenRightBoundary() {
android.graphics.Matrix matrix = imageView.getImageMatrix();
float af[] = new float[9];
matrix.getValues(af);
float f = af[2];
float f1 = getDrawableWidth();
float f2 = java.lang.Math.abs(f1 - (float) screenWidth);
if (f1 > (float) screenWidth)
f2 = -f2;
return f > f2;
}
public int getDrawableHeight() {
android.graphics.Matrix matrix = imageView.getImageMatrix();
float af[] = new float[9];
matrix.getValues(af);
float f = af[4];
if (imageView.getDrawable() == null)
return 0;
else
return (int) (f * (float) imageView.getDrawable().getIntrinsicHeight());
}
public int getDrawableWidth() {
android.graphics.Matrix matrix = imageView.getImageMatrix();
float af[] = new float[9];
matrix.getValues(af);
float f = af[0];
if (imageView.getDrawable() == null)
return 0;
else
return (int) (f * (float) imageView.getDrawable().getIntrinsicWidth());
}
public android.graphics.PointF getLocation() {
android.graphics.Matrix matrix = imageView.getImageMatrix();
float af[] = new float[9];
matrix.getValues(af);
return new PointF(af[2], af[5]);
}
public boolean isZoomIn() {
android.graphics.Matrix matrix = imageView.getImageMatrix();
float af[] = new float[9];
matrix.getValues(af);
boolean i = af[0] != screenScale;
boolean flag = false;
if (i)
flag = true;
return flag;
}
public boolean isZoomInLimit(float f) {
android.graphics.Matrix matrix = imageView.getImageMatrix();
float af[] = new float[9];
matrix.getValues(af);
return (double) (f * af[0]) >= 2.5D;
}
public boolean isZoomOutLimit(float f) {
android.graphics.Matrix matrix = imageView.getImageMatrix();
float af[] = new float[9];
matrix.getValues(af);
return (f * af[0]) <= minScale;
}
public void move(float f, float f1) {
android.graphics.Matrix matrix = imageView.getImageMatrix();
matrix.postTranslate(f, f1);
imageView.setImageMatrix(matrix);
imageView.invalidate();
}
public void moveToLeft() {
android.graphics.Matrix matrix = imageView.getImageMatrix();
float af[] = new float[9];
matrix.getValues(af);
af[2] = 0.0F;
matrix.setValues(af);
imageView.setImageMatrix(matrix);
imageView.invalidate();
}
public void moveToLeftLimit() {
android.graphics.Matrix matrix = imageView.getImageMatrix();
float af[] = new float[9];
matrix.getValues(af);
float f = getDrawableWidth();
float f1 = java.lang.Math.abs(f - (float) screenWidth);
if (f > (float) screenWidth)
f1 = -f1;
af[2] = f1;
matrix.setValues(af);
imageView.setImageMatrix(matrix);
imageView.invalidate();
}
public void moveToRight() {
android.graphics.Matrix matrix = imageView.getImageMatrix();
float af[] = new float[9];
matrix.getValues(af);
float f = getDrawableWidth();
float f1 = java.lang.Math.abs(f - (float) screenWidth);
if (f > (float) screenWidth)
f1 = -f1;
af[2] = f1;
matrix.setValues(af);
imageView.setImageMatrix(matrix);
imageView.invalidate();
}
public void resetScreenResolution(int i, int j) {
screenWidth = i;
screenHeight = j;
}
public void setOriginScale() {
android.graphics.Matrix matrix = imageView.getImageMatrix();
float af[] = new float[9];
matrix.getValues(af);
float f = af[0];
float f1 = af[4];
setScale(1.5F / f, 1.5F / f1, screenWidth / 2, screenHeight / 2);
}
public void setScale(float f, float f1, float f2, float f3) {
android.graphics.Matrix matrix = imageView.getImageMatrix();
matrix.postScale(f, f1, f2, f3);
imageView.setImageMatrix(matrix);
imageView.invalidate();
}
public void updateScreenResolutionScale() {
android.graphics.Matrix matrix = imageView.getImageMatrix();
matrix.reset();
imageView.setImageMatrix(matrix);
if (imageView.getDrawable() == null) {
return;
}
if (screenWidth <= screenHeight) {
scaleByScreenHeight();
} else {
scaleByScreenWidth();
}
}
public void zoomIn(float f) {
setScale(f, f, screenWidth / 2, screenHeight / 2);
}
public void zoomOut(float f) {
setScale(f, f, screenWidth / 2, screenHeight / 2);
}
public boolean onDoubleTap(android.view.MotionEvent motionevent) {
if (isZoomIn()) {
updateScreenResolutionScale();
} else {
setOriginScale();
}
return false;
}
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
return false;
}
@Override
public boolean onDoubleTapEvent(MotionEvent e) {
return false;
}
@Override
public boolean onDown(MotionEvent e) {
return false;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return false;
}
@Override
public void onLongPress(MotionEvent e) {
}
public boolean onTouchEvent(android.view.MotionEvent motionevent) {
int i;
int j;
try {
i = motionevent.getPointerCount();
} catch (java.lang.Exception exception) {
return false;
}
if (i != 2) {
if (i != 1) {
return detector.onTouchEvent(motionevent);
} else {
switch (motionevent.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
touchMode = TouchMode.MOVE_MODE;
moveStartPoint.set(motionevent.getX(), motionevent.getY());
break;
case MotionEvent.ACTION_UP:
imageLocation = getLocation();
checkScreenBoundary();
touchMode = TouchMode.NON_MODE;
break;
case MotionEvent.ACTION_MOVE:
if (!touchMode.equals(TouchMode.MOVE_MODE)) {
} else {
float f1 = motionevent.getX();
float f2 = motionevent.getY();
move(f1 - moveStartPoint.x, f2 - moveStartPoint.y);
moveStartPoint.set(motionevent.getX(), motionevent.getY());
}
break;
}
detector.onTouchEvent(motionevent);
return true;
}
} else {
switch (motionevent.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_MOVE:
if (!touchMode.equals(TouchMode.SCALE_MODE)) {
} else {
diff2 = spacing(motionevent);
android.graphics.PointF pointf = getMidPoint(motionevent);
float f = diff2 / diff1;
if (!isZoomInLimit(f) && !isZoomOutLimit(f)) {
setScale(f, f, pointf.x, pointf.y);
}
diff1 = spacing(motionevent);
}
break;
case MotionEvent.ACTION_POINTER_DOWN:
diff1 = spacing(motionevent);
touchMode = TouchMode.SCALE_MODE;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_OUTSIDE:
default:
}
}
detector.onTouchEvent(motionevent);
return true;
}
private static PointF getMidPoint(android.view.MotionEvent motionevent) {
android.graphics.PointF pointf = new PointF();
float f = motionevent.getX(0) + motionevent.getX(1);
float f1 = motionevent.getY(0) + motionevent.getY(1);
pointf.set(f / 2.0F, f1 / 2.0F);
return pointf;
}
private static float spacing(android.view.MotionEvent motionevent) {
float f = motionevent.getX(0) - motionevent.getX(1);
float f1 = motionevent.getY(0) - motionevent.getY(1);
return android.util.FloatMath.sqrt(f * f + f1 * f1);
}
@Override
public boolean onFling(MotionEvent motionevent, MotionEvent motionevent1, float f, float f1) {
int step = screenWidth / 10;
int rightBound = ((screenWidth - getDrawableWidth()) + 2 * step);
int leftBound = 2 * step;
int TYPE_LEFT_TO_RIGHT = 0;
int TYPE_RIGHT_TO_LEFT = 1;
int TYPE = TYPE_LEFT_TO_RIGHT;
imageLocation = this.getLocation();
if ((motionevent.getX() - motionevent1.getX() > (float) step) && imageLocation.x < (float) (-rightBound)) {
if (TYPE == TYPE_LEFT_TO_RIGHT) {
flingNext();
return true;
} else {
flingPrevious();
return true;
}
}
if ((motionevent.getX() - motionevent1.getX() < (float) (-step)) && imageLocation.x > (float) leftBound) {
if (TYPE == TYPE_LEFT_TO_RIGHT) {
flingPrevious();
return true;
} else {
flingNext();
return true;
}
} else {
return false;
}
}
protected void flingPrevious() {
// Toast.makeText(getContext(), "fliing to previous",
// Toast.LENGTH_SHORT).show();
}
protected void flingNext() {
// Toast.makeText(getContext(), "fliing to next",
// Toast.LENGTH_SHORT).show();
}
private final class SizePreDrawListenter implements ViewTreeObserver.OnPreDrawListener {
public boolean onPreDraw() {
int finalHeight = getMeasuredHeight();
int finalWidth = getMeasuredWidth();
if (finalHeight != 0 && finalWidth != 0) {
screenWidth = finalWidth;
screenHeight = finalHeight;
}
return true;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment