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.
Related
I want to drag, zoom and rotate Bitmap with two fingers (onTouchEvent) but unable to find any solution. There are many solutions to drag, zoom and rotate imageview but no solution for bitmap.
Need help, Thanks
U can detect touch gesture and applied them to the bitmap through matrix.
Defined the scale type : ImageView.setImageMatrix(Matrix)
Detect gesture from any view that U want
Use matrix translation for dragging and rotation and matrix scale for zooming using the values that U got in touch event.
BTW there is gesture helper U can use for simplify your work
https://developer.android.com/training/gestures/detector
Below is the solution to Drag, Rotate and Zoom
public class MainActivity extends BaseActivity implements OnTouchListener {
// these matrices will be used to move and zoom image
private Matrix matrix = new Matrix();
private Matrix savedMatrix = new Matrix();
// we can be in one of these 3 states
private static final int NONE = 0;
private static final int DRAG = 1;
private static final int ZOOM = 2;
private int mode = NONE;
private PointF start = new PointF();
private PointF mid = new PointF();
private float oldDist = 1f;
private float d = 0f;
private float newRot = 0f;
private float[] lastEvent = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ImageView view = (ImageView) findViewById(R.id.imageView);
view.setOnTouchListener(this);
}
public boolean onTouch(View v, MotionEvent event) {
// handle touch events here
ImageView view = (ImageView) v;
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
savedMatrix.set(matrix);
start.set(event.getX(), event.getY());
mode = DRAG;
lastEvent = null;
break;
case MotionEvent.ACTION_POINTER_DOWN:
oldDist = spacing(event);
if (oldDist > 10f) {
savedMatrix.set(matrix);
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:
mode = NONE;
lastEvent = null;
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
matrix.set(savedMatrix);
float dx = event.getX() - start.x;
float dy = event.getY() - start.y;
matrix.postTranslate(dx, dy);
} 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);
}
if (lastEvent != null && event.getPointerCount() == 2) {
newRot = rotation(event);
float r = newRot - d;
float[] values = new float[9];
matrix.getValues(values);
float tx = values[0];
float ty = values[4];
float sx = values[8];
float xc = (view.getWidth() / 2) * sx;
float yc = (view.getHeight() / 2) * sx;
matrix.postRotate(r, tx + xc, ty + yc);
}
}
break;
}
view.setImageMatrix(matrix);
return true;
}
/**
* 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);
}
/**
* Calculate the degree to be rotated by.
*
* #param event
* #return Degrees
*/
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);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK && requestCode == UCrop.REQUEST_CROP) {
final Uri resultUri = UCrop.getOutput(data);
} else if (resultCode == UCrop.RESULT_ERROR) {
final Throwable cropError = UCrop.getError(data);
}
}
public void clickedListener(View view) {
startActivity(new Intent(MainActivity.this, CropActivity.class));
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:background="#android:color/transparent"
android:layout_height="match_parent" >
<ImageView android:id="#+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
android:src="#android:drawable/btn_radio"
android:scaleType="matrix" />
<ImageView android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
android:src="#android:drawable/gallery_thumb"
android:onClick="clickedListener"
android:layout_gravity="bottom"
android:scaleType="centerInside" >
</ImageView>
This is My Touch Listener Class:
public class Touch_Listner implements OnTouchListener{
// these matrices will be used to move and zoom image
private Matrix matrix = new Matrix();
private Matrix savedMatrix = new Matrix();
// we can be in one of these 3 states
private static final int NONE = 0;
private static final int DRAG = 1;
private static final int ZOOM = 2;
private int mode = NONE;
// remember some things for zooming
private PointF start = new PointF();
private PointF mid = new PointF();
private float oldDist = 1f;
private float d = 0f;
private float newRot = 0f;
private float[] lastEvent = null;
public boolean onTouch(View v, MotionEvent event) {
// handle touch events here
ImageView view = (ImageView) v;
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
savedMatrix.set(matrix);
start.set(event.getX(), event.getY());
mode = DRAG;
lastEvent = null;
break;
case MotionEvent.ACTION_POINTER_DOWN:
oldDist = spacing(event);
if (oldDist > 10f) {
savedMatrix.set(matrix);
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:
mode = NONE;
lastEvent = null;
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
matrix.set(savedMatrix);
float dx = event.getX() - start.x;
float dy = event.getY() - start.y;
matrix.postTranslate(dx, dy);
} 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);
}
if (lastEvent != null && event.getPointerCount() == 3) {
newRot = rotation(event);
float r = newRot - d;
float[] values = new float[9];
matrix.getValues(values);
float tx = values[2];
float ty = values[5];
float sx = values[0];
float xc = (view.getWidth() / 2) * sx;
float yc = (view.getHeight() / 2) * sx;
matrix.postRotate(r, tx + xc, ty + yc);
}
}
break;
}
view.setImageMatrix(matrix);
return true;
}
/**
* 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 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) + event.getX(1);
float y = event.getY(0) + event.getY(1);
point.set(x / 2, y / 2);
}
/**
* Calculate the degree to be rotated by.
*
* #param event
* #return Degrees
*/
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);
}
}
}
Create Dynamic Imageview using following method:
private void Add_Imageview(final String btn_id,Bitmap resource) {
ImageView image = new ImageView(this);
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.FILL_PARENT,
FrameLayout.LayoutParams.FILL_PARENT);
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth(); // deprecated
int height = display.getHeight(); // deprecated
image.setScaleType(ImageView.ScaleType.MATRIX);
image.setImageBitmap(resource);
image.setTag(btn_id);
image.setId(imgview_index);
rel_image.addView(image);
image.getLayoutParams().height = rel_image.getHeight();
image.getLayoutParams().width = rel_image.getWidth();
int[] values = new int[2];
image.getLocationOnScreen(values);
System.out.println("x location::"+values[0]);
System.out.println(" y location::"+values[1]);
image.setOnTouchListener(new Touch_Listner());
}
when I call this method more than once it Drag only recently added Imageview i want to move rotate zoom any imageview any time
you can try this code https://github.com/siddhpuraamitr/MultitouchWithDynamicAddandRemove for your project...
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 am new in Android. I am working on opengl for 2 weeks and now stucked at one point. I am able to drag the 3d image at single finger touch and zoom in/out with 2 finger touch. But after one touch, when Second time start to zoom then it is not rendering the image from the previous state but it is first zooming the 3d object and then start zoom in/out.
Here is my code. Plz have a look on it..
public class AnimateActivity extends RendererActivity
{
Object3dContainer objModel;
// touch events
private final int NONE = 0;
private final int DRAG = 0;
private final int ZOOM = 0;
// pinch to zoom
float oldDist = 100.0f;
float newDist;
int mode = 0;
private float mPreviousX;
private float mPreviousY;
private final float TOUCH_SCALE_FACTOR = 180.0f / 320;
private GLSurfaceView mGLSurfaceView;
Renderer renderer;
#Override
public void initScene() {
scene.lights().add(new Light());
IParser parser = Parser.createParser(Parser.Type.OBJ,
getResources(),"com.example.magic3d:raw/camaro_obj", true);
parser.parse();
//mGLSurfaceView=new GLSurfaceView(this);
objModel = parser.getParsedObject();
// objModel.scale().x = objModel.scale().y = objModel.scale().z = .8f;
objModel.scale().x = objModel.scale().y = objModel.scale().z = .8f;
scene.addChild(objModel);
scene.backgroundColor().setAll(Color.WHITE);
renderer=new Renderer(scene);
}
#Override
public void updateScene() {
/*objModel.rotation().x++;
objModel.rotation().z++;*/
}
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
mGLSurfaceView=new GLSurfaceView(this);
}
#Override public boolean onTouchEvent(MotionEvent e) {
float x = e.getX();
float y = e.getY();
switch (e.getAction()) {
case MotionEvent.ACTION_DOWN: // one touch: drag
Log.d("ShaderActivity", "mode=DRAG" );
System.out.println("Action Down");
mode = DRAG;
break;
case MotionEvent.ACTION_POINTER_DOWN: // two touches: zoom
Log.d("ShaderActivity", "mode=ZOOM" );
System.out.println("Action zoom");
oldDist = spacing(e);
if (oldDist > 10.0f) {
mode = ZOOM; // zoom
}
break;
case MotionEvent.ACTION_UP: // no mode
mode = NONE;
System.out.println("Action up");
Log.d("ShaderActivity", "mode=NONE" );
oldDist = 100.0f;
break;
case MotionEvent.ACTION_POINTER_UP: // no mode
mode = NONE;
Log.d("ShaderActivity", "mode=NONE" );
oldDist = 100.0f;
break;
case MotionEvent.ACTION_MOVE:
System.out.println("Action Move");
// rotation
if (e.getPointerCount() > 1 && mode == ZOOM) {
newDist = spacing(e);
Log.d("SPACING: ", "OldDist: " + oldDist + ", NewDist: " + newDist);
if (newDist > 15.0f) {
float scale = newDist/oldDist; // scale
// scale in the renderer
renderer.changeScale(scale);
objModel.scale().x =renderer.scaleX;
objModel.scale().y = renderer.scaleY ;
objModel.scale().z =renderer.scaleZ;
oldDist = newDist;
}
}
else if (mode == DRAG){
float dx = x - mPreviousX;
float dy = y - mPreviousY;
renderer.mAngleX += dx * TOUCH_SCALE_FACTOR;
renderer.mAngleY += dy * TOUCH_SCALE_FACTOR;
//mGLSurfaceView.requestRender();
updateScene();
objModel.rotation().x=renderer.mAngleY;
objModel.rotation().y=renderer.mAngleX;
// objModel.rotation().z=
//Toast.makeText(getApplicationContext(), "action move downl", Toast.LENGTH_SHORT).show();
// updateScene();
}
}
mPreviousX = x;
mPreviousY = y;
return true;
}
// finds spacing
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);
}
}
Thanks....
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