In my program can I move image across screen? Sometimes I am loosing it from site and cannot find it. I wish to add function which will place imag on original position.
My own aproach wich does not work (and related question to it to make it work):
ImageView iv = current;
Matrix matrix = iv.getImageMatrix;
float[] values = new float[9];
matrix.getValues(values);
int a = values[Matrix.MTRANS_X];
int b = values[Matrix.MTRANS_Y];
matrix.postTranslate(-a,-b);
iv.setImageMatrix(matrix);
EDIT: Latest code
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ExecutionException;
import ua.mirkvartir.android.frontend.UILApplication;
import android.app.Activity;
import android.app.Fragment;
import android.app.ProgressDialog;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.graphics.drawable.BitmapDrawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.view.MotionEventCompat;
import android.util.FloatMath;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.Gallery;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
public class ImageShowActivity extends Activity {
int p = 0;
Activity app;
ImageAdapterr ia;
ImageView imView;
int imgPos = 0;
Bitmap bm = null;
int geg = 90;
public int width = 0;
public int hight = 0;
Gallery gallery;
Matrix matrix = new Matrix();
Matrix shift = new Matrix();
private int INVALID_POINTER_ID = -1;
private int mActivePointerId = INVALID_POINTER_ID;
private ScaleGestureDetector mScaleDetector;
private float mLastTouchX = 0;
private float mLastTouchY = 0;
private float mPosX = 0;
private float mPosY = 0;
ImageView current;
public List<ImageView> images;
public int reset = 0;
HashMap<Integer, Bitmap> map = new HashMap<Integer, Bitmap>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.image_show);
app = this;
images = new ArrayList<ImageView>(
UILApplication.photo_buffer_big.size());
Log.d("images", UILApplication.photo_buffer_big.size() + "");
Log.d("images", images.size() + "");
gallery = (Gallery) findViewById(R.id.gallery);
// EDGES ARE INVISIBLE
gallery.setHorizontalFadingEdgeEnabled(false);
ia = new ImageAdapterr(this);
gallery.setAdapter(ia);
final int length = UILApplication.photo_buffer_big.size();
Button back_btn = (Button) findViewById(R.id.analitics_back_btn);
back_btn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
finish();
}
});
final TextView img_counter_tv = (TextView) findViewById(R.id.img_counter);
img_counter_tv.setText(p + 1 + "/" + length);
Button nextButton = (Button) findViewById(R.id.next_btn);
nextButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (p < length - 1) {
p++;
} else {
p = 0;
}
gallery.setSelection(p, true);
img_counter_tv.setText(p + 1 + "/" + length);
}
});
Button backButton = (Button) findViewById(R.id.back_btn);
backButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (p == 0) {
p = length - 1;
} else {
p--;
}
gallery.setSelection(p, true);
img_counter_tv.setText(p + 1 + "/" + length);
}
});
}
public void rotateS(View v) {
ImageView iv = current;
Bitmap b = ((BitmapDrawable) iv.getDrawable()).getBitmap();
Matrix matrix = new Matrix();
matrix.postRotate(geg);
Bitmap bMapRotate = Bitmap.createBitmap(b, 0, 0, b.getWidth(),
b.getHeight(), matrix, true);
iv.setImageBitmap(bMapRotate);
}
public void extendS(View v) {
reset = 1;
Log.d("restart", "yes");
runOnUiThread(new Runnable() {
public void run() {
View viewToUpdate = gallery.getChildAt(p - gallery.getFirstVisiblePosition());
viewToUpdate.invalidate();
// ia.notifyDataSetChanged();
}
});
}
public static Bitmap resizeBitmap(Bitmap photo, float x, float y) {
try {
// get current bitmap width and height
int width = photo.getWidth();
int height = photo.getHeight();
// determine how much to scale
float scaleWidth = x / width;
float scaleHeight = y / height;
Log.d("aspect3", "w: " + scaleWidth + " h: " + scaleHeight);
// create the matrix for the manipulation
Matrix matrix = new Matrix();
// resize the bitmap
matrix.postScale(scaleWidth, scaleHeight);
// recreate the new bitmap
Bitmap resizebitmap = Bitmap.createBitmap(photo, 0, 0, width,
height, matrix, false);
return resizebitmap;
} catch (NullPointerException e) {
e.printStackTrace();
} catch (OutOfMemoryError e) {
e.printStackTrace();
System.gc();
}
return null;
}
class ImageAdapterr extends BaseAdapter {
/** The parent context */
private Context myContext;
/** Simple Constructor saving the 'parent' context. */
public ImageAdapterr(Context c) {
this.myContext = c;
}
Matrix savedMatrix = new Matrix();
/** Returns the amount of images we have defined. */
public int getCount() {
return UILApplication.photo_buffer_big.size();
}
/* Use the array-Positions as unique IDs */
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
/**
* Returns a new ImageView to be displayed, depending on the position
* passed.
*/
public View getView(final int position, View convertView,
ViewGroup parent) {
ImageView imView = new ImageView(this.myContext);
current = imView;
imgPos = position;
if (bm==null){
AsyncLoad imLoad = new AsyncLoad();
imLoad.execute();
try {
bm = imLoad.get();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (bm != null) {
imView.setImageBitmap(bm);
} else if (bm == null) {
imView.setImageResource(R.drawable.logo);
}
/* Image should be scaled as width/height are set. */
imView.setScaleType(ImageView.ScaleType.FIT_CENTER);
/* Set the Width/Height of the ImageView. */
imView.setLayoutParams(new Gallery.LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
imView.setOnTouchListener(new OnTouchListener() {
private static final String TAG = "Touch";
// These matrices will be used to move and zoom image
PointF start = new PointF();
public PointF mid = new PointF();
// We can be in one of these 3 states
public static final int NONE = 0;
public static final int DRAG = 1;
public static final int ZOOM = 2;
public int mode = NONE;
float oldDist;
public boolean onTouch(View v, MotionEvent event) {
ImageView view = (ImageView) v;
view.setScaleType(ImageView.ScaleType.MATRIX);
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
savedMatrix.set(matrix);
start.set(event.getX(), event.getY());
Log.d(TAG, "mode=DRAG");
mode = DRAG;
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");
}
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);
Log.d(TAG, "newDist=" + newDist);
if (newDist > 10f) {
matrix.set(savedMatrix);
float scale = newDist / oldDist;
matrix.postScale(scale, scale, mid.x, mid.y);
}
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
Log.d(TAG, "mode=NONE");
break;
}
// Perform the transformation
Log.d("point",
(event.getX() - start.x) + " "
+ (event.getY() - start.y));
// Log.d("point",start.x +" "+start.y);
float[] values = new float[9];
matrix.getValues(values);
float a = values[Matrix.MTRANS_X];
float b = values[Matrix.MTRANS_Y];
Log.d("touch matrix", values[Matrix.MPERSP_0] + " "
+ values[Matrix.MPERSP_1] + " "
+ values[Matrix.MPERSP_2]);
Log.d("touch matrix scale", values[Matrix.MSCALE_X] + " "
+ values[Matrix.MSCALE_Y]);
Log.d("touch matrix scew", values[Matrix.MSKEW_X] + " "
+ values[Matrix.MSKEW_Y]);
Log.d("touch matrix trans", values[Matrix.MTRANS_X] + " "
+ values[Matrix.MTRANS_Y]);
if (reset == 1) {
matrix.reset();
savedMatrix.reset();
}
view.setImageMatrix(matrix);
reset = 0;
// images.set(position, view);
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);
}
});
return imView;
}
/**
* Returns the size (0.0f to 1.0f) of the views depending on the
* 'offset' to the center.
*/
public float getScale(boolean focused, int offset) {
/* Formula: 1 / (2 ^ offset) */
return Math.max(0, 1.0f / (float) Math.pow(2, Math.abs(offset)));
}
}
class AsyncLoad extends AsyncTask<Void, Void, Bitmap> {
ProgressDialog pd;
#Override
protected void onPreExecute() {
pd = new ProgressDialog(app);
pd.setOwnerActivity(app);
pd.setTitle("Идет загрузка...");
pd.setCancelable(true);
pd.show();
}
#Override
protected Bitmap doInBackground(Void... arg0) {
// TODO Auto-generated method stub
try {
/*
* Open a new URL and get the InputStream to load data from it.
*/
URL aURL = new URL(UILApplication.photo_buffer_big.get(imgPos));
URLConnection conn = aURL.openConnection();
conn.connect();
InputStream is = conn.getInputStream();
/* Buffered is always good for a performance plus. */
BufferedInputStream bis = new BufferedInputStream(is);
/* Decode url-data to a bitmap. */
bm = BitmapFactory.decodeStream(bis);
bis.close();
is.close();
/* Apply the Bitmap to the ImageView that will be returned. */
// imView.setImageBitmap(bm);
} catch (IOException e) {
// imView.setImageResource(R.drawable.logo);
bm = null;
Log.e("DEBUGTAG", "Remote Image Exception", e);
}
map.put(imgPos, bm);
Log.d("map", map.size() + "");
return bm;
}
#Override
protected void onPostExecute(Bitmap arg0) {
pd.dismiss();
}
}
}
XML
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#drawable/top_tab_bg"
android:padding="10dp" >
<Button
android:id="#+id/analitics_back_btn"
style="#style/ButtonText"
android:layout_marginRight="5dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="#+id/back_btn"
android:background="#drawable/btn_clk_selector"
android:text="Назад" />
<Button
android:id="#+id/btn_rotate"
style="#style/ButtonText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dip"
android:layout_toLeftOf="#+id/analitics_back_btn"
android:background="#drawable/btn_clk_selector"
android:onClick="rotateS"
android:text="Повернуть" />
<Button
android:id="#+id/btn_ex"
style="#style/ButtonText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dip"
android:layout_toLeftOf="#+id/btn_rotate"
android:background="#drawable/btn_clk_selector"
android:onClick="extendS"
android:text="рас" />
<Button
android:id="#+id/next_btn"
style="#style/ButtonText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginLeft="5dp"
android:background="#drawable/next_img_btn"
android:paddingRight="10dp" />
<TextView
android:id="#+id/img_counter"
style="#style/ButtonText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toLeftOf="#+id/next_btn"
android:text="1/10" />
<Button
android:id="#+id/back_btn"
style="#style/ButtonText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
android:layout_toLeftOf="#+id/img_counter"
android:background="#drawable/back_img_btn" />
</RelativeLayout>
<RelativeLayout
android:id="#+id/gal"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<Gallery
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/gallery"
android:adjustViewBounds="true"
android:spacing="10dp"
/>
</RelativeLayout>
</LinearLayout>
EDIT: problem with new code - image is not rested after enlargeS was called. It is reseted after enlargeS call + tab on screen. Also image is partially reseted - it goes to original position and scale, but it goes to its original resolution. So usually i bacamos much smaller then screen, while i need it to fill screen.
Use the code here below:
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image);
RelativeLayout layout = (RelativeLayout) findViewById(R.id.layout);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
imageView = new ImageView(this);
imageView.setLayoutParams(params);
imageView.setImageBitmap(bitmap);
layout.setGravity(Gravity.CENTER_VERTICAL | Gravity.TOP);
layout.addView(imageView);
This will position the ImageView at the center of the RelativeLayout which contains it.
EDIT: see in the code above - I changed the RelativeLayout.LayoutParams to LinearLayout.LayoutParams, because it is the LinearLayout, which contains the RelativeLayout in fact. Now it should work.
Try to use this in your code to set the image view wherever you want on the screen,
iconSMS.setImageResource(R.drawable.ic_launcher_smsmms);
LayoutParams paramsIconSMS = new LayoutParams(iconwidth,iconheight);
iconwidthspacing=(int)Math.round(((float)width/480)*(float)45);
iconheightspacing=(int)Math.round(((float)height/800)*(float)520);
paramsIconSMS.setMargins(iconwidthspacing, iconheightspacing, 0, 0);
iconSMS.setId(204);
iconSMS.setLayoutParams(paramsIconSMS);
Here,
iconwidth=(int)Math.round(width*iconwidthf);
iconheight=(int)Math.round(height*iconheightf);
and width and height variables are,
requestWindowFeature(Window.FEATURE_NO_TITLE);
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
width = metrics.widthPixels;
height = metrics.heightPixels;
by width and height you are getting the screen size of your phone in pixels.
Related
Im new on Stack Overflow!, I joined here for some problem that I got right now.
Im working with Android Studio where im trying to make a type of game that it requires a grid usage to start it. At this point im trying to implement the touch event on some bitmaps, those bitmaps are the tiles of my game but im kinda of confused, in My view, where I place all of the tiles i can get all of the coordinates (including height and width) of each tile, I check those values but when I apply the touch event (On Action Down) im getting the coords of my last tile of my grid. Thats strange, because when im drawing it in my canvas Im still got the actual values (the real coords) but in touch are different, im trying to figure this but no result at all.
Can someone here tell me where i go wrong?
Sorry for my english.
PS: The grid can be dragged.
MyView.java
package com.example.sammuzero.aplicamesta;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Map;
/**
* Created by lezama on 24-07-2017.
*/
public class MyView extends SurfaceView {
Bitmap piso1;
Bitmap muro;
Bitmap queso;
SurfaceHolder aguanta;
GameLoopThread loopGame;
Terreno pintaTerreno;
Sprite mouse;
boolean scroll;
float destinyX = 0;
float destinyY = 0;
float originX = 0;
float originY = 0;
float transX = 0;
float transY = 0;
float escala = 1;
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
aguanta = getHolder();
loopGame = new GameLoopThread(this);
aguanta.addCallback(new SurfaceHolder.Callback(){
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
loopGame.setRunning(true);
loopGame.start();
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
boolean retry = true;
loopGame.setRunning(false);
while (retry) {
try {
loopGame.join();
retry = false;
} catch (InterruptedException e) {}
}
}
});
piso1 = BitmapFactory.decodeResource(getResources(), R.drawable.floor1);
muro = BitmapFactory.decodeResource(getResources(), R.drawable.pared);
queso = BitmapFactory.decodeResource(getResources(), R.drawable.kso);
pintaTerreno = new Terreno(0,0,new MapBit(piso1), new MapBit(muro));
}
public void onDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE);
canvas.scale(escala,escala);
canvas.translate((destinyX - originX), (destinyY - originY));
transX = (destinyX - originX);
transY = (destinyY - originY);
for(int i = 0; i < pintaTerreno.getAncho(); i++) {
for (int j = 0; j < pintaTerreno.getAlto(); j ++){
dibujaCasilla(i,j, canvas);
Log.i("Probando X,Y", "X: " + pintaTerreno.getCasilla(i, j).getGrafico().getX()
+ " Y: " + pintaTerreno.getCasilla(i, j).getGrafico().getY());
}
}
canvas.scale(1.0f,1.0f);
//mouse.onDraw(canvas);
}
public void queTerrenoDibujo(Terreno e)
{
pintaTerreno = e;
}
public void setEscala(int escalaATransformar) {
float nuevaEscala;
nuevaEscala = (float) escalaATransformar / 100;
escala = nuevaEscala;
}
private void dibujaCasilla(int i, int j,Canvas canvas) {
// Primero revisa si hay una pared o no alli.
if (pintaTerreno.getCasilla(i,j).getRepresenta() == 'P') {
pintaTerreno.getCasilla(i,j).getGrafico().setX(64 * i);
pintaTerreno.getCasilla(i,j).getGrafico().setY(64 * j);
pintaTerreno.getCasilla(i,j).getGrafico().onDraw(canvas);
}
else {
pintaTerreno.getCasilla(i,j).getGrafico().setX(64 * i);
pintaTerreno.getCasilla(i,j).getGrafico().setY(64 * j);
pintaTerreno.getCasilla(i,j).getGrafico().onDraw(canvas);
if(pintaTerreno.getCasilla(i,j).getRepresenta() == 'Q')
canvas.drawBitmap(queso,(64 * i) + 16, (64 * j) + 16, null);
}
/*
MapBit nuevoBloque = null;
if (pintaTerreno.getCasilla(i,j).getRepresenta() == 'P') {
nuevoBloque = new MapBit((64 * i),(64 * j),muro);
nuevoBloque.onDraw(canvas);
}
else {
nuevoBloque = new MapBit((64 * i),(64 * j),piso1);
nuevoBloque.onDraw(canvas);
if(pintaTerreno.getCasilla(i,j).getRepresenta() == 'Q')
canvas.drawBitmap(queso,(64 * i) + 16, (64 * j) + 16, null);
}
*/
// Luego, asegurate de los elementos que estan en esa casilla.
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
//return super.onTouchEvent(event);
int action = event.getAction();
if (action==MotionEvent.ACTION_MOVE){
destinyX = event.getX();
destinyY = event.getY();
}
else if (action==MotionEvent.ACTION_DOWN) {
Log.i("Probando X,Y en 0,0", "X: " + pintaTerreno.getCasilla(0, 0).getGrafico().getX()
+ " Y: " + pintaTerreno.getCasilla(0, 0).getGrafico().getY());
for (int i = 0; i < pintaTerreno.getAncho(); i++) {
for (int j = 0; j < pintaTerreno.getAlto(); j++) {
Log.i("Probando X,Y", "X: " + pintaTerreno.getCasilla(i, j).getGrafico().getX()
+ " Y: " + pintaTerreno.getCasilla(i, j).getGrafico().getY());
String msg = "X: " + pintaTerreno.getCasilla(i, j).getGrafico().getX() + " Y: " + pintaTerreno.getCasilla(i, j).getGrafico().getY();
if (pintaTerreno.getCasilla(i, j).getGrafico().isCollition(event.getX(), event.getY())) {
Toast.makeText(getContext(), msg, Toast.LENGTH_SHORT).show();
}
}
}
originX = event.getX() - transX;
originY = event.getY() - transY;
scroll = true;
}
else if (action==MotionEvent.ACTION_UP){
transX = (destinyX - originX);
transY = (destinyY - originY);
scroll = false;
}
return true;
}
}
Terreno.java (The grid)
package com.example.sammuzero.aplicamesta;
import java.util.ArrayList;
import java.util.Random;
/**
*
* #author estudiante
*/
public class Terreno {
private ArrayList<Object> todo = new ArrayList<>();
private Casilla[][] plataforma;
private int alto;
private int ancho;
public Terreno (int alt, int anch, MapBit nada, MapBit pared)
{
int i;
int j;
this.plataforma = new Casilla[alt][anch];
this.alto = alt;
this.ancho = anch;
for(i = 0; i < this.alto; i++)
for(j = 0; j < this.ancho; j++)
this.plataforma[i][j] = new Casilla(i,j, nada);
this.inicializa(pared);
}
// Getters //
public int getAlto(){return this.alto;}
public int getAncho(){return this.ancho;}
public Casilla getCasilla(int i, int j){return this.plataforma[i][j];}
public ArrayList<Object> getTodo(){return this.todo;}
// Setters //
public void setEnCasilla(int x, int y, Object o, char r){this.plataforma[x][y].setObjeto(o,r);}
// Metodos //
public void inicializa(MapBit pared)
{
int cuantos = ((this.alto*this.ancho) * 10) / 100;
Random rand = new Random();
int llevo = 0;
int sel = 0;
for(int i = 0; i < this.alto ; i++)
for(int j = 0 ; j < this.ancho; j++)
{
sel = 1+rand.nextInt(10);
if(sel == 1 && llevo < cuantos)
{
Pared nueva = new Pared(this.plataforma[i][j]);
this.plataforma[i][j].setGrafico(pared);
todo.add(nueva);
llevo ++;
}
else if (sel == 10) {
Queso nuevo = new Queso(this.plataforma[i][j]);
todo.add(nuevo);
}
}
}
}
Casilla.java (the tile)
package com.example.sammuzero.aplicamesta;
import android.support.design.widget.Snackbar;
/**
* Created by lezama on 28-07-2017.
*/
public class Casilla {
private int posX;
private int posY;
private Object contenido;
private char representa;
private MapBit grafico;
public Casilla(int i, int j, MapBit graf)
{
this.posX = i;
this.posY = j;
this.representa = '0';
contenido = null;
this.grafico = graf;
}
public int getPosX() {return this.posX;}
public int getPosY() {return this.posY;}
public char getRepresenta() {return this.representa;}
public MapBit getGrafico() {return this.grafico;}
public void setObjeto(Object item , char rep)
{
this.contenido = item;
this.representa = rep;
}
public void setGrafico (MapBit grafico1) {this.grafico = grafico1;}
/*
public void onTouch()
{
Toast.makeText(this.getContext(), "X:"+this.posX+" Y:"+this.posY, Toast.LENGTH_SHORT).show();
} */
}
MapBit.java (where it resides my Bitmap)
package com.example.sammuzero.aplicamesta;
import android.graphics.Bitmap;
import android.graphics.Canvas;
/**
* TI, MapBit!
* Created by Samuzero15 on 28-07-2017.
*/
public class MapBit {
private float x;
private float y;
private int height;
private int width;
private Bitmap bmp;
public MapBit(Bitmap pmb)
{
this.bmp = pmb;
this.height = this.bmp.getHeight();
this.width = this.bmp.getWidth();
}
// Getmethis
public float getX(){return this.x;}
public float getY(){return this.y;}
public int getHeight(){return this.height;}
public int getWidth(){return this.width;}
public Bitmap getBitmap(){return this.bmp;}
public void setX(float newX){this.x = newX;}
public void setY(float newY){this.y = newY;}
public void onDraw(Canvas canvas)
{
canvas.drawBitmap(this.bmp,x,y,null);
}
public boolean isCollition(float x2, float y2) {
return x2 > this.x && x2 < this.x + this.width && y2 > this.y && y2 < this.y + this.height;
}
}
activity_main.xml (The main view for landscape)
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
tools:context="com.example.sammuzero.aplicamesta.MainActivity">
<RelativeLayout
android:layout_width="304dp"
android:layout_height="439dp"
tools:layout_editor_absoluteX="8dp"
tools:layout_editor_absoluteY="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:weightSum="1"
tools:layout_editor_absoluteX="8dp"
tools:layout_editor_absoluteY="8dp">
<view
android:id="#+id/game"
class="com.example.sammuzero.aplicamesta.MyView"
id="#+id/view4"
layout_width="match_parent"
android:layout_width="match_parent"
android:layout_height="356dp"
android:gravity="center" />
<SeekBar
android:id="#+id/zoom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|center"
android:max="150"
android:min="25"
android:progress="100" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
tools:layout_editor_absoluteX="8dp"
tools:layout_editor_absoluteY="8dp">
<Button
android:id="#+id/exit"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="Salir" />
<Button
android:id="#+id/gatos"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="Gatos" />
<Button
android:id="#+id/reinicio"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="Repetir" />
<ImageButton
android:id="#+id/nextTurn"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:srcCompat="#android:drawable/ic_media_play" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
The main activity in java:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
MyView elJuego;
Button salida;
Button reset;
Button nextTurn;
SeekBar escal;
Bitmap piso1;
Bitmap muro;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
salida = (Button) findViewById(R.id.exit);
reset = (Button) findViewById(R.id.reinicio);
elJuego = (MyView) findViewById(R.id.game);
escal = (SeekBar) findViewById(R.id.zoom);
salida.setOnClickListener(this);
reset.setOnClickListener(this);
escal.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
int progressChanged = 0;
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser){
progressChanged = progress;
elJuego.setEscala(progressChanged);
}
public void onStartTrackingTouch(SeekBar seekBar) {}
public void onStopTrackingTouch(SeekBar seekBar) {}
});
piso1 = BitmapFactory.decodeResource(getResources(), R.drawable.floor1);
muro = BitmapFactory.decodeResource(getResources(), R.drawable.pared);
}
#Override
public void onClick(View v)
{
switch(v.getId())
{
case R.id.exit:
finish();
System.exit(0);
break;
case R.id.reinicio:
elJuego.invalidate();
Terreno nuevo = new Terreno(2,2,new MapBit(piso1) , new MapBit(muro));
elJuego.queTerrenoDibujo(nuevo);
default: break;
}
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
}
So I found this code online, but the problem is that instead of drawing a straight Line (Black Straight thin Line)instead it draws dotted lines, But everytime I modify it to draw a line I get an error. Any help would be appreciated.
package cameraadvanced.android2.oreillyschool.com.hello4;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.net.Uri;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import java.io.FileNotFoundException;
public class mic extends Activity {
Button btnLoadImage;
TextView textSource, textInfo;
ImageView imageResult;
final int RQS_IMAGE1 = 1;
Uri source;
Bitmap bitmapMaster;
Canvas canvasMaster;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fingeract);
btnLoadImage = (Button) findViewById(R.id.loadimage);
textSource = (TextView) findViewById(R.id.sourceuri);
imageResult = (ImageView) findViewById(R.id.result);
btnLoadImage.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
Intent intent = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, RQS_IMAGE1);
}
});
imageResult.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
int x = (int) event.getX();
int y = (int) event.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
textSource.setText("ACTION_DOWN- " + x + " : " + y);
drawOnProjectedBitMap((ImageView) v, bitmapMaster, x, y);
break;
case MotionEvent.ACTION_MOVE:
textSource.setText("ACTION_MOVE- " + x + " : " + y);
drawOnProjectedBitMap((ImageView) v, bitmapMaster, x, y);
break;
case MotionEvent.ACTION_UP:
textSource.setText("ACTION_UP- " + x + " : " + y);
drawOnProjectedBitMap((ImageView) v, bitmapMaster, x, y);
break;
}
/*
* Return 'true' to indicate that the event have been consumed.
* If auto-generated 'false', your code can detect ACTION_DOWN only,
* cannot detect ACTION_MOVE and ACTION_UP.
*/
return true;
}
});
}
/*
* Project position on ImageView to position on Bitmap
* draw on it
*/
private void drawOnProjectedBitMap(ImageView iv, Bitmap bm, int x, int y) {
if (x < 0 || y < 0 || x > iv.getWidth() || y > iv.getHeight()) {
//outside ImageView
return;
} else {
int projectedX = (int) ((double) x * ((double) bm.getWidth() / (double) iv.getWidth()));
int projectedY = (int) ((double) y * ((double) bm.getHeight() / (double) iv.getHeight()));
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.WHITE);
paint.setStrokeWidth(3);
canvasMaster.drawCircle(projectedX, projectedY, 5, paint);
imageResult.invalidate();
textSource.setText(x + ":" + y + "/" + iv.getWidth() + " : " + iv.getHeight() + "\n" +
projectedX + " : " + projectedY + "/" + bm.getWidth() + " : " + bm.getHeight()
);
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Bitmap tempBitmap;
if (resultCode == RESULT_OK) {
switch (requestCode) {
case RQS_IMAGE1:
source = data.getData();
textSource.setText(source.toString());
try {
//tempBitmap is Immutable bitmap,
//cannot be passed to Canvas constructor
tempBitmap = BitmapFactory.decodeStream(
getContentResolver().openInputStream(source));
Config config;
if (tempBitmap.getConfig() != null) {
config = tempBitmap.getConfig();
} else {
config = Config.ARGB_8888;
}
//bitmapMaster is Mutable bitmap
bitmapMaster = Bitmap.createBitmap(
tempBitmap.getWidth(),
tempBitmap.getHeight(),
config);
canvasMaster = new Canvas(bitmapMaster);
canvasMaster.drawBitmap(tempBitmap, 0, 0, null);
imageResult.setImageBitmap(bitmapMaster);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
}
}
}
Read your code again. That's what drawOnProjectedBitMap does: it draws circles at specific points (current position). If you want lines instead of dots, you need to draw a line from the previous position to the current position.
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.
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);
}
I have a strange problem in my android app. I have an activity which shows an image. The image is saved on the SD card. The user can choose share from the context menu which is coded with the standard ACTION_SEND code. Please see below
public void shareImage(){
Intent emailShare = new Intent(android.content.Intent.ACTION_SEND);
emailShare.setType("image/jpeg");
emailShare.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
emailShare.putExtra(Intent.EXTRA_STREAM,uriId);
startActivity(Intent.createChooser(emailShare,"Send picture using:"));
}
Where uriId is the uri of the image.
This works and the image can be sent to facebook or whatever. But if I then exit my app, rotate the screen the image is missing. I get a file io error in the log when i try and retrieve the image. I have used Astro to search for the image but it is nowhere to be found!
I will post the entire class below. If anyone has any ideas I would be very appreciative.
Stephen
'package com.pengilleys.fishingsnapz;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.graphics.RectF;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.FloatMath;
import android.util.Log;
import android.view.Display;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;
import android.widget.TextView;
public class ImagePreview extends Activity implements OnTouchListener{
protected Context mContext;
static final String TAG = "ImagePreview";
static final int SHARE_ID = 0;
static final int EDIT_ID = 1;
static final int PROGRESS_DIALOG = 0;
ProgressDialog progressDialog;
private Bundle extras;
protected static Bitmap bm;
protected DBAdapter db = new DBAdapter(ImagePreview.this);
Long id;
private FacebookManager fb;
private Uri uriId;
//Touch gesture related variables
Matrix matrix = new Matrix();
Matrix savedMatrix = new Matrix();
// Remember some things for zooming
PointF start = new PointF();
PointF mid = new PointF();
float oldDist = 0;
// 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;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.image_view);
mContext = this;
try{
extras = getIntent().getExtras();
id = (Long) extras.get(DBAdapter.KEY_ROWID);
Log.d(TAG,"id="+id);
ImageView imageV = (ImageView)findViewById(R.id.image_preview);
imageV.setOnTouchListener(this);
//get image
bm = getImage(id);
imageV.setImageBitmap(bm);
imageV.setImageMatrix(matrix);
//get snap details for text overlay
ArrayList<String> details = new ArrayList<String>();
details = getSnapDetails(id);
prepareSnapDetails(details);
}catch(Exception e){
Log.e(TAG,e.toString());
}finally{
}
}
private ArrayList<String> getSnapDetails(long id){
ArrayList<String> fishDetails = new ArrayList<String>();
Cursor cursor;
//open the database and grab the snap details
db.open();
cursor = db.fetchNote(id);
db.close();
//loop through cursor results and put into our arraylist<string>
try{
startManagingCursor(cursor);
cursor.moveToFirst();
//only one row but multiple columns, manually assign columns
String value = cursor.getString(cursor.getColumnIndexOrThrow("date"));
value = checkValue(value);
fishDetails.add(value);
value = cursor.getString(cursor.getColumnIndexOrThrow("type"));
value = checkValue(value);
fishDetails.add(value);
value = cursor.getString(cursor.getColumnIndexOrThrow("weight"));
value = checkValue(value);
fishDetails.add(value);
value = cursor.getString(cursor.getColumnIndexOrThrow("place"));
value = checkValue(value);
fishDetails.add(value);
}catch(Exception e){
Log.e(TAG,e.toString());
}
db.close();
return fishDetails;
}
private String checkValue(String value){
if(value==""){value="-";};
return value;
}
private boolean prepareSnapDetails(ArrayList<String> details){
TextView tx = (TextView)findViewById(R.id.details_overlay);
tx.setText("");
String detail="";
String[] labels = new String[]{"Date: ","Type: ","Weight: ","Place: "};
try{
for(int i=0;i<4;i++){
//add text details to textview
detail = labels[i] + details.get(i) + '\n';
Log.d(TAG,detail);
CharSequence ch = detail.subSequence(0,detail.length());
tx.append(ch);
}
}catch(Exception e){
Log.e(TAG,e.toString());
}
return true;
}
private Bitmap getImage(Long id){
try{
db.open();
Cursor c = db.fetchUri(id);
uriId = Uri.parse(c.getString(c.getColumnIndexOrThrow(DBAdapter.KEY_URI)));
ContentResolver cr = getContentResolver();
Bitmap bitmap = MediaStore.Images.Media.getBitmap(cr,uriId);
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
if(bitmap.getWidth() > width || bitmap.getHeight() > height){
float heightRatio = (float) height / bitmap.getHeight();
float widthRatio = (float) width / bitmap.getWidth();
Log.d(TAG,"height="+heightRatio + " width=" + widthRatio);
matrix.setScale(widthRatio, heightRatio);
}else{
matrix.setTranslate(1f,1f);
Log.d(TAG,"bitmap.getWidth="+bitmap.getWidth() + " vs width="+width);
Log.d(TAG,"bitmap.getHeight="+bitmap.getHeight() + " vs height="+height);
}
db.close();
return bitmap;
} catch (FileNotFoundException e) {
Log.e("GETIMAGE",e.toString());
return null;
} catch (IOException e) {
Log.e("GETIMAGE",e.toString());
return null;
}catch(Exception e){
Log.e("GETIMAGE",e.toString());
return null;
}
}
public void shareImage(){
Intent emailShare = new Intent(android.content.Intent.ACTION_SEND);
emailShare.setType("image/jpeg");
emailShare.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
emailShare.putExtra(Intent.EXTRA_STREAM,uriId);
startActivity(Intent.createChooser(emailShare,"Send picture using:"));
}
#Override
public boolean onTouch(View v, MotionEvent event) {
ImageView view = (ImageView) v;
final float MIN_ZOOM = 0.25f;
final float MAX_ZOOM = 4;
float height = view.getDrawable().getIntrinsicHeight();
float width = view.getDrawable().getIntrinsicWidth();
float[] matrixValues = new float[9];
RectF viewRect = new RectF(0, 0, view.getWidth(), view.getHeight());
dumpEvent(event);
switch(event.getAction() & MotionEvent.ACTION_MASK){
case MotionEvent.ACTION_DOWN:
savedMatrix.set(matrix);
start.set(event.getX(), event.getY());
Log.d(TAG,"mode=DRAG");
mode=DRAG;
break;
case MotionEvent.ACTION_UP:
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");
}
break;
case MotionEvent.ACTION_MOVE:
if(mode==DRAG){
Log.d(TAG,"mode=MOVE");
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() - 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);
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);
}else if(mode==ZOOM){
float newDist= spacing(event);
if(newDist>10f){
matrix.set(savedMatrix);
float scale = newDist / oldDist;
Log.d(TAG,"Scale="+scale);
matrix.getValues(matrixValues);
float currentScale = matrixValues[Matrix.MSCALE_X];
Log.d(TAG,"currentScale="+currentScale);
// limit zoom
if (scale * currentScale > MAX_ZOOM) {
scale = MAX_ZOOM / currentScale;
} else if (scale * currentScale < MIN_ZOOM) {
scale = MIN_ZOOM / currentScale;
}
matrix.postScale(scale, scale, mid.x, mid.y);
}
}
break;
}
//perform the transformation
view.setImageMatrix(matrix);
return true;
}
private static 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 static 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);
}
/** Show an event in the logcat view for debugging **/
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("DUMP", sb.toString());
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
menu.add(0, SHARE_ID, 0, R.string.share_id);
menu.add(0,EDIT_ID,0,R.string.edit_details);
return true;
}
#Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
switch(item.getItemId()) {
case SHARE_ID:
try{
shareImage();
}catch(Exception e){
Log.e(TAG,e.toString());
}
return true;
case EDIT_ID:
try{
Intent intent = new Intent(mContext,SnapDetails.class);
intent.putExtra(DBAdapter.KEY_ROWID,id);
startActivityForResult(intent,FishingSnapz.SNAP_EDIT);
}catch(Exception e){
Log.e(TAG,e.toString());
}
}
return super.onMenuItemSelected(featureId, item);
}
#Override
protected void onResume(){
super.onResume();
}
#Override
protected void onActivityResult (int requestCode, int resultCode, Intent data){
super.onActivityResult(requestCode, resultCode, data);
//Required by facebook single sign on - check that we are returning to activity from FB
if(data!=null){
fb.authorizeCallback(requestCode, resultCode, data);
}else{
extras = getIntent().getExtras();
id = (Long) extras.get(DBAdapter.KEY_ROWID);
//get snap details for text overlay
ArrayList<String> details = new ArrayList<String>();
details = getSnapDetails(id);
prepareSnapDetails(details);
}
}
}
'
Sounds like a bug in whatever app you are using to share it with. You might consider making a spare copy of the file before issuing the ACTION_SEND, then deleting the spare copy later if it is still hanging around.
This happens when sharing an image via Facebook. Do this:
1 make a copy,
2 share the copy,
3 delete the copy.