On my view I want to place a hidden button, and above this hidden button I want to place an image. Whenever the user drags on the image the button's drag event should be called. Can any one suggest how to do this? As there is no in-built method for drag events in Android.
use this code for drag
Main.java
package com.drag;
import android.app.Activity;
import android.os.Bundle;
public class Main extends Activity{
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// draw the view
setContentView(new DrawView(this));
}
}
DrawView.java
package com.drag;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Point;
import android.view.MotionEvent;
import android.view.View;
public class DrawView extends View
{
private ColorBall[] colorballs = new ColorBall[3]; // array that holds the balls
private int balID = 0; // variable to know what ball is being dragged
public DrawView(Context context) {
super(context);
setFocusable(true); //necessary for getting the touch events
// setting the start point for the balls
Point point1 = new Point();
point1.x = 50;
point1.y = 20;
Point point2 = new Point();
point2.x = 100;
point2.y = 20;
Point point3 = new Point();
point3.x = 150;
point3.y = 20;
// declare each ball with the ColorBall class
colorballs[0] = new ColorBall(context,R.drawable.bol_groen, point1);
colorballs[1] = new ColorBall(context,R.drawable.bol_rood, point2);
colorballs[2] = new ColorBall(context,R.drawable.bol_blauw, point3);
}
// the method that draws the balls
#Override protected void onDraw(Canvas canvas) {
//canvas.drawColor(0xFFCCCCCC); //if you want another background color
//draw the balls on the canvas
for (ColorBall ball : colorballs) {
canvas.drawBitmap(ball.getBitmap(), ball.getX(), ball.getY(), null);
}
}
// events when touching the screen
public boolean onTouchEvent(MotionEvent event) {
int eventaction = event.getAction();
int X = (int)event.getX();
int Y = (int)event.getY();
switch (eventaction ) {
case MotionEvent.ACTION_DOWN: // touch down so check if the finger is on a ball
balID = 0;
for (ColorBall ball : colorballs) {
// check if inside the bounds of the ball (circle)
// get the center for the ball
int centerX = ball.getX() + 25;
int centerY = ball.getY() + 25;
// calculate the radius from the touch to the center of the ball
double radCircle = Math.sqrt( (double) (((centerX-X)*(centerX-X)) + (centerY-Y)*(centerY-Y)));
// if the radius is smaller then 23 (radius of a ball is 22), then it must be on the ball
if (radCircle < 23){
balID = ball.getID();
break;
}
// check all the bounds of the ball (square)
//if (X > ball.getX() && X < ball.getX()+50 && Y > ball.getY() && Y < ball.getY()+50){
// balID = ball.getID();
// break;
//}
}
break;
case MotionEvent.ACTION_MOVE: // touch drag with the ball
// move the balls the same as the finger
if (balID > 0) {
colorballs[balID-1].setX(X-25);
colorballs[balID-1].setY(Y-25);
}
break;
case MotionEvent.ACTION_UP:
// touch drop - just do things here after dropping
break;
}
// redraw the canvas
invalidate();
return true;
}
}
ColorBall.java
package com.drag;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Point;
public class ColorBall
{
private Bitmap img; // the image of the ball
private int coordX = 0; // the x coordinate at the canvas
private int coordY = 0; // the y coordinate at the canvas
private int id; // gives every ball his own id, for now not necessary
private static int count = 1;
private boolean goRight = true;
private boolean goDown = true;
public ColorBall(Context context, int drawable) {
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
img = BitmapFactory.decodeResource(context.getResources(), drawable);
id=count;
count++;
}
public ColorBall(Context context, int drawable, Point point) {
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
img = BitmapFactory.decodeResource(context.getResources(), drawable);
id=count;
count++;
coordX= point.x;
coordY = point.y;
}
public static int getCount() {
return count;
}
void setX(int newValue) {
coordX = newValue;
}
public int getX() {
return coordX;
}
void setY(int newValue) {
coordY = newValue;
}
public int getY() {
return coordY;
}
public int getID() {
return id;
}
public Bitmap getBitmap() {
return img;
}
public void moveBall(int goX, int goY) {
// check the borders, and set the direction if a border has reached
if (coordX > 270){
goRight = false;
}
if (coordX < 0){
goRight = true;
}
if (coordY > 400){
goDown = false;
}
if (coordY < 0){
goDown = true;
}
// move the x and y
if (goRight){
coordX += goX;
}else
{
coordX -= goX;
}
if (goDown){
coordY += goY;
}else
{
coordY -= goY;
}
}
}
Related
I have an image(ball) its a BitmapDrawable and it moves in all directions on the screen for that i am taking onDraw(canvas) in AnimatedView.java its working fine.
My Requirement:
I want to click on the image, but unfortunately the whole screen takes the event.
Please help me.
How to get click event only on the image?
So that i can proceed with further development.
Here is the code:
MainActivity
public class MainActivity extends Activity {
Context context;
int count=0;
EditText text;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AnimatedView animatedView=(AnimatedView) findViewById(R.id.anim_view);
animatedView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
EditText text=(EditText) findViewById(R.id.editText1);
ImageView imageView=(ImageView) findViewById(R.drawable.ball);
v.startAnimation(AnimationUtils.loadAnimation(MainActivity.this, R.anim.animation));
}
});
animatedview.java:
public class AnimatedView extends ImageView{
private Context mContext;
int x = -1;
int y = -1;
private int xVelocity = 10;
private int yVelocity = 5;
private Handler h;
private final int FRAME_RATE = 30;
BitmapDrawable ball;
public AnimatedView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
h = new Handler();
}
private Runnable r = new Runnable() {
#Override
public void run() {
invalidate();
}
};
#Override
protected void onDraw(Canvas c) {
BitmapDrawable ball = (BitmapDrawable) mContext.getResources().getDrawable(R.drawable.ball);
if (x<0 && y <0) {
x = this.getWidth()/2;
y = this.getHeight()/2;
} else {
x += xVelocity;
y += yVelocity;
if ((x > this.getWidth() - ball.getBitmap().getWidth()) || (x < 0)) {
xVelocity = xVelocity*-1;
}
if ((y > this.getHeight() - ball.getBitmap().getHeight()) || (y < 0)) {
yVelocity = yVelocity*-1;
}
}
c.drawBitmap(ball.getBitmap(), x, y, null);
h.postDelayed(r, FRAME_RATE);
}
main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="#000000">
<com.example.example.AnimatedView
android:id="#+id/anim_view"
android:layout_width="fill_parent"
android:layout_height="420dp"
android:onClick="imageClicked" />
</LinearLayout>
**I hope This codes Works for you, what you are looking for.....**
This is the complete code representing both ball movement and touch on ball.
public class MainActivity extends Activity implements OnTouchListener
{
BubbleGraphic bubbleGraphic;
int bm_x = 0, bm_y = 0, bm_offsetx, bm_offsety, bm_w, bm_h, subBM_w, subBM_h;
int f = 0;
private float x, y;
Canvas canvas;
boolean dm_touched = false;
static int random_x;
static int random_y;
boolean touching;
// These variable for position in x_axis direction
int w1;
// These variable for position in y_axis direction
int h1;
// These variable for velocity in x_axis direction
private int w1_V;
// These variable for velocity in y_axis direction
private int h1_V;
Bitmap mainBG;
Bitmap bmpBall;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
bubbleGraphic = new BubbleGraphic(this);
bubbleGraphic.setOnTouchListener(this);
// Your Background Image of Canvas
mainBG = BitmapFactory.decodeResource(getResources(), R.drawable.bg1);
w1 = -1;
h1 = -1;
w1_V = 1;
h1_V = 1;
// This is used to create bitmap object and decode the input stream into bitmap
bmpBall = BitmapFactory.decodeResource(getResources(),
R.drawable.myBall);
bm_w = bmpBall.getWidth();
bm_h = bmpBall.getHeight();
setContentView(bubbleGraphic);
}
protected void onPause() {
super.onPause();
bubbleGraphic.pause();
}
protected void onResume() {
super.onResume();
bubbleGraphic.resume();
}
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
x = event.getX();
y = event.getY();
touching = true;
if (dm_touched) {
w1 = (int) x - bm_offsetx;
h1 = (int) y - bm_offsety;
}
break;
case MotionEvent.ACTION_DOWN:
x = event.getX();
y = event.getY();
touching = true;
// checking if Ball is touched
if ((x > w1) && (x < bm_w + w1) && (y > h1) && (y < bm_h + h1)) {
bm_offsetx = (int) x - w1;
bm_offsety = (int) y - h1;
}
dm_touched = true;
break;
case MotionEvent.ACTION_UP:
default:
dm_touched = false;
touching = false;
}
return true;
}
// **************************************************************************************//
// Creating Canvas graphic Class and running thread //
// *************************************************************************************//
class BubbleGraphic extends SurfaceView implements Runnable {
SurfaceHolder holder;
Thread thread = null;
boolean isRunning = false;
boolean holdingBubble = true;
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
public BubbleGraphic(Context context) {
super(context);
holder = getHolder();
}
public void pause() {
isRunning = false;
while (true) {
try {
thread.join();
} catch (Exception e) {
}
break;
}
thread = null;
}
public void resume() {
isRunning = true;
thread = new Thread(this);
thread.start();
}
public void run() {
while (isRunning) {
if (!holder.getSurface().isValid())
continue;
canvas = holder.lockCanvas();`enter code here`
canvas.drawBitmap(mainBG, 0, 0, null);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(1);
paint.setColor(Color.TRANSPARENT);
if (touching) {
canvas.drawRect(x, y, x + bm_w, y + bm_h, paint);
}
canvas.drawBitmap(bmpBall, w1, h1, null);
// Method Responsible for ball movement and its position
checkBallMovementAndPosition();
holder.unlockCanvasAndPost(canvas);
}
}
private void checkBallMovementAndPosition() {
if (w1 < 0 && h1 < 0) {
w1 = this.getWidth() / 2;
h1 = this.getHeight() / 2;
} else {
w1 += w1_V;
h1 += h1_V;
if ((w1 > this.getWidth() - bm_w) || (w1 < 0)) {
w1_V = w1_V * -1;
w1 += w1_V;
}
if ((h1 > this.getHeight() - bm_h) || (h1 < 0)) {
h1_V = h1_V * -1;
h1 += h1_V;
}
}
}
}
}
Note: Replace the images with Your images.
I have created custom drawable marker which uses canvas to draw
bounds. Everything works great excepts one thing: onItemSingleTapUp
not called when any marker on the screen taped.
Here is overlay creation code:
ItemizedIconOverlay<OverlayItem> groupsOverlay = new ItemizedIconOverlay<OverlayItem>(
new ArrayList<OverlayItem>(),
new OnItemGestureListener<OverlayItem>() {
#Override
public boolean onItemLongPress(int arg0, OverlayItem arg1) {
return false;
}
#Override
public boolean onItemSingleTapUp(int arg0, OverlayItem arg1) {
if(arg1 == null){
return false;
}
if(m_prevView != null){
m_mapView.removeView(m_prevView);
m_prevView = null;
}
View popUp = getLayoutInflater().inflate(R.layout.map_popup, m_mapView, false);
TextView tv = (TextView)popUp.findViewById(R.id.popupTextView);
tv.setText(arg1.getTitle());
MapView.LayoutParams mapParams = new MapView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
arg1.getPoint(),
MapView.LayoutParams.BOTTOM_CENTER, 0, 0);
m_mapView.addView(popUp, mapParams);
m_prevView = popUp;
return true;
}
}, new DefaultResourceProxyImpl(getApplicationContext()));
This is custom drawable marker:
package com.testapp.data;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Paint.Style;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
public class GroupMarkerDrawable extends Drawable {
private final static int DELTA_BOX = 4;
private final Paint m_paint;
private String m_text;
private double m_pxRadius;
public GroupMarkerDrawable(double pxRadius, String text) {
m_text = text;
m_paint = new Paint();
m_pxRadius = pxRadius;
m_paint.setAntiAlias(true);
}
#Override
public void draw(Canvas c) {
// Set the correct values in the Paint
m_paint.setARGB(190, 0, 0, 0);
m_paint.setStrokeWidth(2);
m_paint.setStyle(Style.STROKE);
m_paint.setTextAlign(Align.CENTER);
Rect bounds = new Rect();
m_paint.getTextBounds(m_text, 0, m_text.length(), bounds);
int centerX = getBounds().centerX();
int centerY = getBounds().centerY();
int w2 = bounds.width() / 2;
int h2 = bounds.height() / 2;
Rect rect = new Rect(centerX - w2 - DELTA_BOX, centerY - h2 -
DELTA_BOX, centerX + w2 + DELTA_BOX, centerY + h2 + DELTA_BOX);
// Draw it
c.drawCircle(centerX, centerY, (float) m_pxRadius, m_paint);
m_paint.setStyle(Style.FILL);
m_paint.setARGB(190, 0, 128, 0);
c.drawRect(rect, m_paint);
m_paint.setStyle(Style.STROKE);
m_paint.setARGB(190, 0, 0, 0);
c.drawRect(rect, m_paint);
c.drawText(m_text, centerX, centerY + h2, m_paint);
}
#Override
public int getOpacity() {
return PixelFormat.OPAQUE;
}
#Override
public void setAlpha(int arg0) {
}
#Override
public void setColorFilter(ColorFilter arg0) {
}
}
Same code using static drawable from resources, instead of
GroupMarkerDrawable, works.
I found how to solve this. Just need to return proper dimensions for Drawable. This requires overriding of two methods in GroupMarkerDrawable. FOr example like this:
#Override
public int getIntrinsicHeight() {
return m_pxRadius * 2;
};
#Override
public int getIntrinsicWidth() {
return m_pxRadius * 2;
};
An additional solution for a polygon.
The solutions of ydanila put me on the good track but I had to override hitTest method of ItemizedOverlayWithFocus class in order to get my polygon hit.
Drawable:
Drawable drawable = new Drawable() {
private int mIntrinsicHeight = 0;
private int mIntrinsicWidth = 0;
#Override
public void draw(Canvas canvas) {
// used to determine limit coordinates of the drawable
int yTop, yBottom, xLeft, xRight;
if (points != null && points.size() > 1) {
//we have to make a projection to convert from postions on the map in
//gradiant to a position on the view in pixels
final Projection pj = mapView.getProjection();
Path path = new Path();
Point centerMapPixelPoint = new Point();
Point tmpMapPixelPoint = new Point();
pj.toMapPixels(points.get(0), centerMapPixelPoint);
// init limit coordinates
xLeft = centerMapPixelPoint.x;
xRight = centerMapPixelPoint.x;
yTop = centerMapPixelPoint.y;
yBottom = centerMapPixelPoint.y;
path.moveTo(centerMapPixelPoint.x, centerMapPixelPoint.y);
for (int i = 1; i < points.size(); i++) {
pj.toMapPixels(points.get(i), tmpMapPixelPoint);
// update limit coordinates if necessary
if (xLeft > tmpMapPixelPoint.x) {
xLeft = tmpMapPixelPoint.x;
}
if (xRight < tmpMapPixelPoint.x) {
xRight = tmpMapPixelPoint.x;
}
if (yBottom < tmpMapPixelPoint.y) {
yBottom = tmpMapPixelPoint.y;
}
if (yTop > tmpMapPixelPoint.y) {
yTop = tmpMapPixelPoint.y;
}
path.lineTo(tmpMapPixelPoint.x, tmpMapPixelPoint.y);
}
// close polygon returning to first point
path.close();
canvas.drawPath(path, linePaint);
canvas.drawPath(path, innerPaint);
// calculate drawable height and width
mIntrinsicHeight = yTop -yBottom;
mIntrinsicWidth = xRight - xLeft;
}
}
#Override
public int getIntrinsicHeight() {
return mIntrinsicHeight;
};
#Override
public int getIntrinsicWidth() {
return mIntrinsicWidth;
};
};
Overlay:
public class MyItemizedIconOverlay<Item extends OverlayItem> extends ItemizedOverlayWithFocus<Item> {
#Override
protected boolean hitTest(Item item, Drawable marker, int hitX, int hitY) {
boolean hit = false;
Rect bounds = marker.getBounds();
if (hitX < bounds.right && hitX > bounds.left && hitY < bounds.top && hitY > bounds.bottom) {
hit = true;
} else {
hit = false;
}
return hit;
};
I currently have something working where I can drag a box horizontally on the screen (what I want it to do). However, it works when you click ANYWHERE on the screen, and I want it to work only when the box has been clicked. I have tried implementing this in different ways, and I've looked all over the place and still remain lost. Can anybody help? I also can't figure out how a bitmap is placed (I'm using a bitmap right now as I can't for the life of me figure out how to implement the ImageView inside my SurfaceView). If I say my bitmap is placed at 0,0 will that place the bitmap according to its top left corner at 0,0? I also had an algorithm for stopping the box when it reached an edge, but I'll just have to rewrite that as I must have deleted it. Please if you can offer your knowledge I would GREATLY appreciate it
public class BoardView extends SurfaceView implements SurfaceHolder.Callback{
Context mContext;
private BoardThread thread;
private float box_x = 140;
private float box_y = 378;
ImageView i = (ImageView) findViewById(R.id.box_view);
Bitmap box =
(BitmapFactory.decodeResource
(getResources(), R.drawable.box));
private float boxWidth = box.getWidth();
private float boxHeight = box.getHeight();
public BoardView(Context context){
super(context);
//surfaceHolder provides canvas that we draw on
getHolder().addCallback(this);
// controls drawings
thread = new BoardThread(getHolder(),this);
//intercepts touch events
setFocusable(true);
}
#Override
public void onDraw(Canvas canvas){
canvas.drawColor(Color.WHITE);
//draw box and set start location
canvas.drawBitmap(box, box_x - (boxWidth/2),
box_y - (boxHeight/2), null);
}
#Override
public boolean onTouchEvent(MotionEvent event){
//boolean mode = false;
if(event.getAction() == MotionEvent.ACTION_DOWN){
//int x = (int)event.getX();
//int y = (int)event.getY();
//if (x > box_x && x < box_x + 29 && y > box_y && y < box_y + 30){
//mode = true;
box_x = (int)event.getX();
//}
}
if(event.getAction() == MotionEvent.ACTION_MOVE) {
//int x = (int)event.getX();
//int y = (int)event.getY();
//if (mode == true){
box_x = (int)event.getX();
//}
}
invalidate();
return true;
}
#Override
public void surfaceChanged(SurfaceHolder holder,
int format, int width, int height ){
}
#Override
public void surfaceCreated(SurfaceHolder holder){
thread.startRunning(true);
thread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder){
thread.startRunning(false);
thread.stop();
}
}
Simply check the touch event x and y coordinate, and check if this x,y-combination is within the box's bounds. I can see you are on the right path by looking at your commented out code.
Do something like this:
RectF rect = new RectF(x,y, x + box.getWidth(), y+box.geHeight());
if(rect.contains(touchX, touchY)) {
// You hit the box, allow dragging...
}
Try this:
package teste.com.br.teste;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.view.MotionEvent;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Tacila on 03/07
*/
public class Game extends View {
private Context context;
private BitmaptArrastavel bmArrastavel;
private BitmaptArrastavel bmArrastavel2;
private BitmaptArrastavel bmArrastavelTeste;
private List<BitmaptArrastavel> btms;
private BitmaptArrastavel[] btmsAtivas;
private BitmaptArrastavel[] lake;
private BitmaptArrastavel[] ativos;
private int qntDeItens = 5;
public Game(Context context) {
super(context);
this.context = context;
init();
}
public void init() {
btms = new ArrayList<BitmaptArrastavel>();
btmsAtivas = new BitmaptArrastavel[1];
ativos=new BitmaptArrastavel[1];
lake = new BitmaptArrastavel[3];
lake[0] = new BitmaptArrastavel(escalaBitmap(BitmapFactory.decodeResource(context.getResources(), R.drawable.cartadc)), 200);
lake[1] = new BitmaptArrastavel(escalaBitmap(BitmapFactory.decodeResource(context.getResources(), R.drawable.cartaao)), 210);
lake[2] = new BitmaptArrastavel(escalaBitmap(BitmapFactory.decodeResource(context.getResources(), R.drawable.cartake)), 220);
btms.add(bmArrastavel);
btms.add(bmArrastavelTeste);
btms.add(bmArrastavel2);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRGB(0,0,139);
for(int i = 0; i<=2; i++){
lake[i].drawOnCanvas(canvas);
}
}
public void travarArr(float x, float y ){
for(int i = 0; i<=2 ; i++){
if(lake[i].isDentro(x,y)){
ativos[0]=lake[i];
}
}
}
public void destravarBitmap() {
ativos[0]=null;
}
public Bitmap escalaBitmap(Bitmap bm) {
return Bitmap.createScaledBitmap(bm, 200, 300, false);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
final int action = event.getActionMasked();
switch (action) {
case MotionEvent.ACTION_DOWN:
System.out.println("Dentro do MotionEvent.ActionDown");
travarArr(event.getX(),event.getY());
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
System.out.println("Dentro do MotionEvent.ActionUP e ActionCancel tenho q entrar no destrava ");
destravarBitmap();
break;
case MotionEvent.ACTION_MOVE:
System.out.println("Dentro do MotionEvent.ActionMove");
for(int i = 0; i<ativos.length;i++){
if(ativos[i]!=null){
ativos[i].mover((int)event.getX(),(int)event.getY());
invalidate();
}
}
break;
case MotionEvent.ACTION_POINTER_DOWN:
System.out.println("Dentro do MotionEvent.ActionPointerDown");
travarArr(event.getX(), event.getY());
break;
case MotionEvent.ACTION_POINTER_UP:
System.out.println("Dentro do MotionEvent.ActionPointerUp");
destravarBitmap();
break;
default:
return super.onTouchEvent(event);
}
return true;
}
// int rotation = 0;
//
// public Bitmap vertical() {
// Matrix matrix = new Matrix();
// matrix.postRotate(90);
// Bitmap bm = escalaBitmap(BitmapFactory.decodeResource(context.getResources(), R.drawable.carta4c));
// return Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
// }
}
The class BitmapArrastavel
package teste.com.br.teste;
import android.graphics.Bitmap;
import android.graphics.Canvas;
/**
* Created by Tacila on 05/07/2017.
*/
public class BitmaptArrastavel {
public int x, y, altura, largura;
private Bitmap bitmap;
public BitmaptArrastavel(Bitmap b, int x) {
bitmap = b;
this.x = x;
init();
}
public void init() {
largura = 200;
altura = 350;
}
public Bitmap escalaBitmap(Bitmap bm) {
return Bitmap.createScaledBitmap(bm, largura, altura, false);
}
public boolean isDentro(float x, float y) {
return (x >= this.x && x <= this.x + largura && y >= this.y && y <= this.y + altura);
}
public void drawOnCanvas(Canvas canvas) {
canvas.drawBitmap(bitmap, x, y, null);
}
public void mover(int x, int y) {
this.x = x;
this.y = y;
}
}
I found this class:
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
// borrowed from https://sites.google.com/site/androidhowto/how-to-1/custom-scrollable-image-view
public class ScrollImageView extends View {
private final int DEFAULT_PADDING = 10;
private Display mDisplay;
private Bitmap mImage;
/* Current x and y of the touch */
private float mCurrentX = 0;
private float mCurrentY = 0;
private float mTotalX = 0;
private float mTotalY = 0;
/* The touch distance change from the current touch */
private float mDeltaX = 0;
private float mDeltaY = 0;
int mDisplayWidth;
int mDisplayHeight;
int mPadding;
public ScrollImageView(Context context) {
super(context);
initScrollImageView(context);
}
public ScrollImageView(Context context, AttributeSet attributeSet) {
super(context);
initScrollImageView(context);
}
private void initScrollImageView(Context context) {
mDisplay = ((WindowManager)context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
mPadding = DEFAULT_PADDING;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = measureDim(widthMeasureSpec, mDisplay.getWidth());
int height = measureDim(heightMeasureSpec, mDisplay.getHeight());
setMeasuredDimension(width, height);
}
private int measureDim(int measureSpec, int size) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
} else {
result = size;
if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(result, specSize);
}
}
return result;
}
public Bitmap getImage() {
return mImage;
}
public void setImage(Bitmap image) {
mImage = image;
}
public int getPadding() {
return mPadding;
}
public void setPadding(int padding) {
this.mPadding = padding;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
mCurrentX = event.getRawX();
mCurrentY = event.getRawY();
}
else if (event.getAction() == MotionEvent.ACTION_MOVE) {
float x = event.getRawX();
float y = event.getRawY();
// Update how much the touch moved
mDeltaX = x - mCurrentX;
mDeltaY = y - mCurrentY;
mCurrentX = x;
mCurrentY = y;
invalidate();
}
// Consume event
return true;
}
#Override
protected void onDraw(Canvas canvas) {
if (mImage == null) {
return;
}
float newTotalX = mTotalX + mDeltaX;
// Don't scroll off the left or right edges of the bitmap.
if (mPadding > newTotalX && newTotalX > getMeasuredWidth() - mImage.getWidth() - mPadding)
mTotalX += mDeltaX;
float newTotalY = mTotalY + mDeltaY;
// Don't scroll off the top or bottom edges of the bitmap.
if (mPadding > newTotalY && newTotalY > getMeasuredHeight() - mImage.getHeight() - mPadding)
mTotalY += mDeltaY;
Paint paint = new Paint();
canvas.drawBitmap(mImage, mTotalX, mTotalY, paint);
}
}
and am stumped how to use it with my application.
I want my application when in landscape orientation to display a bitmap image that is scrollable vertically and horizontally. I pull my image from a URL and programatically make it a bitmap. I call a method that returns my bitmap image.
Any ideas?
The setImage methods takes a Bitmap. So, you should be able to programmatically create this view in your activity, set the image with your Bitmap and place the view into your layout.
I've never seen this class before, so your mileage may vary ;)
when i run the code below everything works fine,it's a simple app with three balls that you can move around...
public class dragndrop extends Activity {
/** Called when the activity is first created. */
private ColorBall[] colorballs = new ColorBall[3]; // array that holds the balls
private static final String TAG="MyTAG";
DrawView myView;
private int balID = 0; // variable to know what ball is being dragged
int X;
int Y;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Point point1 = new Point();
point1.x = 50;
point1.y = 20;
Point point2 = new Point();
point2.x = 100;
point2.y = 20;
Point point3 = new Point();
point3.x = 150;
point3.y = 20;
// declare each ball with the ColorBall class
colorballs[0] = new ColorBall(this,R.drawable.bol_groen, point1);
colorballs[1] = new ColorBall(this,R.drawable.bol_rood, point2);
colorballs[2] = new ColorBall(this,R.drawable.bol_blauw, point3);
myView = new DrawView(this);
setContentView(myView);
}
public class DrawView extends View {
public DrawView(Context context) {
super(context);
setFocusable(true); //necessary for getting the touch events
// setting the start point for the balls
}
// the method that draws the balls
#Override protected void onDraw(Canvas canvas) {
//draw the balls on the canvas
for (ColorBall ball : colorballs) {
canvas.drawBitmap(ball.getBitmap(), ball.getX(), ball.getY(), null);
}
}
// events when touching the screen
public boolean onTouchEvent(MotionEvent event) {
int eventaction = event.getAction();
X = (int)event.getX();
Y = (int)event.getY();
switch (eventaction ) {
case MotionEvent.ACTION_DOWN: // touch down so check if the finger is on a ball
balID = 0;
for (ColorBall ball : colorballs) {
Log.d(TAG,"inside action down inside for coords:"+X+" coords: "+Y);
Log.d(TAG,"ball coords:"+ball.getX()+" coords: "+ball.getY());
int x =X;
int y =Y;
Log.d(TAG,"lalalalalala"+x+" coords: "+y);
if (x > ball.getX() && x < ball.getX()+50 && y > ball.getY() && y < ball.getY()+50){//if (X > ball.getX() && X < ball.getX()+50 && Y > ball.getY() && Y < ball.getY()+50){
Log.d(TAG,"inside ball coords!!!!!!!!!!!!!!!!!!!!!!!!:"+ball.getX()+" coords: "+ball.getY());
balID = ball.getID();
break;
}
}
break;
case MotionEvent.ACTION_MOVE: // touch drag with the ball
// move the balls the same as the finger
if (balID > 0) {
colorballs[balID-1].setX(X-25);
colorballs[balID-1].setY(Y-25);
}
break;
case MotionEvent.ACTION_UP:
// touch drop - just do things here after dropping
break;
}
// redraw the canvas
myView.invalidate();
return true;
}
}
}
But when i try to handle the onTouchevent from the main activity doesn't work and the strange is that it can't read a simple variable(x,y)!!!
i can't understand why this happened,it seems it can red them only if it's in a View!!!
public class dragndrop extends Activity {
/** Called when the activity is first created. */
private ColorBall[] colorballs = new ColorBall[3]; // array that holds the balls
private static final String TAG="MyTAG";
DrawView myView;
private int balID = 0; // variable to know what ball is being dragged
int X;
int Y;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Point point1 = new Point();
point1.x = 50;
point1.y = 20;
Point point2 = new Point();
point2.x = 100;
point2.y = 20;
Point point3 = new Point();
point3.x = 150;
point3.y = 20;
// declare each ball with the ColorBall class
colorballs[0] = new ColorBall(this,R.drawable.bol_groen, point1);
colorballs[1] = new ColorBall(this,R.drawable.bol_rood, point2);
colorballs[2] = new ColorBall(this,R.drawable.bol_blauw, point3);
myView = new DrawView(this);
setContentView(myView);
}
// events when touching the screen
public boolean onTouchEvent(MotionEvent event) {
int eventaction = event.getAction();
X = (int)event.getX();
Y = (int)event.getY();
switch (eventaction ) {
case MotionEvent.ACTION_DOWN: // touch down so check if the finger is on a ball
balID = 0;
for (ColorBall ball : colorballs) {
Log.d(TAG,"inside action down inside for coords:"+X+" coords: "+Y);
Log.d(TAG,"ball coords:"+ball.getX()+" coords: "+ball.getY());
int x =X;
int y =Y;
Log.d(TAG,"lalalalalala"+x+" coords: "+y);
if (x > ball.getX() && x < ball.getX()+50 && y > ball.getY() && y < ball.getY()+50){//if (X > ball.getX() && X < ball.getX()+50 && Y > ball.getY() && Y < ball.getY()+50){
Log.d(TAG,"inside ball coords!!:"+ball.getX()+" coords: "+ball.getY());
balID = ball.getID();
break;
}
}
break;
case MotionEvent.ACTION_MOVE: // touch drag with the ball
// move the balls the same as the finger
if (balID > 0) {
colorballs[balID-1].setX(X-25);
colorballs[balID-1].setY(Y-25);
}
break;
case MotionEvent.ACTION_UP:
// touch drop - just do things here after dropping
break;
}
// redraw the canvas
myView.invalidate();
return true;
}
public class DrawView extends View {
public DrawView(Context context) {
super(context);
setFocusable(true); //necessary for getting the touch events
// setting the start point for the balls
}
// the method that draws the balls
#Override protected void onDraw(Canvas canvas) {
//canvas.drawColor(0xFFCCCCCC); //if you want another background color
//draw the balls on the canvas
for (ColorBall ball : colorballs) {
canvas.drawBitmap(ball.getBitmap(), ball.getX(), ball.getY(), null);
}
}
}
}
Anyone who knows why?
Yes #bigstones the onTouchevent is working,it captures all the actions,the problem is that if i have the ontouchevent code inside the activity the variables X,Y seems not to work althought that they have a value and i can print it(or log)what i am saying is tested,i've tried and change all the values from the if() statement(getX,getY)to integers and it didn't work only for X,Y.....check the code again please!
thanks!
Found it!
I found that the problem is that it was the layout that should be registering some sort of listner so I did this:
I added this code to my Main clas:
private OnClickListener previewListener = new OnClickListener() {
#Override
public void onClick(View v) {
System.err.println("I've been clicked");
}
};
And the this line to the onCreate method:
previewLayout.setOnClickListener(previewListener);
And it worked!
Seemed you moved the onTouch outside of the DrawView. Since you're trying to handle touch events, you need to set up a onTouchListener but not the onClickListener.