I am developing an android app after image view is rotated
image view not fitting the entire screen how can I fit the entire
screen so that ImageView covers the entire screen
`
below my MainActivity.java where I have implemented image rotation logic in my java class
below my MainActivity.java where I have implemented image rotation logic in my java class
public class MainActivity extends AppCompatActivity {
float scaleDiff;
private static final int NONE = 0;
private static final int DRAG = 1;
private static final int ZOOM = 2;
private int mode = NONE;
private float oldDist = 1f;
private float d = 0f;
private float newRot = 0f;
#BindView(R.id.show_image)
ImageView mImageView;
private boolean mMoved = false;
private PhotoViewAttacher mViewAttacher;
private float mScaleX = 0, mScaleY = 0;
#SuppressLint("ClickableViewAccessibility")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
mScaleX = mImageView.getScaleX();
mScaleY = mImageView.getScaleY();
final RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(getScreenWidth(), getScreenHeight());
mImageView.setLayoutParams(layoutParams);
mImageView.setOnTouchListener(new View.OnTouchListener() {
RelativeLayout.LayoutParams params;
int startWidth;
int startHeight;
float dx = 0, dy = 0, x = 0, y = 0;
float angle = 0;
#Override
public boolean onTouch(View v, MotionEvent event) {
final ImageView view = (ImageView) v;
((BitmapDrawable) view.getDrawable()).setAntiAlias(true);
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
params = (RelativeLayout.LayoutParams) view.getLayoutParams();
startWidth = params.width;
startHeight = params.height;
dx = event.getRawX() - params.leftMargin;
dy = event.getRawY() - params.topMargin;
mode = DRAG;
break;
case MotionEvent.ACTION_POINTER_DOWN:
oldDist = spacing(event);
if (oldDist > 10f) {
mode = ZOOM;
}
d = rotation(event);
break;
case MotionEvent.ACTION_UP:
if (view.getScaleX() <= mScaleX || view.getScaleY() <= mScaleY) {
view.setScaleX(mScaleX);
view.setScaleY(mScaleY);
params.leftMargin = 0;
params.topMargin = 0;
params.rightMargin = 0;
params.bottomMargin = 0;
}
if (mMoved || view.getWidth() != getScreenWidth() || view.getHeight() != getScreenHeight()) {
params.leftMargin = 0;
params.topMargin = 0;
params.rightMargin = 0;
params.bottomMargin = 0;
mMoved = false;
}
view.setScaleType(ImageView.ScaleType.CENTER_CROP);
view.setLayoutParams(params);
break;
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
mMoved = true;
x = event.getRawX();
y = event.getRawY();
params.leftMargin = (int) (x - dx);
params.topMargin = (int) (y - dy);
params.rightMargin = 0;
params.bottomMargin = 0;
params.rightMargin = params.leftMargin + (5 * params.width);
params.bottomMargin = params.topMargin + (10 * params.height);
view.setLayoutParams(params);
}
else if (mode == ZOOM) {
if (event.getPointerCount() == 2) {
newRot = rotation(event);
float r = newRot - d;
angle = r;
x = event.getRawX();
y = event.getRawY();
float newDist = spacing(event);
if (newDist > 10f) {
float scale = newDist / oldDist * view.getScaleX();
if (scale > 0.6) {
scaleDiff = scale;
view.setScaleX(scale);
view.setScaleY(scale);
}
}
view.animate().rotationBy(angle).setDuration(0).setInterpolator(new LinearInterpolator()).start();
x = event.getRawX();
y = event.getRawY();
params.leftMargin = (int) ((x - dx) + scaleDiff);
params.topMargin = (int) ((y - dy) + scaleDiff);
params.rightMargin = 0;
params.bottomMargin = 0;
params.rightMargin = params.leftMargin + (5 * params.width);
params.bottomMargin = params.topMargin + (10 * params.height);
view.setLayoutParams(params);
}
}
break;
}
return true;
}
});
}
private float spacing(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return (float) Math.sqrt(x * x + y * y);
}
private float rotation(MotionEvent event) {
double delta_x = (event.getX(0) - event.getX(1));
double delta_y = (event.getY(0) - event.getY(1));
double radians = Math.atan2(delta_y, delta_x);
return (float) Math.toDegrees(radians);
}
public static int getScreenWidth() {
return Resources.getSystem().getDisplayMetrics().widthPixels;
}
public static int getScreenHeight() {
return Resources.getSystem().getDisplayMetrics().heightPixels;
}
}
below activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone" />
<ImageView
android:id="#+id/show_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:scaleType="centerCrop"
android:adjustViewBounds="true"
android:src="#drawable/abstract_image"
android:transitionName="image_transition" />
</RelativeLayout>
Use this in imageView
<ImageView
android:id="#+id/show_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:scaleType="fitXY"
android:adjustViewBounds="true"
android:src="#drawable/abstract_image"
android:transitionName="image_transition" />
java file
imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Bitmap myImg = BitmapFactory.decodeResource(getResources(),
R.drawable.abstract_image);
Matrix matrix = new Matrix();
matrix.postRotate(90);
Bitmap rotated = Bitmap.createBitmap(myImg, 0, 0,
myImg.getWidth(), myImg.getHeight(),
matrix, true);
imageView.setImageBitmap(rotated);
}
});
using this code image is rotate properly now you can adjust in your code according to your need
Related
I'm trying to make a view invisible when it's dragged to a certain Y coordinate on the screen.
This is what I got now:
private final class dragTouchListener implements View.OnTouchListener {
#Override
public boolean onTouch(View v, MotionEvent event) {
final int X = (int) event.getRawX();
final int Y = (int) event.getRawY();
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
ContentFrameLayout.LayoutParams lParams = (ContentFrameLayout.LayoutParams) v.getLayoutParams();
_xDelta = X - lParams.leftMargin;
_yDelta = Y - lParams.topMargin;
break;
case MotionEvent.ACTION_UP:
trash_image.setVisibility(View.INVISIBLE);
break;
case MotionEvent.ACTION_POINTER_DOWN:
break;
case MotionEvent.ACTION_POINTER_UP:
break;
case MotionEvent.ACTION_MOVE:
trash_image.setVisibility(View.VISIBLE);
ContentFrameLayout.LayoutParams layoutParams = (ContentFrameLayout.LayoutParams) v.getLayoutParams();
layoutParams.leftMargin = X - _xDelta;
layoutParams.topMargin = Y - _yDelta;
layoutParams.rightMargin = -250;
layoutParams.bottomMargin = -250;
v.setLayoutParams(layoutParams);
if(v.getY() > trash_image.getY()){
v.setVisibility(View.INVISIBLE);
}
break;
}
contentView.invalidate();
return true;
}
}
So basically what I've tried here is simply an if statement to check if the Y position of the view has "passed" that of another ImageView placed on the upper part of the screen. This however result in becoming invisible as soon as I touch the view to be dragged, no matter where on the screen it's located. So it's far from accurate, or wrong all together.
As requested in comment, a suggestion (do note I had to change it, since this is for a client program, so I didnt test it again):
First, discover SCREEN_DENSITY
private static float SCREEN_DENSITY = getResources().getDisplayMetrics().density;
The onTouch function:
public boolean onTouch(final View v, MotionEvent event) {
case MotionEvent.ACTION_DOWN:
mainFinger = new Point(
(int) (event.getRawX() / SCREEN_DENSITY),
(int) (event.getRawY() / SCREEN_DENSITY)
);
break;
case MotionEvent.ACTION_MOVE:
movFrame(
(FrameLayout) v,
(int) (event.getRawX() / SCREEN_DENSITY),
(int) (event.getRawY() / SCREEN_DENSITY)
);
}
movFrame function:
private void movFrame(FrameLayout v, int movX, int movY) {
MyObject p = (MyObject ) v.getTag();
int[] x, y, h, w;
x = p.x;
y = p.y;
h = p.h;
w = p.w;
x = p.x + movX - mainFinger.x;
mainFinger.x = movX;
if (x + w > p.parent.w) {
x = p.parent.w - w;
}
if (x < 0) {
x = 0;
}
y = p.y + movY - mainFinger.y;
mainFinger.y = movY;
if (y + h > p.parent.h) {
y = p.parent.h - h;
}
if (y < 0) {
y = 0;
}
p.updateMyObject(x, y, h, w);
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
(int) ((p.w * SCREEN_DENSITY) + 0.5),
(int) ((p.h * SCREEN_DENSITY) + 0.5)
);
params.leftMargin = (int) ((p.x * SCREEN_DENSITY) + 0.5);
params.topMargin = (int) ((p.y * SCREEN_DENSITY) + 0.5);
v.setLayoutParams(params);
}
can anyone please help me, how to implement pinch zoom, rotate and drag on dynamic edittext android. i have tried many things but not getting proper output. Please tell m easy way to implement this.
this is my activity.
public class MainActivity extends Activity implements OnRotationGestureListener {
RelativeLayout container;
TextView curEt;
private float oldDist = 1f;
int count = 0;
private PointF mid = new PointF();
private static final int NONE = 0;
private static final int DRAG = 1;
private static final int ZOOM = 2;
private float[] lastEvent = null;
private int mode = NONE;
public int firstClick;
public int secClick;
public int offset_x;
public int offset_y;
private PointF start = new PointF();
private float degrees, prevDegrees;
private RotationGestureDetector mRotationDetector;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_editable_area);
container = (RelativeLayout) findViewById(R.id.container);
mRotationDetector = new RotationGestureDetector(this);
curEt = new EditText(this);
container.setOnTouchListener(new MyTouch());
}
class MyTouch implements OnTouchListener {
private static final float MAX_FONT_SIZE = 100;
private static final float MIN_FONT_SIZE = 10;
#Override
public boolean onTouch(View v, MotionEvent event) {
mRotationDetector.onTouchEvent(event);
System.out.println();
if (container == v) {
if (MotionEvent.ACTION_DOWN == event.getAction()) {
createET(event);
}
} else {
curEt = (EditText) v;
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
start.set(event.getX(), event.getY());
offset_x = (int) event.getX();
offset_y = (int) event.getY();
mode = DRAG;
break;
case MotionEvent.ACTION_POINTER_DOWN:
oldDist = spacing(event);
midPoint(mid, event);
mode = ZOOM;
lastEvent = new float[4];
lastEvent[0] = event.getX(0);
lastEvent[1] = event.getX(1);
lastEvent[2] = event.getY(0);
lastEvent[3] = event.getY(1);
// d = rotation(event);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
prevDegrees = degrees;
mode = NONE;
// lastEvent = null;
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
// curEt.setX(event.getRawX() - 40);
// curEt.setY(event.getRawY() - 150);
} else if (mode == ZOOM) {
float newDist = spacing(event);
if (newDist > 10f) {
float scale = newDist / oldDist;
if (scale > 1) {
scale = 1.1f;
} else if (scale < 1) {
scale = 0.95f;
}
float currentSize = curEt.getTextSize() * scale;
if ((currentSize < MAX_FONT_SIZE && currentSize > MIN_FONT_SIZE)
|| (currentSize >= MAX_FONT_SIZE && scale < 1)
|| (currentSize <= MIN_FONT_SIZE && scale > 1)) {
curEt.setTextSize(TypedValue.COMPLEX_UNIT_PX,
currentSize);
}
}
if (lastEvent != null) {
// float newRot = rotation(event);
// float r = newRot - d;
if (degrees < 180 && degrees > -180) {
curEt.animate().rotationBy(-degrees);
curEt.setRotation(-degrees);
}
// RotateAnimation an = new RotateAnimation(0.0f,
// degrees, 0, 0);
// RotateAnimation anim = new RotateAnimation(0,
// degrees,
// Animation.RELATIVE_TO_SELF, 0f,
// Animation.RELATIVE_TO_SELF,0f);
// //degrees = (degrees + 30) % 360;
}
}
break;
}
}
return false;
}
}
private void createET(MotionEvent event) {
EditText et = new EditText(MainActivity.this);
curEt = et;
curEt.setHint("EditText");
curEt.setTag(et.getId());
curEt.setX(event.getX());
curEt.setFocusable(false);
curEt.setY(event.getY());
curEt.setSingleLine(true);
curEt.setOnTouchListener(new MyTouch());
container.addView(et);
}
/* Determine the space between the first two fingers */
private float spacing(MotionEvent event) {
return (float) (Math.pow((event.getX(1) - event.getX(0)), 2) + Math
.pow((event.getY(1) - event.getY(0)), 2));
}
/* Calculate the mid point of the first two fingers */
private void midPoint(PointF point, MotionEvent event) {
float x = event.getX(0) + event.getX(1);
float y = event.getY(0) + event.getY(1);
point.set(x / 2, y / 2);
}
#Override
public void OnRotation(RotationGestureDetector rotationDetector) {
degrees = rotationDetector.getAngle();
System.out.println(degrees);
}
/* Calculate the degree to be rotated by. */
// private float rotation(MotionEvent event) {
// float x = event.getX(0) - event.getX(1);
// float y = event.getY(0) - event.getY(1);
// DisplayMetrics displaymetrics = new DisplayMetrics();
// getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
// int height = displaymetrics.heightPixels;
// int width = displaymetrics.widthPixels;
// double delta_x = x - (width) /2;
// double delta_y = (height) /2 - y;
// double radians = Math.atan2(delta_y, delta_x);
// return (float) Math.toDegrees(radians);
// }
}
and XML Layout
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
please help me with this. if i try to rotate it gets flickering effect.
I am developing an app which has feature that resizing and rotating the imageview by dragging its bottom right corner button.
I saw one app which has feature that if we drag the bottom right corner button diagonally imageview size had resized or else if we drag the button left or right side direction imageview had rotated as per direction. I wish to implement this feature in my app
I am struggling to implement single finger rotation as well as resizing the imageview.
Please guide me in right way.
I am trying this code, and try to apply zoom and rotate but not able to do please help me.
belove code to do zoom and rotate finger base action.
public class ScaleActivity extends Activity {
ViewGroup lLayout;
static ImageView img, backgrndImg;
Canvas mCanvas;
float d;
private float mAspectQuotient;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lLayout = (FrameLayout) findViewById(R.id.lLayout);
final CropView cv = new CropView(this);
lLayout.addView(cv);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public class CropView extends ImageView {
private static final int SELECTION_RECT_PAINT_COLOR = 0xFF000000;
private static final int SELECTION_RECT_FILL_COLOR = 0x70FFFFFF;
private static final int TOUCH_TOLERANCE = 25;
private static final int xInc = 25;
private static final int yInc = 25;
Paint paint = new Paint();
private int initial_size = 200;
private Point leftTop, rightBottom, center, previous, currentPoint,
rectPos;
private Paint fillPaint;
private Paint rectPaint;
protected Rect selection, dest;
private boolean isAffectedBottom = false;
Bitmap bitmap, backgroundBitmap;
Rect rectf;
Rect knobRect;
private Context mContext;
int width, height;
private Matrix matrix = new Matrix();
Bitmap resizedBitmap;
// Adding parent class constructors
public CropView(Context context) {
super(context);
mContext = context;
backgroundBitmap = BitmapFactory.decodeResource(getContext()
.getResources(), R.drawable.toast_bkgrd);
bitmap = BitmapFactory.decodeResource(getContext().getResources(),
R.drawable.aviary_adjust_knob);
rectPaint = new Paint();
rectPaint.setStyle(Style.STROKE);
rectPaint.setColor(SELECTION_RECT_PAINT_COLOR);
fillPaint = new Paint();
fillPaint.setStyle(Style.FILL);
fillPaint.setColor(SELECTION_RECT_FILL_COLOR);
currentPoint = new Point(getWidth() / 2, getHeight() / 2);
width = backgroundBitmap.getWidth();
height = backgroundBitmap.getHeight();
initCropView();
}
public CropView(Context context, AttributeSet attrs) {
super(context, attrs, 0);
initCropView();
}
public CropView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initCropView();
}
#SuppressLint("DrawAllocation")
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mCanvas = canvas;
if (leftTop.equals(0, 0))
resetPoints();
mCanvas.save();
resizedBitmap = Bitmap.createBitmap(backgroundBitmap, 0, 0,
backgroundBitmap.getWidth(), backgroundBitmap.getHeight(),
matrix, true);
// mCanvas.drawBitmap(backgroundBitmap, matrix, rectPaint);
mCanvas.drawBitmap(resizedBitmap, null, selection, rectPaint);
mCanvas.drawBitmap(bitmap, selection.right - 25,
selection.bottom - 25, null);
rectPos.set(selection.left, selection.top);
mCanvas.restore();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
int eventaction = event.getAction();
switch (eventaction) {
case MotionEvent.ACTION_DOWN:
touchDown((int) event.getX(), (int) event.getY());
previous.set((int) event.getX(), (int) event.getY());
break;
case MotionEvent.ACTION_MOVE:
touchMove((int) event.getX(), (int) event.getY());
if (isActionInsideRectangle(event.getX(), event.getY())
&& !isAffectedBottom) {
drag((int) event.getX(), (int) event.getY());
invalidate(); // redraw rectangle
previous.set((int) event.getX(), (int) event.getY());
}
previous.set((int) event.getX(), (int) event.getY());
break;
case MotionEvent.ACTION_UP:
touchUp((int) event.getX(), (int) event.getY());
previous = new Point();
break;
}
return true;
}
private void initCropView() {
paint.setColor(Color.WHITE);
paint.setStyle(Style.STROKE);
paint.setStrokeWidth(5);
leftTop = new Point();
rightBottom = new Point();
center = new Point();
previous = new Point();
rectPos = new Point();
}
public void resetPoints() {
center.set(getWidth() / 2, getHeight() / 2);
leftTop.set((getWidth() - initial_size) / 2,
(getHeight() - initial_size) / 2);
rightBottom.set(leftTop.x + initial_size, leftTop.y + initial_size);
selection = new Rect(leftTop.x, leftTop.y, rightBottom.x,
rightBottom.y);
knobRect = new Rect(selection.right, selection.bottom,
bitmap.getWidth(), bitmap.getHeight());
dest = selection;
}
private boolean isActionInsideRectangle(float x, float y) {
int buffer = 10;
return (x >= (selection.left) && x <= (selection.right)
&& y >= (selection.top) && y <= (selection.bottom)) ? true
: false;
}
void touchDown(int x, int y) {
System.out.println("selection " + selection);
int dx = (previous.x - x) / 2;
int dy = (previous.y - y) / 2;
// d= rotation(dx,dy);
currentPoint.set(x, y);
if (pointsAreClose(x, y, selection.right, selection.bottom)) {
isAffectedBottom = true;
System.out.println("isAffectedBottom " + isAffectedBottom);
}
}
void touchMove(int x, int y) {
currentPoint.set(x, y);
if (isAffectedBottom) {
int dx = (previous.x - x) / 2;
int dy = (previous.y - y) / 2;
double startAngle = getAngle(previous.x, previous.y);
double currentAngle = getAngle(x, y);
matrix.postRotate((float) (startAngle - currentAngle),
selection.width() / 2.0f, selection.height() / 2.0f);
// selection.inset(dx, dy);
invalidate();
}
}
void touchUp(int x, int y) {
currentPoint.set(x, y);
isAffectedBottom = false;
}
private boolean pointsAreClose(float x1, float y1, float x2, float y2) {
return Math.hypot(x1 - x2, y1 - y2) < TOUCH_TOLERANCE;
}
private void drag(int x, int y) {
int movement;
movement = x - previous.x;
int movementY = y - previous.y;
selection.set(selection.left + movement, selection.top + movementY,
selection.right + movement, selection.bottom + movementY);
selection.sort();
invalidate();
}
/**
* Calculate the degree to be rotated by.
*
* #param event
* #return Degrees
*/
// private float rotation(float dx, float dy) {
//
// // double delta_x = (dx);
// // double delta_y = (dy);
// double radians = Math.atan2((selection.left) - (previous.y),
// (selection.top) - (previous.x));
// double radians2 = Math.atan2((selection.left) - (dy),
// (selection.top) - (dx));
//
// System.out.println("radians" + radians);
// System.out.println("" + radians2);
// System.out.println("radians2-radians" + (radians2 - radians));
// System.out.println(Math.toDegrees(radians2 - radians));
// return (float) Math.toDegrees(radians2 - radians);
//
// }
private double getAngle(double xTouch, double yTouch) {
double x = xTouch - (getWidth() / 2d);
double y = getHeight() - yTouch - (getHeight() / 2d);
switch (getQuadrant(x, y)) {
case 1:
System.out.println("1");
return Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI;
case 2:
case 3:
System.out.println("32");
return 180 - (Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI);
case 4:
System.out.println("4");
return 360 + Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI;
default:
// ignore, does not happen
return 0;
}
}
/**
* #return The selected quadrant.
*/
private int getQuadrant(double x, double y) {
if (x >= 0) {
return y >= 0 ? 1 : 4;
} else {
return y >= 0 ? 2 : 3;
}
}
}
}
I have Design A Layout that may work as your need.
Download Demo here
Java File
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.RelativeLayout;
public class ClipArt extends RelativeLayout {
int baseh;
int basew;
int basex;
int basey;
ImageButton btndel;
ImageButton btnrot;
ImageButton btnscl;
RelativeLayout clip;
Context cntx;
boolean freeze = false;
int h;
int i;
ImageView image;
String imageUri;
boolean isShadow;
int iv;
RelativeLayout layBg;
RelativeLayout layGroup;
RelativeLayout.LayoutParams layoutParams;
public LayoutInflater mInflater;
int margl;
int margt;
float opacity = 1.0F;
Bitmap originalBitmap;
int pivx;
int pivy;
int pos;
Bitmap shadowBitmap;
float startDegree;
String[] v;
public ClipArt(Context paramContext) {
super(paramContext);
cntx = paramContext;
layGroup = this;
basex = 0;
basey = 0;
pivx = 0;
pivy = 0;
mInflater = ((LayoutInflater) paramContext.getSystemService("layout_inflater"));
mInflater.inflate(R.layout.clipart, this, true);
btndel = ((ImageButton) findViewById(R.id.del));
btnrot = ((ImageButton) findViewById(R.id.rotate));
btnscl = ((ImageButton) findViewById(R.id.sacle));
layoutParams = new RelativeLayout.LayoutParams(250, 250);
layGroup.setLayoutParams(layoutParams);
image = ((ImageView) findViewById(R.id.clipart));
image.setImageResource(R.drawable.ic_launcher);
setOnTouchListener(new View.OnTouchListener() {
final GestureDetector gestureDetector = new GestureDetector(ClipArt.this.cntx,
new GestureDetector.SimpleOnGestureListener() {
public boolean onDoubleTap(MotionEvent paramAnonymous2MotionEvent) {
return false;
}
});
public boolean onTouch(View paramAnonymousView, MotionEvent event) {
if (!ClipArt.this.freeze) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
layGroup.invalidate();
gestureDetector.onTouchEvent(event);
layGroup.performClick();
basex = ((int) (event.getRawX() - layoutParams.leftMargin));
basey = ((int) (event.getRawY() - layoutParams.topMargin));
break;
case MotionEvent.ACTION_MOVE:
int i = (int) event.getRawX();
int j = (int) event.getRawY();
layBg = ((RelativeLayout) getParent());
if ((i - basex > -(layGroup.getWidth() * 2 / 3))
&& (i - basex < layBg.getWidth() - layGroup.getWidth() / 3)) {
layoutParams.leftMargin = (i - basex);
}
if ((j - basey > -(layGroup.getHeight() * 2 / 3))
&& (j - basey < layBg.getHeight() - layGroup.getHeight() / 3)) {
layoutParams.topMargin = (j - basey);
}
layoutParams.rightMargin = -1000;
layoutParams.bottomMargin = -1000;
layGroup.setLayoutParams(layoutParams);
break;
}
return true;
}
return true;
}
});
this.btnscl.setOnTouchListener(new View.OnTouchListener() {
#SuppressLint({ "NewApi" })
public boolean onTouch(View paramAnonymousView, MotionEvent event) {
if (!ClipArt.this.freeze) {
int j = (int) event.getRawX();
int i = (int) event.getRawY();
layoutParams = (RelativeLayout.LayoutParams) layGroup.getLayoutParams();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
ClipArt.this.layGroup.invalidate();
ClipArt.this.basex = j;
ClipArt.this.basey = i;
ClipArt.this.basew = ClipArt.this.layGroup.getWidth();
ClipArt.this.baseh = ClipArt.this.layGroup.getHeight();
int[] loaction = new int[2];
layGroup.getLocationOnScreen(loaction);
margl = layoutParams.leftMargin;
margt = layoutParams.topMargin;
break;
case MotionEvent.ACTION_MOVE:
float f2 = (float) Math.toDegrees(Math.atan2(i - ClipArt.this.basey, j - ClipArt.this.basex));
float f1 = f2;
if (f2 < 0.0F) {
f1 = f2 + 360.0F;
}
j -= ClipArt.this.basex;
int k = i - ClipArt.this.basey;
i = (int) (Math.sqrt(j * j + k * k)
* Math.cos(Math.toRadians(f1 - ClipArt.this.layGroup.getRotation())));
j = (int) (Math.sqrt(i * i + k * k)
* Math.sin(Math.toRadians(f1 - ClipArt.this.layGroup.getRotation())));
k = i * 2 + ClipArt.this.basew;
int m = j * 2 + ClipArt.this.baseh;
if (k > 150) {
layoutParams.width = k;
layoutParams.leftMargin = (ClipArt.this.margl - i);
}
if (m > 150) {
layoutParams.height = m;
layoutParams.topMargin = (ClipArt.this.margt - j);
}
ClipArt.this.layGroup.setLayoutParams(layoutParams);
ClipArt.this.layGroup.performLongClick();
break;
}
return true;
}
return ClipArt.this.freeze;
}
});
this.btnrot.setOnTouchListener(new View.OnTouchListener() {
#SuppressLint({ "NewApi" })
public boolean onTouch(View paramAnonymousView, MotionEvent event) {
if (!ClipArt.this.freeze) {
layoutParams = (RelativeLayout.LayoutParams) ClipArt.this.layGroup.getLayoutParams();
ClipArt.this.layBg = ((RelativeLayout) ClipArt.this.getParent());
int[] arrayOfInt = new int[2];
layBg.getLocationOnScreen(arrayOfInt);
int i = (int) event.getRawX() - arrayOfInt[0];
int j = (int) event.getRawY() - arrayOfInt[1];
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
ClipArt.this.layGroup.invalidate();
ClipArt.this.startDegree = layGroup.getRotation();
ClipArt.this.pivx = (layoutParams.leftMargin + ClipArt.this.getWidth() / 2);
ClipArt.this.pivy = (layoutParams.topMargin + ClipArt.this.getHeight() / 2);
ClipArt.this.basex = (i - ClipArt.this.pivx);
ClipArt.this.basey = (ClipArt.this.pivy - j);
break;
case MotionEvent.ACTION_MOVE:
int k = ClipArt.this.pivx;
int m = ClipArt.this.pivy;
j = (int) (Math.toDegrees(Math.atan2(ClipArt.this.basey, ClipArt.this.basex))
- Math.toDegrees(Math.atan2(m - j, i - k)));
i = j;
if (j < 0) {
i = j + 360;
}
ClipArt.this.layGroup.setRotation((ClipArt.this.startDegree + i) % 360.0F);
break;
}
return true;
}
return ClipArt.this.freeze;
}
});
this.btndel.setOnClickListener(new View.OnClickListener() {
public void onClick(View paramAnonymousView) {
if (!ClipArt.this.freeze) {
layBg = ((RelativeLayout) ClipArt.this.getParent());
layBg.performClick();
layBg.removeView(ClipArt.this.layGroup);
}
}
});
}
public void disableAll() {
this.btndel.setVisibility(4);
this.btnrot.setVisibility(4);
this.btnscl.setVisibility(4);
}
public ImageView getImageView() {
return this.image;
}
public void setFreeze(boolean paramBoolean) {
this.freeze = paramBoolean;
}
}
Layout file
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent">
<ImageButton android:id="#+id/rotate" android:layout_width="50dp" android:layout_height="50dp" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:adjustViewBounds="true" android:background="#android:color/transparent" android:scaleType="fitCenter" android:src="#drawable/rotation"/>
<ImageButton android:id="#+id/sacle" android:layout_width="50dp" android:layout_height="50dp" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:adjustViewBounds="true" android:background="#android:color/transparent" android:scaleType="fitCenter" android:src="#drawable/pointer"/>
<ImageButton android:id="#+id/del" android:layout_width="50dp" android:layout_height="50dp" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:adjustViewBounds="true" android:background="#android:color/transparent" android:scaleType="fitCenter" android:src="#drawable/close"/>
<ImageView android:id="#+id/clipart" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="10dp"/>
</RelativeLayout>
and images put in drawable
please check the repository in github i create it .
count the distance from center point in the rotate and zoom view to the push point.
just use :
private float getDistance(Point a, Point b) {
float v = ((a.x - b.x) * (a.x - b.x)) + ((a.y - b.y) * (a.y - b.y));
return ((int) (Math.sqrt(v) * 100)) / 100f;
}
and count the OA/OB that value can count the view new height and width
count the angle AOB, the A is the first push point , the B is the last move point ,the O is the center of the View Point .
and then just set new height and width for view ,and count the left and top for view .
souce link : https://github.com/ryanch741/android-view-rotate-zoom-single-finger
the code:
Point pushPoint;
int lastImgWidth;
int lastImgHeight;
int lastImgLeft;
int lastImgTop;
int lastImgAngle;
double lastComAngle;
int pushImgWidth;
int pushImgHeight;
int lastPushBtnLeft;
int lastPushBtnTop;
private View mView;
private Point mViewCenter;
private static final double PI = 3.14159265359;
public PushBtnTouchListener(View mView) {
this.mView = mView;
}
private FrameLayout.LayoutParams pushBtnLP;
private FrameLayout.LayoutParams imgLP;
float lastX = -1;
float lastY = -1;
#Override
public boolean onTouch(View pushView, MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
// 主点按下
case MotionEvent.ACTION_DOWN:
pushBtnLP = (FrameLayout.LayoutParams) pushView.getLayoutParams();
imgLP = (FrameLayout.LayoutParams) mView.getLayoutParams();
pushPoint = getPushPoint(pushBtnLP, event);
lastImgWidth = imgLP.width;
lastImgHeight = imgLP.height;
lastImgLeft = imgLP.leftMargin;
lastImgTop = imgLP.topMargin;
lastImgAngle = (int) mView.getRotation();
lastPushBtnLeft = pushBtnLP.leftMargin;
lastPushBtnTop = pushBtnLP.topMargin;
pushImgWidth = pushBtnLP.width;
pushImgHeight = pushBtnLP.height;
lastX = event.getRawX();
lastY = event.getRawY();
refreshImageCenter();
break;
// 副点按下
case MotionEvent.ACTION_POINTER_DOWN:
break;
case MotionEvent.ACTION_UP: {
break;
}
case MotionEvent.ACTION_POINTER_UP:
break;
case MotionEvent.ACTION_MOVE:
float rawX = event.getRawX();
float rawY = event.getRawY();
if (lastX != -1) {
if (Math.abs(rawX - lastX) < 5 && Math.abs(rawY - lastY) < 5) {
return false;
}
}
lastX = rawX;
lastY = rawY;
Point O = mViewCenter, A = pushPoint, B = getPushPoint(pushBtnLP, event);
float dOA = getDistance(O, A);
float dOB = getDistance(O, B);
float f = dOB / dOA;
int newWidth = (int) (lastImgWidth * f);
int newHeight = (int) (lastImgHeight * f);
imgLP.leftMargin = lastImgLeft - ((newWidth - lastImgWidth) / 2);
imgLP.topMargin = lastImgTop - ((newHeight - lastImgHeight) / 2);
imgLP.width = newWidth;
imgLP.height = newHeight;
mView.setLayoutParams(imgLP);
float fz = (((A.x - O.x) * (B.x - O.x)) + ((A.y - O.y) * (B.y - O.y)));
float fm = dOA * dOB;
double comAngle = (180 * Math.acos(fz / fm) / PI);
if (Double.isNaN(comAngle)) {
comAngle = (lastComAngle < 90 || lastComAngle > 270) ? 0 : 180;
} else if ((B.y - O.y) * (A.x - O.x) < (A.y - O.y) * (B.x - O.x)) {
comAngle = 360 - comAngle;
}
lastComAngle = comAngle;
float angle = (float) (lastImgAngle + comAngle);
angle = angle % 360;
mView.setRotation(angle);
Point imageRB = new Point(mView.getLeft() + mView.getWidth(), mView.getTop() + mView.getHeight());
Point anglePoint = getAnglePoint(O, imageRB, angle);
pushBtnLP.leftMargin = (int) (anglePoint.x - pushImgWidth / 2);
pushBtnLP.topMargin = (int) (anglePoint.y - pushImgHeight / 2);
pushView.setLayoutParams(pushBtnLP);
break;
}
return false;
}
private void refreshImageCenter() {
int x = mView.getLeft() + mView.getWidth() / 2;
int y = mView.getTop() + mView.getHeight() / 2;
mViewCenter = new Point(x, y);
}
private Point getPushPoint(FrameLayout.LayoutParams lp, MotionEvent event) {
return new Point(lp.leftMargin + (int) event.getX(), lp.topMargin + (int) event.getY());
}
private float getDistance(Point a, Point b) {
float v = ((a.x - b.x) * (a.x - b.x)) + ((a.y - b.y) * (a.y - b.y));
return ((int) (Math.sqrt(v) * 100)) / 100f;
}
private Point getAnglePoint(Point O, Point A, float angle) {
int x, y;
float dOA = getDistance(O, A);
double p1 = angle * PI / 180f;
double p2 = Math.acos((A.x - O.x) / dOA);
x = (int) (O.x + dOA * Math.cos(p1 + p2));
double p3 = Math.acos((A.x - O.x) / dOA);
y = (int) (O.y + dOA * Math.sin(p1 + p3));
return new Point(x, y);
}
I'm assuming the rotation/scaling happens from the image center? In that case, it's simple trigonometry to find the rotation angle and the size:
Calculate dx and dy of the finger's coordinates minus the center coordinates. Math.atan2(dy, dx) is the rotation angle (in radians) and Math.hypot(dx,dy) can be used for the relative size, or just double the dx/dy and use directly.
I have certain data in placed in my ScrollView. I want to enable it to zoom in/ zoom out. It contains simple ImageView and TextView.
Any suggestions will be helpful.
Thank you.
Here is my code:
<ScrollView
android:id="#+id/viewSoupMenu"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/soupback" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="50dp">
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="35dp"
android:layout_marginTop="30dp"
android:background="#android:color/transparent"
android:src="#drawable/flowericon" />
<ImageButton
android:id="#+id/btnVegClearSoup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginTop="20dp"
android:background="#android:color/transparent"
android:src="#drawable/btnvegsoupclearclickedxml" />
</LinearLayout>
</ScrollView>
You can use the class mentioned below for enabling Pinch Zoom in your ImageView and you can create a duplicate class of this class which extends TextView instead of ImageView for enabling zooming in it.
public class PinchZoomImageView extends ImageView implements OnTouchListener{
public PinchZoomImageView(Context context) {
super(context);
_init();
}
public PinchZoomImageView(Context context, AttributeSet attrs) {
super(context, attrs);
_init();
}
public PinchZoomImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
_init();
}
private void _init(){
//setOnTouchListener(this);
view = (ImageView) this;
view.setOnTouchListener(this);
metric = new DisplayMetrics();
// Work around a Cupcake bug
d_dpi=((0.52f/(metric.densityDpi))*240.0f)-0.52f;
Log.d("ash","dpi= "+d_dpi);
if(metric.densityDpi==160)
d_dpi=0.34f;
matrix.setTranslate(1f, 1f);
matrix.setScale((0.52f/800.0f)*metric.widthPixels+d_dpi, (0.52f/480.0f)*metric.heightPixels+d_dpi);
view.setImageMatrix(matrix);
bMap = BitmapFactory.decodeResource(getResources(), R.drawable.mfigure);
btsize = BitmapFactory.decodeResource(getResources(), R.drawable.map);
}
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if(hasFocus){
init();
}
}
private void init() {
maxZoom = (3.0f/480.0f)*metric.heightPixels+d_dpi;
minZoom = (0.52f/800.0f)*metric.widthPixels+d_dpi;
height = view.getDrawable().getIntrinsicHeight();
width = view.getDrawable().getIntrinsicWidth();
viewRect = new RectF(0, 0, view.getWidth(), view.getHeight());
}
#Override
public boolean onTouch(View v, MotionEvent event) {
ImageView view = (ImageView) v;
// Handle touch events here...
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
savedMatrix.set(matrix);
start.set(event.getX()/metric.widthPixels * 800, event.getY()/metric.heightPixels * 480);
Log.d(TAG, "mode=DRAG");
mode = DRAG;
click = true;
break;
case MotionEvent.ACTION_POINTER_DOWN:
oldDist = spacing(event);
Log.d(TAG, "oldDist=" + oldDist);
if (oldDist > 10f) {
savedMatrix.set(matrix);
midPoint(mid, event);
mode = ZOOM;
Log.d(TAG, "mode=ZOOM");
}
click = false;
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
Log.d(TAG, "mode=NONE");
if(click)
onClick(event.getX(), event.getY(),true);
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
temp_x = ((start.x) - ((event.getX()/metric.widthPixels)*800));
temp_y = ((start.y) - ((event.getY()/metric.heightPixels) * 480));
if(FloatMath.sqrt(temp_x * temp_x + temp_y * temp_y)< 10)
break;
matrix.set(savedMatrix);
// limit pan
matrix.getValues(matrixValues);
float currentY = matrixValues[Matrix.MTRANS_Y];
float currentX = matrixValues[Matrix.MTRANS_X];
float currentScale = matrixValues[Matrix.MSCALE_X];
float currentHeight = height * currentScale;
float currentWidth = width * currentScale;
float dx = (event.getX()/metric.widthPixels * 800) - start.x;
float dy = (event.getY()/metric.heightPixels * 480) - start.y;
float newX = currentX+dx;
float newY = currentY+dy;
RectF drawingRect = new RectF(newX, newY, newX+currentWidth, newY+currentHeight);
float diffUp = Math.min(viewRect.bottom-drawingRect.bottom, viewRect.top-drawingRect.top);
float diffDown = Math.max(viewRect.bottom-drawingRect.bottom, viewRect.top-drawingRect.top);
float diffLeft = Math.min(viewRect.left-drawingRect.left, viewRect.right-drawingRect.right);
float diffRight = Math.max(viewRect.left-drawingRect.left, viewRect.right-drawingRect.right);
if(diffUp > 0 ){
dy +=diffUp;
}
if(diffDown < 0){
dy +=diffDown;
}
if( diffLeft> 0){
dx += diffLeft;
}
if(diffRight < 0){
dx += diffRight;
}
matrix.postTranslate(dx, dy);
//selection.set(selection.x + dx, selection.y + dy);
click = false;
}
else if (mode == ZOOM) {
float newDist = spacing(event);
Log.d(TAG, "newDist=" + newDist);
if (newDist > 10f) {
matrix.set(savedMatrix);
float scale = newDist / oldDist;
matrix.getValues(matrixValues);
float currentScale = matrixValues[Matrix.MSCALE_X];
// limit zoom
if (scale * currentScale > maxZoom) {
scale = maxZoom / currentScale;
} else if (scale * currentScale < minZoom) {
scale = minZoom / currentScale;
}
matrix.postScale(scale, scale, mid.x, mid.y);
}
}
break;
}
float mv[] = new float[9];
matrix.getValues(mv);
Log.d("PV", "Click x " + mv[Matrix.MTRANS_X] + " y " + mv[Matrix.MTRANS_Y] + " cx " + event.getX() + " cy " + event.getY());
view.setImageMatrix(matrix);
view.invalidate();
return true; // indicate event was handled
}
public void onClick(float x, float y,boolean state){
Log.d("TAG","x="+x+" y "+y);
float mv[] = new float[9];
matrix.getValues(mv);
if(btsize != null)
btsize.recycle();
btsize = BitmapFactory.decodeResource(getResources(), R.drawable.map);
if(btSel != null)
btSel.recycle();
btSel = BitmapFactory.decodeResource(getResources(), R.drawable.mfigure);
Canvas canvas;
try{
canvas = new Canvas(btsize);
}
catch(Exception e){
btsize = BitmapFactory.decodeResource(getResources(), R.drawable.map).copy(Config.ARGB_8888,true);
canvas = new Canvas(btsize);
}
x -= mv[Matrix.MTRANS_X];
y -= mv[Matrix.MTRANS_Y];
float wdt = btsize.getWidth() * mv[Matrix.MSCALE_X];
float ht = btsize.getHeight() * mv[Matrix.MSCALE_Y];
float tw = x/wdt;
float th = y/ht;
selPoint.set(tw, th);
if(state)
canvas.drawBitmap(btSel, (tw * btsize.getWidth()) - (btSel.getWidth()/2), (th * btsize.getHeight()) - (btSel.getHeight()/2), null);
else
canvas.drawBitmap(btSel, (x * btsize.getWidth()) - (btSel.getWidth()/2), (y * btsize.getHeight()) - (btSel.getHeight()/2), null);
setImageBitmap(btsize);
}
/** Determine the space between the first two fingers */
private float spacing(MotionEvent event) {
float x = ((event.getX(0)/metric.widthPixels)*800) - ((event.getX(1)/metric.widthPixels)*800);
float y = ((event.getY(0)/metric.heightPixels) * 480) - ((event.getY(1)/metric.heightPixels) * 480);
return FloatMath.sqrt(x * x + y * y);
}
/** Calculate the mid point of the first two fingers */
private void midPoint(PointF point, MotionEvent event) {
float x = ((event.getX(0)/metric.widthPixels) * 800) + ((event.getX(1)/metric.widthPixels)*800);
float y = ((event.getY(0)/metric.heightPixels) * 480) + ((event.getY(1)/metric.heightPixels) * 480);
point.set(x / 2, y / 2);
}
private static final String TAG = "Touch";
// These matrices will be used to move and zoom image
Matrix matrix = new Matrix();
Matrix savedMatrix = 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 start = new PointF();
PointF mid = new PointF();
float oldDist = 1f;
// Limit zoomable/pannable image
private ImageView view;
private float[] matrixValues = new float[9];
private float maxZoom;
private float minZoom;
private float height;
private float width;
private RectF viewRect;
private float temp_x,temp_y;
private boolean click = false;
public PointF selPoint = new PointF();
Bitmap bMap;
private float d_dpi;
Paint paint = new Paint();
Canvas canvas = new Canvas();
private DisplayMetrics metric;
Bitmap bt = null;
Bitmap btsize = null;
Bitmap btSel = null;
}
Try using FrameLayout and have a look at this official document: Zooming a View.
I have tried develop an apps. This is ok for a small 101KB image file but when i use this apps for 307KB image instead of this image then it doesn't run and shows : java.lang.OutOfMemoryError: bitmap size exceeds VM budget.
Following is my code:
Resources rs = getResources();
Drawable dw = rs.getDrawable(R.drawable.chart);
width = dw.getIntrinsicWidth();
height = dw.getIntrinsicHeight();
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
fitScaleX = (float)dm.widthPixels / (float)width;
fitScaleY = fitScaleX;
and at line, Drawable dw = rs.getDrawable(R.drawable.chart);
The error occurs. How can i avoid this probleme?
This is my full code:
public class ZoomActivity extends Activity implements OnTouchListener {
ImageView view;
Matrix matrix = new Matrix();
Matrix savedMatrix = new Matrix();
PointF start = new PointF();
PointF mid = new PointF();
float oldDist = 0;
int width = 0;
int height = 0;
float fitScaleX = 1.0f;
float fitScaleY = 1.0f;
static final int STATE_NONE = 0;
static final int STATE_DRAG = 1;
static final int STATE_ZOOM = 2;
int mode = STATE_NONE;
long doubleClickStartTime = 0;
boolean doubleClickFlag = false;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.chart);
view = (ImageView) findViewById(R.id.imageViewChart);
view.setOnTouchListener(this);
getFitScale();
matrix.postScale(fitScaleX, fitScaleY, 0, 0);
view.setImageMatrix(matrix);
}
public void onStart() {
super.onStart();
}
private void getFitScale() {
Resources rs = getResources();
Drawable dw = rs.getDrawable(R.drawable.chart);
width = dw.getIntrinsicWidth();
height = dw.getIntrinsicHeight();
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
fitScaleX = (float)dm.widthPixels / (float)width;
fitScaleY = fitScaleX;
}
public boolean onTouch(View v, MotionEvent event)
{
// Handle touch events here...
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
savedMatrix.set(matrix);
start.set(event.getX(), event.getY());
mode = STATE_DRAG;
break;
case MotionEvent.ACTION_UP:
mode = STATE_NONE;
// for Auto Fitting
if(doubleClickFlag == false)
doubleClickStartTime = SystemClock.uptimeMillis();
if(doubleClickFlag) {
if(SystemClock.uptimeMillis() - doubleClickStartTime < 500) {
matrix.reset();
matrix.postScale(fitScaleX, fitScaleY, 0, 0);
} else {
doubleClickStartTime = SystemClock.uptimeMillis();
doubleClickFlag = false;
}
}
if(doubleClickFlag == false)
doubleClickFlag = true;
else
doubleClickFlag = false;
break;
case MotionEvent.ACTION_POINTER_UP:
mode = STATE_NONE;
break;
case MotionEvent.ACTION_MOVE:
if (mode == STATE_DRAG) {
float dx = event.getX() - start.x;
float dy = event.getY() - start.y;
float[] values = new float[9];
matrix.set(savedMatrix);
matrix.getValues(values);
if(values[Matrix.MTRANS_X]+ dx < view.getWidth() - width * values[Matrix.MSCALE_X]) {
dx = view.getWidth() - values[Matrix.MTRANS_X] - width * values[Matrix.MSCALE_X];
}
else if(values[Matrix.MTRANS_X]+ dx > 0) {
dx = 0 - values[Matrix.MTRANS_X];
}
if(values[Matrix.MTRANS_Y] + dy < view.getHeight() - height*values[Matrix.MSCALE_Y]) {
dy = view.getHeight() - height * values[Matrix.MSCALE_Y] - values[Matrix.MTRANS_Y];
}
else if(values[Matrix.MTRANS_Y] + dy > 0) {
dy = 0 - values[Matrix.MTRANS_Y];
}
matrix.postTranslate(dx, dy);
}
else if (mode == STATE_ZOOM) {
float newDist = spacing(event);
matrix.set(savedMatrix);
if (newDist > 10f) {
float[] values = new float[9];
matrix.set(savedMatrix);
matrix.getValues(values);
float scale = newDist / oldDist;
if(values[Matrix.MSCALE_X] * scale > 3.0f ||
values[Matrix.MSCALE_Y] * scale > 3.0f ) {
matrix.reset();
matrix.postScale(3.0f, 3.0f, 0, 0);
}
else if(values[Matrix.MSCALE_X] * scale < fitScaleX ||
values[Matrix.MSCALE_Y] * scale < fitScaleY) {
matrix.reset();
matrix.postScale(fitScaleX, fitScaleY, 0, 0);
}
else {
matrix.postScale(scale, scale, 0, 0);
}
}
}
break;
case MotionEvent.ACTION_POINTER_DOWN:
oldDist = spacing(event);
if (oldDist > 10f) {
savedMatrix.set(matrix);
midPoint(mid, event);
mode = STATE_ZOOM;
}
break;
}
// Perform the transformation
view.setImageMatrix(matrix);
return true; // indicate event was handled
}
private float spacing(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return FloatMath.sqrt(x * x + y * y);
}
private void midPoint(PointF point, MotionEvent event) {
float x = event.getX(0) + event.getX(1);
float y = event.getY(0) + event.getY(1);
point.set(x / 2, y / 2);
}
}
Bitmap images consume lot of memory, it is better to reduce their resolution. Here is a link with couple of workarounds with this issue. Bitmap images exceed VM budget work arounds