I am working on a sample application which allows resizing of view on dragging
the selection knobs. Resizing works fine when the view is not rotated. When the
view is rotated, if we resize the view, it gets offset by a certain amount. I
need to make the opposite corner of the view stay in its original position
while the view is being resized. Could anyone help me in understanding how this can
be achieved in android. The code snippet for resize is given below:
public void resize(float dx, float dy, SelectionView.KnobTypes selectedKnob) {
float newDx = dx;
float newDy = dy;
FrameLayout.LayoutParams params;
float viewWidth, viewHeight, ratio, newWidth, newHeight;
viewWidth = getWidth();
viewHeight = getHeight();
ratio = 1;
switch (selectedKnob) {
case eLeftTop:
newWidth = viewWidth - dx;
newHeight = viewHeight - dy;
if (newWidth <= mKnobRadius * 4 || newHeight <= mKnobRadius * 4) {
break;
}
if (viewWidth > viewHeight) {
if (viewHeight != 0) {
ratio = viewWidth / viewHeight;
}
newWidth = newHeight * ratio;
} else {
if (viewWidth != 0) {
ratio = viewHeight / viewWidth;
}
newHeight = newWidth * ratio;
}
params = new FrameLayout.LayoutParams(Math.round(newWidth),
Math.round(newHeight));
setLayoutParams(params);
newDx = Math.round(newWidth) - Math.round(viewWidth);
newDy = Math.round(newHeight) - Math.round(viewHeight);
setTranslationX(getTranslationX() - newDx);
setTranslationY(getTranslationY() - newDy);
break;
case eTopRight:
newWidth = viewWidth + dx;
newHeight = viewHeight - dy;
if (newWidth <= mKnobRadius * 4 || newHeight <= mKnobRadius * 4) {
break;
}
if (viewWidth > viewHeight) {
if (viewHeight != 0) {
ratio = viewWidth / viewHeight;
}
newWidth = newHeight * ratio;
} else {
if (viewWidth != 0) {
ratio = viewHeight / viewWidth;
}
newHeight = newWidth * ratio;
}
params = new FrameLayout.LayoutParams(Math.round(newWidth),
Math.round(newHeight));
setLayoutParams(params);
newDx = Math.round(newWidth) - Math.round(viewWidth);
newDy = Math.round(newHeight) - Math.round(viewHeight);
setTranslationY(getTranslationY() - newDy);
break;
case eRightBottom:
newWidth = viewWidth + dx;
newHeight = viewHeight + dy;
if (newWidth <= mKnobRadius * 4 || newHeight <= mKnobRadius * 4) {
break;
}
if (viewWidth > viewHeight) {
if (viewHeight != 0) {
ratio = viewWidth / viewHeight;
}
newWidth = newHeight * ratio;
} else {
if (viewWidth != 0) {
ratio = viewHeight / viewWidth;
}
newHeight = newWidth * ratio;
}
params = new FrameLayout.LayoutParams(Math.round(newWidth),
Math.round(newHeight));
setLayoutParams(params);
break;
case eLeftBottom:
newWidth = viewWidth - dx;
newHeight = viewHeight + dy;
if (newWidth <= mKnobRadius * 4 || newHeight <= mKnobRadius * 4) {
break;
}
if (viewWidth > viewHeight) {
if (viewHeight != 0) {
ratio = viewWidth / viewHeight;
}
newWidth = newHeight * ratio;
} else {
if (viewWidth != 0) {
ratio = viewHeight / viewWidth;
}
newHeight = newWidth * ratio;
}
params = new FrameLayout.LayoutParams(Math.round(newWidth),
Math.round(newHeight));
setLayoutParams(params);
newDx = Math.round(newWidth) - Math.round(viewWidth);
newDy = Math.round(newHeight) - Math.round(viewHeight);
setTranslationX(getTranslationX() - newDx);
break;
default:
break;
}
}
dx and dy are the offset by which the mouse is moved, selected knob is the knob which is currently being dragged.
The working sample is uploaded to this github repo:
https://github.com/vivekrk/resizesample.git
Related
Recently I used an implementation for a pinch to zoom in my TextureView using a SurfaceView. The zoom works perfectly but the view does not grow to the dimensions of the screen. In my case the TextureView is always in the dimensions 1080, 612. I would like to modify this zoom so that the view is filling the screen as I do the pinch.
Here is the code for my class that receives TextureView:
public class ScaleManager extends BaseInputManager {
private final TextureView mTargetView;
private final ScaleGestureDetector mScaleDetector;
private static final float MIN_SCALE = 1.0f;
private static final float MAX_SCALE = 5.0f;
private float mCurrentScale = MIN_SCALE;
private Matrix mMatrix = new Matrix();
private float[] mMatrixValues = new float[9];
private float mPreviousX;
private float mPreviousY;
private boolean mIsDragInProgress = false;
public ScaleManager(TextureView view) {
mTargetView = view;
mScaleDetector = new ScaleGestureDetector(view.getContext(), new ScaleListener());
mScaleDetector.setQuickScaleEnabled(false);
}
#Override
public boolean handle(KeyEvent event) {
return false;
}
#Override
public boolean handle(MotionEvent event) {
final int index = event.getActionIndex();
final int type = event.getToolType(index);
if (type == MotionEvent.TOOL_TYPE_FINGER || type == MotionEvent.TOOL_TYPE_STYLUS) {
mScaleDetector.onTouchEvent(event);
mMatrix.getValues(mMatrixValues);
boolean isScaling = (mMatrixValues[Matrix.MSCALE_X] != 1.0f && mMatrixValues[Matrix.MSCALE_Y] != 1.0f);
if (isScaling || mScaleDetector.isInProgress()) {
switch (event.getAction()) {
case MotionEvent.ACTION_POINTER_DOWN:
case MotionEvent.ACTION_DOWN:
if (event.getPointerCount() <= 2) {
mPreviousX = event.getX();
mPreviousY = event.getY();
}
if (event.getPointerCount() == 2) {
mIsDragInProgress = true;
}
break;
case MotionEvent.ACTION_MOVE:
if (event.getPointerCount() == 2) {
float x = mMatrixValues[Matrix.MTRANS_X];
float y = mMatrixValues[Matrix.MTRANS_Y];
float width = mTargetView.getWidth();
float height = mTargetView.getHeight();
float right = width * mCurrentScale - width;
float bottom = height * mCurrentScale - height;
float deltaX = event.getX() - mPreviousX;// x difference
float deltaY = event.getY() - mPreviousY;// y difference
float scaledWidth = Math.round(width * mCurrentScale);// width after applying current scale
float scaledHeight = Math.round(height * mCurrentScale);// height after applying current scale
//if scaledWidth is smaller than the views width
//in other words if the image width fits in the view
//limit left and right movement
if (scaledWidth < width) {
deltaX = 0;
if (y + deltaY > 0) {
deltaY = -y;
} else if (y + deltaY < -bottom) {
deltaY = -(y + bottom);
}
//if scaledHeight is smaller than the views height
//in other words if the image height fits in the view
//limit up and down movement
} else if (scaledHeight < height) {
deltaY = 0;
if (x + deltaX > 0) {
deltaX = -x;
} else if (x + deltaX < -right) {
deltaX = -(x + right);
}
//if the image doesn't fit in the width or height
//limit both up and down and left and 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);
}
}
//move the image with the matrix
mMatrix.postTranslate(deltaX, deltaY);
mTargetView.setTransform(mMatrix);
mTargetView.invalidate();
mPreviousX = event.getX();
mPreviousY = event.getY();
}
break;
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_UP:
if (event.getPointerCount() == 1) {
mIsDragInProgress = false;
}
break;
}
}
return mScaleDetector.isInProgress() || mIsDragInProgress;
}
return false;
}
private class ScaleListener implements ScaleGestureDetector.OnScaleGestureListener {
#Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
return true;
}
#Override
public boolean onScale(ScaleGestureDetector detector) {
float width = mTargetView.getWidth();
float height = mTargetView.getHeight();
float factor = detector.getScaleFactor();
float scale = mCurrentScale * factor;
if (scale > MAX_SCALE) {
factor = MAX_SCALE / mCurrentScale;
mCurrentScale = MAX_SCALE;
} else if (scale < MIN_SCALE) {
factor = MIN_SCALE / mCurrentScale;
mCurrentScale = MIN_SCALE;
} else {
mCurrentScale = scale;
}
if (width * scale <= width || height * scale <= height) {
mMatrix.postScale(factor, factor, width / 2, height / 2);
} else {
mMatrix.postScale(factor, factor, detector.getFocusX(), detector.getFocusY());
}
if (factor < 1) {
float right = width * mCurrentScale - width;
float bottom = height * mCurrentScale - height;
mMatrix.getValues(mMatrixValues);
float x = mMatrixValues[Matrix.MTRANS_X];
float y = mMatrixValues[Matrix.MTRANS_Y];
if (x < -right) {
mMatrix.postTranslate(-(x + right), 0);
} else if (x > 0) {
mMatrix.postTranslate(-x, 0);
}
if (y < -bottom) {
mMatrix.postTranslate(0, -(y + bottom));
} else if (y > 0) {
mMatrix.postTranslate(0, -y);
}
}
return true;
}
#Override
public void onScaleEnd(ScaleGestureDetector detector) {
}
}
}
When I start the view I use a class called AspectFrameLayout to determine the initial ratio of the view. And this AspectFrameLayout is called each time the view is being modified to maintain the aspect ratio. Follow the code:
<com.examples.views.AspectRatioFrameLayout
android:id="#+id/player_video"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:focusable="true"
android:focusableInTouchMode="true" />
mSurfaceView = layoutInflater.inflate(R.layout.texture_view,
player_video_frame, false)
This is the AspectFrameLayout class that I use to keep the aspect ratio:
public final class AspectRatioFrameLayout extends FrameLayout {
private static final float MAX_ASPECT_RATIO_DEFORMATION_FRACTION = 0.01f;
private float mVideoAspectRatio;
public AspectRatioFrameLayout(Context context) {
super(context);
}
public AspectRatioFrameLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setAspectRatio(float ratio) {
if (this.mVideoAspectRatio != ratio) {
this.mVideoAspectRatio = ratio;
requestLayout();
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (mVideoAspectRatio == 0) {
// Aspect ratio not set.
return;
}
int width = getMeasuredWidth();
int height = getMeasuredHeight();
float viewAspectRatio = (float) width / height;
float aspectDeformation = mVideoAspectRatio / viewAspectRatio - 1;
if (Math.abs(aspectDeformation) <= MAX_ASPECT_RATIO_DEFORMATION_FRACTION) {
// We're within the allowed tolerance.
return;
}
if (aspectDeformation > 0) {
height = (int) (width / mVideoAspectRatio);
} else {
width = (int) (height * mVideoAspectRatio);
}
super.onMeasure(
MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
);
}
}
I'm loading Image from server to imageview. I'm using Picasso to load the image from server to imageview.
On touch of that image, i want it to appear fullscreen and even zoom/tap should work.
I don't know what to do for this, Please help me with suggestions or some examples.
I found few examples, but there was more than 1000 lines code, I couldn't find it helpful and I didn't understand what to do with it.
Thanks.
this is my code.
image = (ImageView) findViewById(R.id.image);
image.setOnClickListener(this);
Picasso.with(this).load("http://Imageurl").into(image);
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.image:
//what to do here ?
break;
}
}
You can use following cusome class for implment zooming functionality in your layout which will work for me better.
public class TouchOrZoomImageView extends ImageView
{
Matrix mMatrix = 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 TouchOrZoomImageView(Context context)
{
super(context);
sharedConstructing(context);
}
public TouchOrZoomImageView(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());
mMatrix.setTranslate(1f, 1f);
m = new float[9];
setImageMatrix(mMatrix);
setScaleType(ScaleType.MATRIX);
setOnTouchListener(new OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
mScaleDetector.onTouchEvent(event);
mMatrix.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);
}
mMatrix.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(mMatrix);
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 = (float) Math.min(
Math.max(.95f, detector.getScaleFactor()), 1.05);
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)
{
mMatrix.postScale(mScaleFactor, mScaleFactor, width / 2, height / 2);
if (mScaleFactor < 1)
{
mMatrix.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)
mMatrix.postTranslate(0, -(y + bottom));
else if (y > 0)
mMatrix.postTranslate(0, -y);
}
else
{
if (x < -right)
mMatrix.postTranslate(-(x + right), 0);
else if (x > 0)
mMatrix.postTranslate(-x, 0);
}
}
}
}
else
{
mMatrix.postScale(mScaleFactor, mScaleFactor, detector.getFocusX(),
detector.getFocusY());
mMatrix.getValues(m);
float x = m[Matrix.MTRANS_X];
float y = m[Matrix.MTRANS_Y];
if (mScaleFactor < 1)
{
if (x < -right)
mMatrix.postTranslate(-(x + right), 0);
else if (x > 0)
mMatrix.postTranslate(-x, 0);
if (y < -bottom)
mMatrix.postTranslate(0, -(y + bottom));
else if (y > 0)
mMatrix.postTranslate(0, -y);
}
}
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);
mMatrix.setScale(scale, scale);
setImageMatrix(mMatrix);
saveScale = 1f;
// Center the image
redundantYSpace = (float) height - (scale * (float) bmHeight);
redundantXSpace = (float) width - (scale * (float) bmWidth);
redundantYSpace /= (float) 2;
redundantXSpace /= (float) 2;
mMatrix.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(mMatrix);
}
}
Now put after this class as view in your layout whereyou want to show like bellow is the example
<com.yourpackagename.TouchOrZoomImageView
android:id="#+id/bottomImage"
android:src="#drawable/nature_2"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1" />
Then after you can load data or set src same as you are setting in ImageView, This class inherit ImageView class so you can set all property which is using image use.
There are some simple steps you should follow.
Create one full-screen Activitywith ImageView only.
You need to implement library for Pinch to Zoom In/Zoom Out Images. Through which you can zoom In/Out your Imageview.
By Clicking on Imageview Start that Activity and Finish on onBackPress()
There are some of the examples of library you can use.
https://github.com/martinwithaar/PinchToZoom
https://github.com/jsibbold/zoomage
I have a custom component that basically Draws a Bitmap on a canvas for interaction with the user.
Now I would like to add zoom-in capability, so that the user can zoom in and see better the details.
The problem is that when I enlarge the Bitmap I often hit the memory limit and get an "Out of Memory" error.
This is because I try to ENLARGE the Bitmap.
I have tried createBitmap(Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter) wit the appropriate matrix matrix.postScale(2, 2);
Please any suggestion on how to implement "zoom-in" without going out of memory?
If i use this code (THE ONLY DIFFERENCE IS THAT I SURROUNDED IT WITH TRY-CATCH) it does not go out of memory.
Matrix matrix = new Matrix();
// resize the bit map
matrix.postScale(2, 2);
Bitmap bm2=null;
try {
bm2=Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, false);
} catch (Exception e){Toast.makeText(MainActivity.this, "Image is too large, out of memory", Toast.LENGTH_LONG).show();
return;
}
//bm.recycle();
myView.setimage(bm2);
Why does it work now?
Create this custom ImageView, and add it to activity:
public class TouchImageView extends ImageView {
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() {
#Override
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);
}
}
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);
}
}
I recommand you the ZoomableImageView library, which is very easy to set up and use:
https://github.com/Neferetheka/ZoomableImageView
Basically, all you have to do is this:
zoomableImageView.setImageBitmap( bitmap );
I m using the MikeOrtiz TouchImageView From the GitHub. Here is the link TouchImageView
I m trying to set the width fit to Screen in landscape Orientation only
here is an image to show what i want to do.
i want this
Instead of this which I m getting now in landscape
Here is some code.
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
viewWidth = MeasureSpec.getSize(widthMeasureSpec);
viewHeight = MeasureSpec.getSize(heightMeasureSpec);
//
// Rescales image on rotation
//
if (oldMeasuredHeight == viewWidth && oldMeasuredHeight == viewHeight
|| viewWidth == 0 || viewHeight == 0)
return;
oldMeasuredHeight = viewHeight;
oldMeasuredWidth = viewWidth;
if (saveScale == 1) {
// Fit to screen.
float scale;
Drawable drawable = getDrawable();
if (drawable == null || drawable.getIntrinsicWidth() == 0
|| drawable.getIntrinsicHeight() == 0)
return;
int bmWidth = drawable.getIntrinsicWidth();
int bmHeight = drawable.getIntrinsicHeight();
Log.d("bmSize", "bmWidth: " + bmWidth + " bmHeight : " + bmHeight);
float scaleX = (float) viewWidth / (float) bmWidth;
float scaleY = (float) viewHeight / (float) bmHeight;
scale = Math.min(scaleX, scaleY);
matrix.setScale(scale , scale );
// Center the image
float redundantYSpace = (float) viewHeight
- (scale * (float) bmHeight);
float redundantXSpace = (float) viewWidth
- (scale * (float) bmWidth);
redundantYSpace /= (float) 2;
redundantXSpace /= (float) 2;
matrix.postTranslate(redundantXSpace, redundantYSpace);
origWidth = viewWidth - 2 * redundantXSpace;
origHeight = viewHeight - 2 * redundantYSpace;
setImageMatrix(matrix);
}
fixTrans();
}
Thank you
Is there any way to zoom the video from any specific coordinate on touch. I have tried all the way from mediaplayer and surfaceview and making both custom and accessing window manager and all.If any one has idea so please explain.
You can do this using SurfaceView. Check out my article Surface View - Video Cropping.
Code to crop SurfaceView.
private void updateTextureViewSize(int viewWidth, int viewHeight) {
float scaleX = 1.0f;
float scaleY = 1.0f;
if (mVideoWidth > viewWidth && mVideoHeight > viewHeight) {
scaleX = mVideoWidth / viewWidth;
scaleY = mVideoHeight / viewHeight;
} else if (mVideoWidth < viewWidth && mVideoHeight < viewHeight) {
scaleY = viewWidth / mVideoWidth;
scaleX = viewHeight / mVideoHeight;
} else if (viewWidth > mVideoWidth) {
scaleY = (viewWidth / mVideoWidth) / (viewHeight / mVideoHeight);
} else if (viewHeight > mVideoHeight) {
scaleX = (viewHeight / mVideoHeight) / (viewWidth / mVideoWidth);
}
// Calculate pivot points, in our case crop from center
int pivotPointX = viewWidth / 2;
int pivotPointY = viewHeight / 2;
Matrix matrix = new Matrix();
matrix.setScale(scaleX, scaleY, pivotPointX, pivotPointY);
mTextureView.setTransform(matrix);
mTextureView.setLayoutParams(new FrameLayout.LayoutParams(viewWidth, viewHeight));
}