Unable to zoom in the bus route map - java

i have a bus route map as an image.
using the zoom controller the image is zooming out but not zooming in
please look at my code and let me know the change to be done make it working..
i am developing my app on Gingerbread i.e API 10
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.ZoomControls;
public class Busmaps extends Activity {
ImageView img;
ZoomControls zoom;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.busmaps);
img = (ImageView) findViewById(R.id.imageViewmaps1);
zoom = (ZoomControls) findViewById(R.id.zoomControls1);
zoom.setOnZoomInClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
int w = img.getWidth();
int h = img.getHeight();
RelativeLayout.LayoutParams params =
new RelativeLayout.LayoutParams(w + 50, h + 50);
params.addRule(RelativeLayout.CENTER_IN_PARENT);
img.setLayoutParams(params);
}
});
zoom.setOnZoomOutClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
int w = img.getWidth();
int h = img.getHeight();
RelativeLayout.LayoutParams params =
new RelativeLayout.LayoutParams(w - 50, h - 50);
params.addRule(RelativeLayout.CENTER_IN_PARENT);
img.setLayoutParams(params);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.bus_map_zoom, menu);
return true;
}
}
my xml says for bus route image:-
<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" >
<ImageView
android:id="#+id/imageViewmaps1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:src="#drawable/map" />
<ZoomControls
android:id="#+id/zoomControls1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
/>
</RelativeLayout>
how should i make my zoom control working for both Zoom in and Zoom out.

Please replace your Zoom in and ZoomOut listener with the following:
zoom.setOnZoomInClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
float x = img.getScaleX();
float y = img.getScaleY();
img.setScaleX((float) (x+1));
img.setScaleY((float) (y+1));
}
});
zoom.setOnZoomOutClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
float x = img.getScaleX();
float y = img.getScaleY();
img.setScaleX((float) (x-1));
img.setScaleY((float) (y-1));
}
});
}
Alternate option is to load the image in the Web view which has build in zoom controller.
As follows:
String page = "<html><body><center><img src=\""+path to your image+"\"/></center></body></html>";
webView.loadDataWithBaseURL("fake",page, "text/html", "UTF-8","");
If you dont want to use the build in web view zoom controller then you can just place your own buttons and apply zoom in and zoom out on web view as follows:
webView.setInitialScale(ZOOM_LEVEL);

public class Busmap extends Activity implements OnTouchListener
{
private static final String TAG = "Touch";
#SuppressWarnings("unused")
private static final float MIN_ZOOM = 1f,MAX_ZOOM = 1f;
// These matrices will be used to scale points of the image
Matrix matrix = new Matrix();
Matrix savedMatrix = new Matrix();
// The 3 states (events) which the user is trying to perform
static final int NONE = 0;
static final int DRAG = 1;
static final int ZOOM = 2;
int mode = NONE;
// these PointF objects are used to record the point(s) the user is touching
PointF start = new PointF();
PointF mid = new PointF();
float oldDist = 1f;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.busmaps);
ImageView view = (ImageView) findViewById(R.id.imageViewmaps1);
view.setOnTouchListener(this);
}
#Override
public boolean onTouch(View v, MotionEvent event)
{
ImageView view = (ImageView) v;
view.setScaleType(ImageView.ScaleType.MATRIX);
float scale;
dumpEvent(event);
// Handle touch events here...
switch (event.getAction() & MotionEvent.ACTION_MASK)
{
case MotionEvent.ACTION_DOWN: // first finger down only
savedMatrix.set(matrix);
start.set(event.getX(), event.getY());
Log.d(TAG, "mode=DRAG"); // write to LogCat
mode = DRAG;
break;
case MotionEvent.ACTION_UP: // first finger lifted
case MotionEvent.ACTION_POINTER_UP: // second finger lifted
mode = NONE;
Log.d(TAG, "mode=NONE");
break;
case MotionEvent.ACTION_POINTER_DOWN: // first and second finger down
oldDist = spacing(event);
Log.d(TAG, "oldDist=" + oldDist);
if (oldDist > 5f) {
savedMatrix.set(matrix);
midPoint(mid, event);
mode = ZOOM;
Log.d(TAG, "mode=ZOOM");
}
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG)
{
matrix.set(savedMatrix);
matrix.postTranslate(event.getX() - start.x, event.getY() - start.y); // create the transformation in the matrix of points
}
else if (mode == ZOOM)
{
// pinch zooming
float newDist = spacing(event);
Log.d(TAG, "newDist=" + newDist);
if (newDist > 5f)
{
matrix.set(savedMatrix);
scale = newDist / oldDist; // setting the scaling of the
// matrix...if scale > 1 means
// zoom in...if scale < 1 means
// zoom out
matrix.postScale(scale, scale, mid.x, mid.y);
}
}
break;
}
view.setImageMatrix(matrix); // display the transformation on screen
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);
}

Related

android how to recycle image before loading a new one

I have a out of memory problem here in which i have full screen images being displayed. I want to show images in full screen and I have two buttons to cycle through them to the left or to the right. How can i have the past images be recycled before showing the next to prevent the out of memory exception? or is there an even better way to do so?
here is my class in which i view the image.
public class ImageViewActivity extends Activity
{
private Button btnHome;
private Button btnBack;
private ImageButton btnLeft;
private ImageButton btnRight;
ImageView imageView;
RelativeLayout layout;
int height;
int width;
Bitmap bitmap;
String[] imagesPath;
int position;
// 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;
String savedItemClicked;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.imageview_activity);
btnHome = (Button) findViewById(R.id.btnHome);
btnBack = (Button) findViewById(R.id.btnBack);
btnLeft = (ImageButton) findViewById(R.id.leftArrow);
btnRight = (ImageButton) findViewById(R.id.rightArrow);
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
height = displayMetrics.heightPixels;
width = displayMetrics.widthPixels;
imagesPath = getIntent().getStringExtra("IMAGES").split("\\|");
position = getIntent().getIntExtra("POSITION", 0);
bitmap = BitmapFactory.decodeFile(imagesPath[position]);
imageView = (ImageView)findViewById(R.id.displayImage);
imageView.setImageBitmap(Bitmap.createScaledBitmap(bitmap, width, height, false));
btnLeft.setOnClickListener(new View.OnClickListener()
{
public void onClick(View arg0)
{
if (position == 0)
position = 5;
else
position--;
RectF imageRectF = new RectF(0, 0, width, height);
RectF viewRectF = new RectF(0, 0, width, height);
matrix.setRectToRect(imageRectF, viewRectF, Matrix.ScaleToFit.CENTER);
bitmap = BitmapFactory.decodeFile(imagesPath[position]);
ImageView imageView = (ImageView)findViewById(R.id.displayImage);
imageView.setImageBitmap(Bitmap.createScaledBitmap(bitmap, width, height, false));
imageView.setImageMatrix(matrix);
}
});
btnRight.setOnClickListener(new View.OnClickListener()
{
public void onClick(View arg0)
{
if (position == 5)
position = 0;
else
position++;
RectF imageRectF = new RectF(0, 0, width, height);
RectF viewRectF = new RectF(0, 0, width, height);
matrix.setRectToRect(imageRectF, viewRectF, Matrix.ScaleToFit.CENTER);
bitmap = BitmapFactory.decodeFile(imagesPath[position]);
ImageView imageView = (ImageView)findViewById(R.id.displayImage);
imageView.setImageBitmap(Bitmap.createScaledBitmap(bitmap, width, height, false));
imageView.setImageMatrix(matrix);
}
});
btnHome.setOnClickListener(new View.OnClickListener()
{
public void onClick(View arg0)
{
Intent ActivitySwitch = new Intent(getApplicationContext(), MainMenuActivity.class);
startActivity(ActivitySwitch);
}
});
btnBack.setOnClickListener(new View.OnClickListener()
{
public void onClick(View arg0)
{
Intent ActivitySwitch = new Intent(getApplicationContext(), AddClientActivity.class);
startActivity(ActivitySwitch);
}
});
imageView.setOnTouchListener(new View.OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
ImageView view = (ImageView) v;
dumpEvent(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 = DRAG;
break;
case MotionEvent.ACTION_POINTER_DOWN:
oldDist = spacing(event);
if (oldDist > 10f) {
savedMatrix.set(matrix);
midPoint(mid, event);
mode = ZOOM;
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
// ...
matrix.set(savedMatrix);
matrix.postTranslate(event.getX() - start.x, event.getY()
- start.y);
} else if (mode == ZOOM) {
float newDist = spacing(event);
if (newDist > 10f) {
matrix.set(savedMatrix);
float scale = newDist / oldDist;
matrix.postScale(scale, scale, mid.x, mid.y);
}
}
break;
}
view.setImageMatrix(matrix);
return true;
}
});
}
private void dumpEvent(MotionEvent event) {
String names[] = { "DOWN", "UP", "MOVE", "CANCEL", "OUTSIDE",
"POINTER_DOWN", "POINTER_UP", "7?", "8?", "9?" };
StringBuilder sb = new StringBuilder();
int action = event.getAction();
int actionCode = action & MotionEvent.ACTION_MASK;
sb.append("event ACTION_").append(names[actionCode]);
if (actionCode == MotionEvent.ACTION_POINTER_DOWN
|| actionCode == MotionEvent.ACTION_POINTER_UP) {
sb.append("(pid ").append(
action >> MotionEvent.ACTION_POINTER_ID_SHIFT);
sb.append(")");
}
sb.append("[");
for (int i = 0; i < event.getPointerCount(); i++) {
sb.append("#").append(i);
sb.append("(pid ").append(event.getPointerId(i));
sb.append(")=").append((int) event.getX(i));
sb.append(",").append((int) event.getY(i));
if (i + 1 < event.getPointerCount())
sb.append(";");
}
sb.append("]");
}
/** Determine the space between the first two fingers */
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);
}
/** 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);
}
thank you for any input and if you need any additional information please feel free to ask!
I would either scale down the image or consider using the Picasso image loading library: http://square.github.io/picasso/
It is also really simply to use and prevents a lot Out of Memory Exceptions.
Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);
it was a lot simpler then i first imagined. i simply added this
bitmap.recycle();
before i declared my bitmap to the new image.

Pinch zoom ImageView - Want to scale whole image beyond size of screen

I have pinch zooming for an image, however when I first load the app the whole of the image is not visible, only a portion. The image fills the width of the screen but there is white-space above and below it. Also when the image is scaled the image becomes very short. The aspect ratio should stay the same.
I would like to have the whole image visible when the app loads and then I want to be able to zoom out with two fingers where the image doesn't become smaller than the size of the screen, so that the screen is always full (the image is a map).
For zooming in, the image should scale beyond the width and height of the phone screen. That way I can pan across to view the map in detail.
Any help would be greatly appreciated. Related code is below.
My MainActivity code:
public class MainActivity extends Activity
{
private MapView image;
private Matrix matrix = new Matrix();
float mLastTouchX, mPosX;
float mLastTouchY, mPosY;
private ScaleGestureDetector mScaleDetector;
private float mScaleFactor = 1f;
private int mActivePointerId = MotionEvent.INVALID_POINTER_ID;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
image = (MapView)findViewById(R.id.imageView1);
mScaleDetector = new ScaleGestureDetector(MainActivity.this, new ScaleListener());
}
public void onDraw(Canvas canvas)
{
canvas.save();
canvas.scale(mScaleFactor, mScaleFactor);
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings)
{
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public boolean onTouchEvent(MotionEvent event)
{
mScaleDetector.onTouchEvent(event);
final int action = MotionEventCompat.getActionMasked(event);
switch (action)
{
case MotionEvent.ACTION_DOWN:
{
final int pointerIndex = MotionEventCompat.getActionIndex(event);
final float x = MotionEventCompat.getX(event, pointerIndex);
final float y = MotionEventCompat.getY(event, pointerIndex);
// Remember where we started (for dragging)
mLastTouchX = x;
mLastTouchY = y;
// Save the ID of this pointer (for dragging)
mActivePointerId = MotionEventCompat.getPointerId(event, 0);
break;
}
case MotionEvent.ACTION_MOVE:
{
// Find the index of the active pointer and fetch its position
final int pointerIndex =
MotionEventCompat.findPointerIndex(event, mActivePointerId);
final float x = MotionEventCompat.getX(event, pointerIndex);
final float y = MotionEventCompat.getY(event, pointerIndex);
// Calculate the distance moved
final float dx = x - mLastTouchX;
final float dy = y - mLastTouchY;
mPosX += dx;
mPosY += dy;
// Remember this touch position for the next move event
mLastTouchX = x;
mLastTouchY = y;
break;
}
case MotionEvent.ACTION_UP:
{
mActivePointerId = MotionEvent.INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_CANCEL:
{
mActivePointerId = MotionEvent.INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_POINTER_UP:
{
final int pointerIndex = MotionEventCompat.getActionIndex(event);
final int pointerId = MotionEventCompat.getPointerId(event, pointerIndex);
if (pointerId == mActivePointerId)
{
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mLastTouchX = MotionEventCompat.getX(event, newPointerIndex);
mLastTouchY = MotionEventCompat.getY(event, newPointerIndex);
mActivePointerId = MotionEventCompat.getPointerId(event, newPointerIndex);
}
break;
}
}
image.setX(mPosX);
image.setY(mPosY);
return true;
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener
{
#Override
public boolean onScale(ScaleGestureDetector detector)
{
mScaleFactor *= detector.getScaleFactor();
mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));
matrix.setScale(mScaleFactor, mScaleFactor);
image.setImageMatrix(matrix);
return true;
}
}
}
Custom ImageView:
public class MapView extends ImageView
{
public MapView(final Context context, final AttributeSet attrs)
{
super(context, attrs);
}
public void scaleImage(int boundBoxInDp)
{
Drawable drawable = getDrawable();
Bitmap bitmap = ((BitmapDrawable)drawable).getBitmap();
int width = bitmap.getWidth();
int height = bitmap.getHeight();
float xScale = ((float) boundBoxInDp) / width;
float yScale = ((float) boundBoxInDp) / height;
float scale = (xScale <= yScale) ? xScale : yScale;
Matrix matrix = new Matrix();
matrix.postScale(scale, scale);
Bitmap scaledBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
BitmapDrawable result = new BitmapDrawable(scaledBitmap);
width = scaledBitmap.getWidth();
height = scaledBitmap.getHeight();
// Apply the scaled bitmap
setImageDrawable(result);
// Now change ImageView's dimensions to match the scaled image
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)getLayoutParams();
params.width = width;
params.height = height;
setLayoutParams(params);
}
private int dpToPx(Context c, int dp)
{
float density = c.getResources().getDisplayMetrics().density;
return Math.round((float)dp * density);
}
#Override
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec)
{
final Drawable d = this.getDrawable();
if (d != null)
{
// ceil not round - avoid thin vertical gaps along the left/right edges
final int width = MeasureSpec.getSize(widthMeasureSpec);
final int height = (int) Math.ceil(width * (float) d.getIntrinsicHeight() / d.getIntrinsicWidth());
this.setMeasuredDimension(width, height);
}
else
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
}
Layout file:
<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:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context=".MainActivity">
<com.kilobolt.framework.locationfinder.MapView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="matrix"
android:src="#drawable/uea" />
</RelativeLayout>
I took a different approach to solve the problem of displaying a custom map. Instead of displaying a fixed sized image, I used Google Maps Javascript API v3 (https://developers.google.com/maps/documentation/javascript/examples/marker-simple).
I displayed this in a web view and created a reusable function in javascript to create custom markers.
If anyone comes across this issue, which appears to not to be well documented, give this map solution a try, and feel free to message me. Hope this helps.

How to Zoom a Text View in Scroll View?

I have seen a lots of code here which is helpful to zoom your textview but none of them work with my text because it is within scrollview. How can I get rid of this problem?
import android.app.Activity;
import android.os.Bundle;
import android.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.TextView;
public class Introduce extends Activity implements OnTouchListener{
final static float STEP = 200;
TextView mtxtRatio1,mtxtRatio2,mtxtRatio3,mtxtRatio4;
float mRatio = 1.0f;
int mBaseDist;
float mBaseRatio;
float fontsize = 13;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.introduce);
mtxtRatio1 = (TextView)findViewById(R.id.intro1);
mtxtRatio1.setTextSize(mRatio+13);
}
public boolean onTouchEvent(MotionEvent event) {
if (event.getPointerCount() == 2) {
int action = event.getAction();
int pureaction = action & MotionEvent.ACTION_MASK;
if (pureaction == MotionEvent.ACTION_POINTER_DOWN) {
mBaseDist = getDistance(event);
mBaseRatio = mRatio;
} else {
float delta = (getDistance(event) - mBaseDist) / STEP;
float multi = (float)Math.pow(2, delta);
mRatio = Math.min(1024.0f, Math.max(0.1f, mBaseRatio * multi));
mtxtRatio1.setTextSize(mRatio+13);
}
}
return true;
}
int getDistance(MotionEvent event) {
int dx = (int)(event.getX(0) - event.getX(1));
int dy = (int)(event.getY(0) - event.getY(1));
return (int)(Math.sqrt(dx * dx + dy * dy));
}
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
return false;
}
}
Following is the way for implementing Pinch Zoom in TextView with/without ScrollView
MainActivity.java
public class MainActivity extends AppCompatActivity{
final static float STEP = 200;
float mRatio = 1.0f;
int mBaseDist;
float mBaseRatio;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
textViewData = (TextView).findViewById(R.id.tvContributeData);
textViewData.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent event) {
if (event.getPointerCount() == 2) {
int action = event.getAction();
int pureaction = action & MotionEvent.ACTION_MASK;
if (pureaction == MotionEvent.ACTION_POINTER_DOWN) {
mBaseDist = getDistance(event);
mBaseRatio = mRatio;
} else {
float delta = (getDistance(event) - mBaseDist) / STEP;
float multi = (float) Math.pow(2, delta);
mRatio = Math.min(1024.0f, Math.max(0.1f, mBaseRatio * multi));
textViewData.setTextSize(mRatio + 13);
}
}
return true;
});
int getDistance(MotionEvent event) {
int dx = (int) (event.getX(0) - event.getX(1));
int dy = (int) (event.getY(0) - event.getY(1));
return (int) (Math.sqrt(dx * dx + dy * dy));
}
}
}
Use Polidea's zoomview, it works in a scrollview and has pinch zoom and double tap to zoom, one thing thought, I ended up disabling the pinch zoom and just using the double tap
https://github.com/Polidea/android-zoom-view
Put your TextView andany other Views you are using into a LinearLayout that lives on a ZoomView which lives on the ScrollView, e.g.:
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.polidea.ZoomView
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<LinearLayout
android:id="#+id/myLinearLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
</LinearLayout>
</com.polidea.ZoomView>
</ScrollView>
Hopefully this will help others. This answer is from here and here.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.tv);
tv.setText(getString(R.string.hello_world));
scaleGestureDetector = new ScaleGestureDetector(this, new simpleOnScaleGestureListener());
tv.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getPointerCount() == 1){
//stuff for 1 pointer
}else{ //when 2 pointers are present
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// Disallow ScrollView to intercept touch events.
v.getParent().requestDisallowInterceptTouchEvent(true);
scaleGestureDetector.onTouchEvent(event);
break;
case MotionEvent.ACTION_MOVE:
// Disallow ScrollView to intercept touch events.
v.getParent().requestDisallowInterceptTouchEvent(true);
scaleGestureDetector.onTouchEvent(event);
break;
case MotionEvent.ACTION_UP:
// Allow ScrollView to intercept touch events.
v.getParent().requestDisallowInterceptTouchEvent(false);
break;
}
}
return true;
}
});
}
The answer from here has the problem when text is resized even fingers are static (two fingers on the screen). What I did is add a check so that the textSize do not make any changes instantly.
private float safe;
public class simpleOnScaleGestureListener extends SimpleOnScaleGestureListener {
#Override
public boolean onScale(ScaleGestureDetector detector) {
// TODO Auto-generated method stub
float size = tv.getTextSize();
Log.d("TextSizeStart", String.valueOf(size));
//float factor = detector.getScaleFactor();
float factor = Math.max(0.5f, Math.min(detector.getScaleFactor(), 2f));
Log.d("Factor", String.valueOf(factor));
float product = size*factor;
Log.d("TextSize", String.valueOf(product));
safe = Math.abs(product - size);
if(product <= 100 && product >= 20 && safe < 3){
//tv.setText("factor= " +factor + "\n" + "product = \n" + size + " * " + factor + " \n= " + product +"\n" + getString(R.string.hello_world));
tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, product);
}
size = tv.getTextSize();
Log.d("TextSizeEnd", String.valueOf(size));
return true;
}
}
You can play around with safe < 3 to your desired changes value.
I'm using this solution.
Crédits for Zoom Algorithm in this vídeo
Use a TextView without ScrollView, just use android:scrollbars="vertical"
<TextView
android:id="#+id/activity_content_text_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_weight="1"
android:gravity="fill"
android:textSize="8pt"
android:scrollbars="vertical"
/>
Java:
public class MainActivity extends Activity implements View.OnTouchListener {
private TextView textContent = null;
private final static float move = 200;
private float ratio = 1.0f;
private int baseDist;
private float baseRatio;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.teste_layout);
textContent = findViewById(R.id.activity_content_text_content);
textContent.setText("Lorem ipsum dolor sit amet......");
textContent.setMovementMethod(new ScrollingMovementMethod());
textContent.setOnTouchListener(this);
}
#Override
public boolean onTouch(View v, MotionEvent event) {
return onTouchEvent(event);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getPointerCount() == 2){
int action = event.getAction();
int mainAction = action&MotionEvent.ACTION_MASK;
if(mainAction == MotionEvent .ACTION_POINTER_DOWN){
baseDist = getDisTance(event);
baseRatio = ratio;
} else {
float scale = (getDisTance(event)-baseDist)/move;
float factor = (float)Math.pow(2, scale);
ratio = Math.min(1024.0f, Math.max(0.1f, baseRatio*factor));
textContent.setTextSize(ratio+15);
}
} else {
return false;
}
return true;
}
private int getDisTance(MotionEvent event) {
int dx = (int) (event.getX(0)-event.getX(1));
int dy = (int) (event.getY(0)-event.getY(1));
return (int) (Math.sqrt(dx*dx+dy*dy));
}
}

how to set default image size in image view with zoom in zoom out?

I am using horizontal scrollview, and when I am clicking on the image buttom of horizontal scrollview, then my image is showing in the imageview. This functionality is working properly.
And in the image view I am able to zoom the image. But after zooming, when I am clicking on the next image button of scrollview then, imageview bydefault showing zoomed image. Actually it is taking zoom of previous image. So my problem is that how can I remove previous zoom, for next image. I mean next image must come with default size, not already zoomed.
Here is my code.
public class ViewButtonActivity extends Activity implements OnClickListener,
OnTouchListener {
ImageView imgView;
private ProgressDialog pDialog;
public static boolean isTouch = false;
ImageButton imgButton1, imgButton2, imgButton3, imgButton4, imgButton5;
HorizontalScrollView horizontalScrollView;
public ImageLoader imageLoader;
public static String[] imageUrl = {
"http://0-03/_cover.jpg",
"http://www.magazine.jpg",
"http://large_1.jpg",
"http://4.bp.Apr2011.jpg",
"http://www.theof.com/git.jpg" };
private int mImageHeight, mImageWidth;
private static final String TAG = "Touch";
private static final float MIN_ZOOM = 1f, MAX_ZOOM = 1f;
Matrix matrix = new Matrix();
Matrix savedMatrix = new Matrix();
static final int NONE = 0;
static final int DRAG = 1;
static final int ZOOM = 2;
int mode = NONE;
PointF start = new PointF();
PointF mid = new PointF();
float oldDist = 1f;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view_button_click_activity);
imageLoader = new ImageLoader(getApplicationContext());
imgView = (ImageView) findViewById(R.id.image_view);
imgButton1 = (ImageButton) findViewById(R.id.imageButton1);
imgButton2 = (ImageButton) findViewById(R.id.imageButton2);
imgButton3 = (ImageButton) findViewById(R.id.imageButton3);
imgButton4 = (ImageButton) findViewById(R.id.imageButton4);
imgButton5 = (ImageButton) findViewById(R.id.imageButton5);
horizontalScrollView = (HorizontalScrollView) findViewById(R.id.horizontal_scroll_view);
imageLoader.DisplayImage(imageUrl[0], imgButton1);
imageLoader.DisplayImage(imageUrl[1], imgButton2);
imageLoader.DisplayImage(imageUrl[2], imgButton3);
imageLoader.DisplayImage(imageUrl[3], imgButton4);
imageLoader.DisplayImage(imageUrl[4], imgButton5);
imgButton1.setOnClickListener(this);
imgButton2.setOnClickListener(this);
imgButton3.setOnClickListener(this);
imgButton4.setOnClickListener(this);
imgButton5.setOnClickListener(this);
mImageHeight = imgView.getWidth();
mImageWidth = imgView.getHeight();
imgView.setOnTouchListener(this);
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.imageButton1:
imageLoader.DisplayImage(imageUrl[0], imgView);
break;
case R.id.imageButton2:
imageLoader.DisplayImage(imageUrl[1], imgView);
break;
case R.id.imageButton3:
imageLoader.DisplayImage(imageUrl[2], imgView);
break;
case R.id.imageButton4:
imageLoader.DisplayImage(imageUrl[3], imgView);
break;
case R.id.imageButton5:
imageLoader.DisplayImage(imageUrl[4], imgView);
// imgView.setImageResource(R.drawable.img5);
break;
}
}
public boolean onTouch(View v, MotionEvent event) {
ImageView imgView = (ImageView) v;
imgView.setScaleType(ImageView.ScaleType.MATRIX);
float scale;
dumpEvent(event);
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: // first finger down only
savedMatrix.set(matrix);
start.set(event.getX(), event.getY());
Log.d(TAG, "mode=DRAG"); // write to LogCat
mode = DRAG;
break;
case MotionEvent.ACTION_UP: // first finger lifted
case MotionEvent.ACTION_POINTER_UP: // second finger lifted
mode = NONE;
Log.d(TAG, "mode=NONE");
break;
case MotionEvent.ACTION_POINTER_DOWN: // first and second finger down
oldDist = spacing(event);
Log.d(TAG, "oldDist=" + oldDist);
if (oldDist > 5f) {
savedMatrix.set(matrix);
midPoint(mid, event);
mode = ZOOM;
Log.d(TAG, "mode=ZOOM");
}
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
matrix.set(savedMatrix);
matrix.postTranslate(event.getX() - start.x, event.getY()
- start.y); // create the transformation in the matrix
// of points
} else if (mode == ZOOM) {
// pinch zooming
float newDist = spacing(event);
Log.d(TAG, "newDist=" + newDist);
if (newDist > 5f) {
matrix.set(savedMatrix);
scale = newDist / oldDist; // setting the scaling of the
// matrix...if scale > 1 means
// zoom in...if scale < 1 means
// zoom out
matrix.postScale(scale, scale, mid.x, mid.y);
}
}
break;
}
imgView.setImageMatrix(matrix);
return true;
}
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);
}
private void dumpEvent(MotionEvent event)
{
String names[] = { "DOWN", "UP", "MOVE", "CANCEL", "OUTSIDE","POINTER_DOWN", "POINTER_UP", "7?", "8?", "9?" };
StringBuilder sb = new StringBuilder();
int action = event.getAction();
int actionCode = action & MotionEvent.ACTION_MASK;
sb.append("event ACTION_").append(names[actionCode]);
if (actionCode == MotionEvent.ACTION_POINTER_DOWN || actionCode == MotionEvent.ACTION_POINTER_UP)
{
sb.append("(pid ").append(action >> MotionEvent.ACTION_POINTER_ID_SHIFT);
sb.append(")");
}
sb.append("[");
for (int i = 0; i < event.getPointerCount(); i++)
{
sb.append("#").append(i);
sb.append("(pid ").append(event.getPointerId(i));
sb.append(")=").append((int) event.getX(i));
sb.append(",").append((int) event.getY(i));
if (i + 1 < event.getPointerCount())
sb.append(";");
}
sb.append("]");
Log.d("Touch Events ---------", sb.toString());
}
}
Presumably you have to reset to the original value of the Matrix which contains the current state of the transformation (which includes zoom)? I see you already keep track of the Matrix, what's standing in your way resetting it to the old value when you advance to the next image during onClick()?

How does pinch zoom work with panning for image in Android

Goal
An activity is made to view image, we can pinch zoom or pan the image. The image is centered in the screen in the beginning. Pinch zoom is centered at the center of the image, even after the image is panned somewhere else in the screen.
The image for displaying is downloaded from a given URL, and the URL is passed from extra of an intent to start the image viewing activity.
Pinch zoom is implemented by postScale(), pan by postTranslate().
Problem
After panning the image somewhere, the pinch-zoom center is still at the center of the screen. Tried to follow the center of the image when it's been moved to a new place but my code doesn't work that way. Please give some idea.
The image downloading and panning work well.
Code
activity_image_viewer_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:background="#color/MyPureBlack" >
<LinearLayout
android:id="#+id/progressbar_wrapper"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<ProgressBar
android:id="#+id/progressbar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:max="100"
android:progress="0"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_gravity="center" >
</ProgressBar>
</LinearLayout>
<ImageView
android:id="#+id/image_viewer"
android:visibility="gone"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#color/MyPureBlack"
android:scaleType="matrix" >
</ImageView>
</LinearLayout>
</FrameLayout>
ActivityImageViewer.java
package com.com2us.hubapp.android;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLConnection;
import org.apache.http.util.ByteArrayBuffer;
import android.app.Activity;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.FloatMath;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.animation.AlphaAnimation;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
public class ActivityImageViewer extends Activity {
File imageFile = null;
// Matrices for pinch zoom and pan
Matrix matrix = new Matrix();
Matrix savedMatrix = new Matrix();
Matrix savedMatrixZoom = new Matrix();
// State of motion event
static final int NONE = 0;
static final int PAN = 1;
static final int PINCH_ZOOM = 2;
int mode = NONE;
// The first pointer down
PointF start = new PointF();
// The center of the image (Failed to track it when the image has been moved)
PointF centerOfImage = new PointF();
// oldest is the Cartesian distance between first two pointers when the second pointer is down
float oldDist = 1f;
// MIN_SCALE/MAX_SCALE is the min/max scale factor
private final float MIN_SCALE = 0.5f;
private final float MAX_SCALE = 3.0f;
// TOUCH_SENSITIVE is the minimum Cartesian distance between the first two pointers that triggers the pinch zoom
private final float TOUCH_SENSITIVE = 10.0f;
private final float SPACING_LEFT_AND_RIGHT = 30.0f;
private final float SPACING_TOP_AND_BOTTOM = 30.0f;
// The ImageView widget
private ImageView image_viewer;
// The progress bar shows what current progress is before the image downloading is completed
private ProgressBar progressbar;
private LinearLayout progressbar_wrapper;
// An async task that downloads the image from a given URL
private DownloadFilesTask downloadFilesTask;
private class DownloadFilesTask extends AsyncTask<String, Integer, Bitmap> {
protected Bitmap doInBackground(String... urls) {
InputStream input = null;
OutputStream output = null;
try {
URL url = new URL(urls[0]);
URLConnection connection = url.openConnection();
connection.connect();
int lenghtOfFile = connection.getContentLength();
// download the file
InputStream is = connection.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is, 8190);
ByteArrayBuffer baf = new ByteArrayBuffer(50);
int current = 0;
while ((current = bis.read()) != -1) {
baf.append((byte)current);
}
byte[] imageData = baf.toByteArray();
Bitmap bmp = BitmapFactory.decodeByteArray(imageData, 0, imageData.length);
//final int percent = (int) (total * 100 / lenghtOfFile);
//publishProgress(percent);
//lenghtOfFile
return bmp;
} catch (Exception e) {
} finally {
try {
if (output != null)
output.close();
output = null;
} catch (IOException e) {
}
try {
if (input != null)
input.close();
input = null;
} catch (IOException e) {
}
}
return null;
} // protected Bitmap doInBackground(String... urls) {}
protected void onProgressUpdate(Integer... progress) {
progressbar.setProgress(progress[0]);
}
protected void onPostExecute(Bitmap bmp) {
if (bmp != null) {
final AlphaAnimation animationAfter = new AlphaAnimation(0.0f, 1.0f);
animationAfter.setDuration(300);
animationAfter.setFillEnabled(true);
animationAfter.setFillAfter(true);
image_viewer.setAnimation(animationAfter);
image_viewer.setImageBitmap(bmp);
ViewTreeObserver viewTreeObserver = image_viewer.getViewTreeObserver();
viewTreeObserver.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
Drawable drawable = image_viewer.getDrawable();
int dx = (image_viewer.getWidth() - drawable.getIntrinsicWidth()) / 2;
int dy = (image_viewer.getHeight() - drawable.getIntrinsicHeight()) / 2;
matrix.postTranslate(dx, dy);
image_viewer.setImageMatrix(matrix);
}
});
progressbar_wrapper.setVisibility(View.GONE);
image_viewer.setVisibility(View.VISIBLE);
} else {
android.os.Handler handler = new android.os.Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
finish();
}
}, 2000);
}
} // End of protected void onPostExecute(Bitmap bmp) {}
} // End of private class DownloadFilesTask extends AsyncTask<String, Integer, Bitmap> {}
// These are activity life cycle handling
// onCreate
#Override
public void onCreate(Bundle savedInstanceState) {
//setTheme(R.style.HubTheme);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image_viewer);
progressbar_wrapper = (LinearLayout) findViewById(R.id.progressbar_wrapper);
image_viewer = (ImageView) findViewById(R.id.image_viewer);
progressbar = (ProgressBar) findViewById(R.id.progressbar);
image_viewer.setOnTouchListener(new MyOnTouchListener());
final String uriForImage = getIntent().getStringExtra("url");
downloadFilesTask = new DownloadFilesTask();
downloadFilesTask.execute(uriForImage);
}
// onStart
#Override
protected void onStart() {
super.onStart();
}
// onResume
#Override
protected void onResume() {
super.onResume();
}
// onPause
#Override
protected void onPause() {
super.onPause();
}
// onStop
#Override
protected void onStop() {
super.onStop();
}
// onRestart
#Override
protected void onRestart() {
super.onRestart();
}
// onDestroy
#Override
protected void onDestroy() {
super.onDestroy();
if (imageFile != null) {
try {
Drawable drawable = image_viewer.getDrawable();
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
Bitmap bitmap = bitmapDrawable.getBitmap();
bitmap.recycle();
drawable = null;
bitmapDrawable = null;
bitmap = null;
} catch (NullPointerException e) {
}
}
}
// onKeyDown
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
this.onBackPressed();
}
return true;
}
// onBackPressed
public void onBackPressed() {
finish();
}
// onConfigurationChanged
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.equals(Configuration.ORIENTATION_LANDSCAPE)) {
} else if (newConfig.equals(Configuration.ORIENTATION_PORTRAIT)) {
}
}
// onLowMemory
#Override
public void onLowMemory() {
super.onLowMemory();
finish();
}
// Get the Cartesian distance between the first two pointers
private float spacing(MotionEvent event) {
float x = 0;
float y = 0;
try {
Method getX = MotionEvent.class.getMethod("getX", Integer.TYPE);
Method getY = MotionEvent.class.getMethod("getX", Integer.TYPE);
// x = event.getX(0) - event.getX(1);
// y = event.getY(0) - event.getY(1);
float x1 = (Float) getX.invoke(event, 0);
float x2 = (Float) getX.invoke(event, 1);
x = x1 - x2;
float y1 = (Float) getY.invoke(event, 0);
float y2 = (Float) getY.invoke(event, 1);
y = y1 - y2;
} catch (SecurityException e) {
} catch (NoSuchMethodException e) {
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
}
return FloatMath.sqrt(x * x + y * y);
}
// Some flags set manually for convenience
private final int MotionEvent_ACTION_MASK = 255; // that is 0xFF or 11111111
private final int MotionEvent_ACTION_POINTER_DOWN = 5; // that is 101
private final int MotionEvent_ACTION_POINTER_UP = 6; // that is 110
private class MyOnTouchListener implements OnTouchListener {
// onTouch
#Override
public boolean onTouch(View v, MotionEvent event) {
ImageView view = (ImageView) v;
Drawable drawable = view.getDrawable();
if (drawable == null)
return true;
switch (event.getAction() & MotionEvent_ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
savedMatrix.set(matrix);
start.set(event.getX(), event.getY());
mode = PAN;
break;
case MotionEvent_ACTION_POINTER_DOWN:
oldDist = spacing(event);
if (oldDist > TOUCH_SENSITIVE) {
savedMatrix.set(matrix);
mode = PINCH_ZOOM;
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent_ACTION_POINTER_UP:
mode = NONE;
break;
case MotionEvent.ACTION_MOVE:
if (mode == PAN) {
// /////////////////////////////////////////
matrix.set(savedMatrix);
float[] matrixValues = new float[9];
Rect viewRect = new Rect(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
matrix.getValues(matrixValues);
float currentY = matrixValues[Matrix.MTRANS_Y];
float currentX = matrixValues[Matrix.MTRANS_X];
float currentScale = matrixValues[Matrix.MSCALE_X];
float currentHeight = drawable.getIntrinsicHeight() * currentScale;
float currentWidth = drawable.getIntrinsicWidth() * currentScale;
float dx = event.getX() - start.x;
float dy = event.getY() - 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) - SPACING_TOP_AND_BOTTOM;
float diffDown = Math.max(viewRect.bottom - drawingRect.bottom, viewRect.top - drawingRect.top) + SPACING_TOP_AND_BOTTOM;
float diffLeft = Math.min(viewRect.left - drawingRect.left, viewRect.right - drawingRect.right) - SPACING_LEFT_AND_RIGHT;
float diffRight = Math.max(viewRect.left - drawingRect.left, viewRect.right - drawingRect.right) + SPACING_LEFT_AND_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);
} else if (mode == PINCH_ZOOM) {
float newDist = spacing(event);
if (newDist > TOUCH_SENSITIVE) {
matrix.set(savedMatrix);
float scale = newDist / oldDist;
// Get the center of the image. (Failed to get it when image has been moved)
Rect viewRect = new Rect(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
centerOfImage.x = viewRect.centerX();
centerOfImage.y = viewRect.centerY();
float[] f = new float[9];
Matrix tmp = new Matrix(matrix);
tmp.postScale(scale, scale, centerOfImage.x, centerOfImage.y);
tmp.getValues(f);
float scaleX = f[Matrix.MSCALE_X];
if (scaleX < MIN_SCALE || scaleX > MAX_SCALE) {
matrix.set(savedMatrixZoom);
} else {
matrix.postScale(scale, scale, centerOfImage.x, centerOfImage.y);
savedMatrixZoom.set(matrix);
}
}
}
break;
}
view.setImageMatrix(matrix);
return true;
} // End of public boolean onTouch(View v, MotionEvent event) {}
} // End of private class MyOnTouchListener implements OnTouchListener {}
} // End of public class ActivityImageViewer extends Activity {}
You can use the Scale Gesture Detector for pinch to zoom. Instead of creating pinch to zoom from scratch you can do something like following,
public class MyCustomView extends View {
private ScaleGestureDetector mScaleDetector;
private float mScaleFactor = 1.f;
public MyCustomView(Context mContext){
...
// View code goes here
...
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
// Let the ScaleGestureDetector inspect all events.
mScaleDetector.onTouchEvent(ev);
return true;
}
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
canvas.scale(mScaleFactor, mScaleFactor);
...
// onDraw() code goes here
...
canvas.restore();
}
private class ScaleListener
extends ScaleGestureDetector.SimpleOnScaleGestureListener {
#Override
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor *= detector.getScaleFactor();
// Don't let the object get too small or too large.
mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));
invalidate();
return true;
}
}
}
Note : Your translation will reside in onDraw method to scale an image.

Categories