Created
June 7, 2013 21:41
-
-
Save tony1223/5732622 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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