I think I have hit a coders block here. I am writing a game where multiples images will fall from the top of the screen and you have to catch them at the bottom. There will be an indeterminate number of images, so you don't know how many there will be upon start time. For the life of me I CANNOT figure out the way to implement this. I understand the logic, but am having trouble trucking through Android's classes. I tried to create my own "blossom" object, but every time I try to write anything having to do with a bitmap inside of it, it freaks out. Maybe I'm just writing the class wrong, I don't know. All of this is being performed on a SurfaceView. Is there anybody who has any ideas on how to accomplish this? Here is my code thus far:
public class BoardView extends SurfaceView implements SurfaceHolder.Callback{
Context mContext;
Bitmap box =
(BitmapFactory.decodeResource
(getResources(), R.drawable.box));
Bitmap blossom =
(BitmapFactory.decodeResource
(getResources(), R.drawable.blossom));
private BoardThread thread;
private float box_x = 140;
private float box_y = 378;
private float blossom_x = 0;
private float blossom_y = 0;
private float boxWidth = box.getWidth();
private float boxHeight = box.getHeight();
private float blossomWidth = blossom.getWidth();
private float blossomHeight = blossom.getHeight();
private Random generator = new Random();
boolean mode = false;
RectF boxRect = new RectF(box_x,box_y, box_x + boxWidth, box_y + boxHeight);
//ImageView box_view;
public BoardView(Context context){
super(context);
//surfaceHolder provides canvas that we draw on
getHolder().addCallback(this);
// controls drawings
thread = new BoardThread(getHolder(),this);
//draws the blossom at a random starting point
blossom_x = generator.nextInt(300);
//box_view = (ImageView)findViewById(R.id.box_view);
//box_view.setVisibility(ImageView.VISIBLE);
//TranslateAnimation anim = new TranslateAnimation(0,0,300,0);
//anim.setDuration(500);
//box_view.startAnimation(anim);
//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);
canvas.drawBitmap(blossom, blossom_x,
blossom_y = blossom_y+3 , null);
//collision detection, currently not working after
//implementing random draw
if(blossom_y + blossomHeight == box_y)
{
canvas.drawBitmap(blossom, 40,100, null);
}
}
#Override
public boolean onTouchEvent(MotionEvent event){
if(event.getAction() == MotionEvent.ACTION_DOWN){
if(boxRect.contains(event.getX(),event.getY())){
mode = true;
}
}
if(event.getAction() == MotionEvent.ACTION_MOVE) {
if(boxRect.contains(event.getX(),event.getY())){
mode = true;
}
if(mode == true){
box_x = (int)event.getX();
boxRect.set(box_x,box_y, box_x + boxWidth, box_y + boxHeight);
}
}
if(event.getAction() == MotionEvent.ACTION_UP){
mode = false;
}
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();
}
}
I am currently using a bitmap to draw the falling flower. I started making a class for the flower object instead, which so far looks like this
public class Blossom{
private Bitmap blossom;
public Blossom()
{
Bitmap blossom =
(BitmapFactory.decodeResource
(getResources(), R.drawable.blossom));
}
public void setImage(Bitmap bitmap)
{
//sets the image for the blossom;
Bitmap blossom = bitmap;
}
}
It keeps giving me an error saying getResources is undefined for the Blossom class. When I try to write a method called setImage, and do the setting of the Image in the BoardView class, it won't let me at all :( It looked something like this
public class Blossom{
private Bitmap blossom;
public void setImage(Bitmap bitmap)
{
//sets the image for the blossom;
Bitmap blossom = bitmap;
}
}
Can anybody see what is going wrong here?
Since your class extends SurfaceView, you should be doing getContext().getResources()
Edit - if you want to use getResources in your other class, then you need to pass in a Context as well. You might instead just pass in your Bitmap instead of trying to fetch it from that data class.
Related
I have a surface view, and whenever I touch the screen, an image comes up in the spot I touch. It's great, but I cannot figure out how to put a background on the SurfaceView. I have tried using the OnDraw to draw a background right away (Without having to touch it), and that only works some of the time. It force closes most of the time.
Would anyone want to look at my code and see if it's possible to get a background image on the Surface view? Thanks in advance.
class MyView extends SurfaceView implements SurfaceHolder.Callback {
private Thready _thread;
private ArrayList _graphicsz = new ArrayList();
private GraphicObject _currentGraphic = null;
public MyView(Context context) {
super(context);
getHolder().addCallback(this);
_thread = new Thready(getHolder(), this);
setFocusable(true);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
synchronized (_thread.getSurfaceHolder()) {
GraphicObject graphic = null;
if (event.getAction() == MotionEvent.ACTION_DOWN) {
graphic = new GraphicObject(BitmapFactory.decodeResource(getResources(), R.drawable.cat1small));
graphic.getCoordinates().setX((int) event.getX() - graphic.getGraphic().getWidth() / 2);
graphic.getCoordinates().setY((int) event.getY() - graphic.getGraphic().getHeight() / 2);
_currentGraphic = graphic;
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
_currentGraphic.getCoordinates().setX((int) event.getX() - _currentGraphic.getGraphic().getWidth() / 2);
_currentGraphic.getCoordinates().setY((int) event.getY() - _currentGraphic.getGraphic().getHeight() / 2);
} else if (event.getAction() == MotionEvent.ACTION_UP) {
_graphicsz.add(_currentGraphic);
_currentGraphic = null;
}
return true;
}
}
#Override
public void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK);
Bitmap bitmap1;
GraphicObject.Coordinates coords1;
for (GraphicObject graphic : _graphicsz) {
bitmap1 = graphic.getGraphic();
coords1 = graphic.getCoordinates();
canvas.drawBitmap(bitmap1, coords1.getX(), coords1.getY(), null);
}
// draw current graphic at last...
if (_currentGraphic != null) {
bitmap1 = _currentGraphic.getGraphic();
coords1 = _currentGraphic.getCoordinates();
canvas.drawBitmap(bitmap1, coords1.getX(), coords1.getY(), null);
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// TODO Auto-generated method stub
}
public void surfaceCreated(SurfaceHolder holder) {
_thread.setRunning(true);
_thread.start();
}
public void surfaceDestroyed(SurfaceHolder holder) {
// simply copied from sample application LunarLander:
// we have to tell thread to shut down & wait for it to finish, or else
// it might touch the Surface after we return and explode
boolean retry = true;
_thread.setRunning(false);
while (retry) {
try {
_thread.join();
retry = false;
} catch (InterruptedException e) {
// we will try it again and again...
}
}
}
}
class Thready extends Thread {
private SurfaceHolder _surfaceHolder;
private MyView _panel;
private boolean _run = false;
public Thready(SurfaceHolder surfaceHolder, MyView panel) {
_surfaceHolder = surfaceHolder;
_panel = panel;
}
public void setRunning(boolean run) {
_run = run;
}
public SurfaceHolder getSurfaceHolder() {
return _surfaceHolder;
}
#Override
public void run() {
Canvas c;
while (_run) {
c = null;
try {
c = _surfaceHolder.lockCanvas(null);
synchronized (_surfaceHolder) {
_panel.onDraw(c);
}
} finally {
// do this in a finally so that if an exception is thrown
// during the above, we don't leave the Surface in an
// inconsistent state
if (c != null) {
_surfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
}
class GraphicObject {
/**
* Contains the coordinates of the graphic.
*/
public class Coordinates {
private int _x = 100;
private int _y = 0;
public int getX() {
return _x + _bitmap.getWidth() / 2;
}
public void setX(int value) {
_x = value - _bitmap.getWidth() / 2;
}
public int getY() {
return _y + _bitmap.getHeight() / 2;
}
public void setY(int value) {
_y = value - _bitmap.getHeight() / 2;
}
public String toString() {
return "Coordinates: (" + _x + "/" + _y + ")";
}
}
private Bitmap _bitmap;
private Coordinates _coordinates;
public GraphicObject(Bitmap bitmap) {
_bitmap = bitmap;
_coordinates = new Coordinates();
}
public Bitmap getGraphic() {
return _bitmap;
}
public Coordinates getCoordinates() {
return _coordinates;
}
}
Well, what strikes me first off all (and what could be causing a lot of problem) is this:
you're creating new bitmap way too often
Every time you get a touch event, you're loading in your bitmaps ... and you can get 80 to 100 touchevents every second!
So to start with, define global bitmaps (private Bitmap bmp1; etc), load them somewhere else and THEN use them in your touch event.
Also, remove the bmp loading/creation from onDraw and move it to somewhere else.
After you've done that, see what happens; you might have more problems (a REALY quick scan of your code seemed fine), but not creating and loading bitmaps 80 times a second will definitely help out :)
Is it possible to pass arguments to an Android Handler?? I have two pieces of code.
new Thread(){
public void run(){
for(;;){
uiCallback.sendEmptyMessage(0);
Thread.sleep(2000); //sleep for 2 seconds
}
}
}.start();
private Handler uiCallback = new Handler(){
public void handleMessage(Message msg){
//add a new blossom to the blossom ArrayList!!
blossomArrayList.add(new Blossom(context, R.drawable.blossom));
}
};
I of course get an error because the Handler method cannot see my context. This is probably because of this piece of code
public BoardView(Context context){
super(context);
Context is not visible elsewhere, and I'm wondering if I can pass it as an argument to my Handler.
EDIT: I am posting the two main pieces of code to answer a question about why my Blossom object needs context. I myself am not 100% sure >.> Maybe you could have a look and see what's going on.
public class Blossom{
private Bitmap blossom;
private float blossomX = 0;
private float blossomY = 0;
private Random generator = new Random();
public Blossom(Context context, int drawable)
{
blossom = BitmapFactory.decodeResource(context.getResources(), drawable);
blossomX = generator.nextInt(300);
}
public Bitmap getBitmap()
{
return blossom;
}
public float getBlossomX()
{
return blossomX;
}
public float getBlossomY()
{
return blossomY;
}
public void Fall(Canvas canvas, float boxY)
{
//draws the flower falling
canvas.drawBitmap(blossom, blossomX,
blossomY = blossomY+3 , null);
//collision detection, currently not working after
//implementing random start location
//if(blossomY + 29 == boxY)
//{
//canvas.drawBitmap(blossom,0,0,null);
//}
}
}
public class BoardView extends SurfaceView implements SurfaceHolder.Callback{
Context mContext;
Bitmap box =
(BitmapFactory.decodeResource
(getResources(), R.drawable.box));
private BoardThread thread;
private float box_x = 140;
private float box_y = 378;
private float boxWidth = box.getWidth();
private float boxHeight = box.getHeight();
private ArrayList<Blossom> blossomArrayList = new ArrayList<Blossom>();;
boolean mode = false;
RectF boxRect = new RectF(box_x,box_y, box_x + boxWidth, box_y + boxHeight);
public BoardView(Context context){
super(context);
//surfaceHolder provides canvas that we draw on
getHolder().addCallback(this);
// controls drawings
thread = new BoardThread(getHolder(),this);
//pass variables to instance of Blossom
//for(int i = 0; i <= 3; i++)
//{
//blossomArrayList.add(new Blossom(context, R.drawable.blossom));
//}
new Thread(){
public void run(){
for(;;){
uiCallback.sendEmptyMessage(0);
Thread.sleep(2000); //sleep for 2 seconds
}
}
}.start();
//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);
for(int i = 0; i<= 3; i++)
{
blossomArrayList.get(i).Fall(canvas, box_y);
}
}
#Override
public boolean onTouchEvent(MotionEvent event){
if(event.getAction() == MotionEvent.ACTION_DOWN){
if(boxRect.contains(event.getX(),event.getY())){
mode = true;
}
}
if(event.getAction() == MotionEvent.ACTION_MOVE) {
if(boxRect.contains(event.getX(),event.getY())){
mode = true;
}
if(mode == true){
box_x = (int)event.getX();
boxRect.set(box_x,box_y, box_x + boxWidth, box_y + boxHeight);
}
}
if(event.getAction() == MotionEvent.ACTION_UP){
mode = false;
}
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();
}
private Handler uiCallback = new Handler(){
public void handleMessage(Message msg){
//add a new blossom to the blossom ArrayList!!
blossomArrayList.add(new Blossom(context, R.drawable.blossom));
}
};
}
Create a class that extends Handler, and store a weak reference to the context. This will help prevent some memory issues.
public class SomeHandler extends Handler {
// A weak reference to the enclosing context
private WeakReference<Context> mContext;
public SomeHandler (Context context) {
mContext = new WeakReference<Context>(context);
}
public void handleMessage(Message msg) {
// Get an actual reference to the DownloadActivity
// from the WeakReference.
Context context=mContext.get();
...
}
}
What if you create a subclass which extends Handler? That way you could pass any parameters you want.
But just out of curiosity, why does the Blossom object require the context object? It's usually best to separate your logic from GUI dependencies.
i'm trying to fix this problem for more than 2 days now and have become quite desperate.
I want to write a 'Checkers-like' board game for android. The game engine itself is kinda complete but i have problems with updating the views.
I wrote a little example class to demonstrate my problem:
public class GameEngineView extends View {
private static final String TAG = GameEngineView.class.getSimpleName();
private int px;
private int py;
private int cx;
private int cy;
private boolean players_move;
private int clickx;
private int clicky;
Random rgen;
private RefreshHandler mRedrawHandler = new RefreshHandler();
class RefreshHandler extends Handler {
#Override
public void handleMessage(Message msg) {
GameEngineView.this.update();
GameEngineView.this.invalidate();
Log.d(TAG, "invalidate()");
}
public void sleep(long delayMillis) {
this.removeMessages(0);
sendMessageDelayed(obtainMessage(0), delayMillis);
}
};
public GameEngineView(Context context) {
super(context);
setFocusable(true);
players_move = true;
rgen = new Random();
}
public void update() {
updateGame();
Log.d(TAG, "update -> sleep handler");
mRedrawHandler.sleep(100);
}
public void updateGame() {
if(players_move) {
px = clickx;
py = clicky;
} else {
calcAIMove();
switchMove();
}
}
public void switchMove() {
players_move = !players_move;
}
public void calcAIMove() {
for(int i = 0; i < 20000; i++) {
cx = rgen.nextInt(getWidth());
cy = rgen.nextInt(getHeight());
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
Log.d(TAG, "event");
int eventaction = event.getAction();
if(eventaction == MotionEvent.ACTION_DOWN) {
Log.d(TAG, "action_down");
clickx = (int) event.getX();
clicky = (int) event.getY();
switchMove();
update();
}
return super.onTouchEvent(event);
}
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint green = new Paint();
green.setColor(Color.GREEN);
Paint red = new Paint();
red.setColor(Color.RED);
canvas.drawColor(Color.BLACK);
canvas.drawCircle(px, py, 25, green);
canvas.drawCircle(cx, cy, 25, red);
}
}
The function calcAIMove() just burns time to simulate a real evaluation of the position in a board game.
Now my Problem is: If the player clicks(makes a move) the green ball is first drawn when the ai move calculation has been complete. So both moves are drawn at the same time.
I wonder HOW to accomplish this:
-Player clicks
-green Ball is drawn
-AI calculates
-red ball is drawn
-and so on..
When searching the web i found a lot of game loop examples but they all need a Thread with constant polling.. it should be possible without this since the whole program runs sequentially .. right?
Hoping for advice.
thanks,
Dave
Here is how your game could work:
user makes a move
game view is updated
game switches to CPU's turn
sleep to simulate CPU player thinking (if move computation is trivial)
compute CPU's move
game view is updated
game switches to player's turn
There is no need for constant polling in a turn-based game like this. The only place you should have sleep is in step 4, so you can remove it from the other areas (no need for the old update() method which is just a delayed call to updateGame()).
One way to implement this is to simply delay the call to calcAIMove() and switchMove() by putting it into a Runnable and using Handler.postDelayed() or similar.
I don't see how you are disabling touch events when it is the CPU's turn, which can lead to a host of other problems if switchMove() and update() are still being called...
In your game loop you can use a instance of TimerTask to ensure certain delay between greenBall and some other drawing task. Game tutorials like Snake and LunarLander are great references on when and if you need to invalidate your View. Hope this helps a little!
ok so the answer provided by antonyt helped me solve this.. I provide the corrected code for other interested ones.
public class GameEngineView extends View {
private static final String TAG = GameEngineView.class.getSimpleName();
private int px;
private int py;
private int cx;
private int cy;
private boolean players_move;
private int clickx;
private int clicky;
Random rgen;
/**
* Create a simple handler that we can use to cause animation to happen. We
* set ourselves as a target and we can use the sleep()
* function to cause an update/invalidate to occur at a later date.
*/
private RefreshHandler mRedrawHandler = new RefreshHandler();
class RefreshHandler extends Handler {
#Override
public void handleMessage(Message msg) {
GameEngineView.this.update();
}
public void sleep(long delayMillis) {
this.removeMessages(0);
sendMessageDelayed(obtainMessage(0), delayMillis);
}
};
public GameEngineView(Context context) {
super(context);
setFocusable(true);
players_move = true;
rgen = new Random();
}
public void update() {
if(players_move) {
Log.d(TAG, "new player x");
px = clickx;
py = clicky;
GameEngineView.this.invalidate();
switchMove();
mRedrawHandler.sleep(100);
} else {
Log.d(TAG, "new ai x");
calcAIMove();
GameEngineView.this.invalidate();
switchMove();
}
Log.d(TAG, "update -> sleep handler");
}
public void switchMove() {
players_move = !players_move;
}
public void calcAIMove() {
for(int i = 0; i < 100000; i++) {
cx = rgen.nextInt(getWidth());
cy = rgen.nextInt(getHeight());
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
Log.d(TAG, "event");
int eventaction = event.getAction();
if(players_move && eventaction == MotionEvent.ACTION_DOWN) {
Log.d(TAG, "action_down");
clickx = (int) event.getX();
clicky = (int) event.getY();
update();
}
return super.onTouchEvent(event);
}
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.BLACK);
Paint green = new Paint();
green.setColor(Color.GREEN);
Paint red = new Paint();
red.setColor(Color.RED);
canvas.drawCircle(px, py, 25, green);
canvas.drawCircle(cx, cy, 25, red);
}
}
I'm not a programmer, but I'm trying to learn android development, and having a blast.
Lately I've hit a fork in the road, and I don't know that any of the directions I can identify will meet all my needs. This is where you (the experts) can help ;)
Endpoint: I want to have the user touch a ball, and drag it to any location on the screen. I would also like to animate this ball when it gets drawn, and when it gets dropped.
I can accomplish the dragging part using a custom class (that doesn't extend anything... just a class like is found in this tutorial: basic drag & drop, however, I don't know how to apply the tween animation to it since it's not a view.
I have also developed an animated version of an ImageView with my image in it, however, I can't manage to apply the same drag & drop functionality without using AbsoluteLayout, which I know is a no-no.
So... how do I move an ImageView around a ??? layout using MotionEvents, or how do I animate (using tweens defined in XML) a non-view based custom class?
Please ask questions if this is not clear. I don't know all the terminology as well as most of you might.
There is also a copy of this question on the anddev.org forums, so I'll keep this post updated with any responses I get over there.
Why can't you extend View? Then, you have complete control over how it draws because you can override the OnDraw() method. Just make the ColorBall class extend View. Change its position when you move and then invalidate just that one view and have it draw itself instead of having the DrawView class draw it.
Edit - Here is an example class
public class Card extends View
{
private Bitmap mImage;
private final Paint mPaint = new Paint();
private final Point mSize = new Point();
private final Point mStartPosition = new Point();
public Card(Context context)
{
super(context);
}
public final Bitmap getImage() { return mCardImage; }
public final void setImage(Bitmap image)
{
mImage = image;
setSize(mCardImage.getWidth(), mCardImage.getHeight());
}
#Override
protected void onDraw(Canvas canvas)
{
Point position = getPosition();
canvas.drawBitmap(mCardImage, position.x, position.y, mPaint);
}
public final void setPosition(final Point position)
{
mRegion.set(position.x, position.y, position.x + mSize.x, position.y + mSize.y);
}
public final Point getPosition()
{
Rect bounds = mRegion.getBounds();
return new Point(bounds.left, bounds.top);
}
public final void setSize(int width, int height)
{
mSize.x = width;
mSize.y = height;
Rect bounds = mRegion.getBounds();
mRegion.set(bounds.left, bounds.top, bounds.left + width, bounds.top + height);
}
public final Point getSize() { return mSize; }
#Override
public boolean onTouchEvent(MotionEvent event)
{
// Is the event inside of this view?
if(!mRegion.contains((int)event.getX(), (int)event.getY()))
{
return super.onTouchEvent(event);
}
if(event.getAction() == MotionEvent.ACTION_DOWN)
{
mStartPosition.x = (int)event.getX();
mStartPosition.y = (int)event.getY();
bringToFront();
onSelected();
return true;
}
else if(event.getAction() == MotionEvent.ACTION_MOVE)
{
int x = 0, y = 0;
if(mLock == DirectionLock.FREE || mLock == DirectionLock.HORIZONTAL_ONLY)
{
x = (int)event.getX() - mStartPosition.x;
}
if(mLock == DirectionLock.FREE || mLock == DirectionLock.VERTICAL_ONLY)
{
y = (int)event.getY() - mStartPosition.y;
}
mRegion.translate(x, y);
mStartPosition.x = (int)event.getX();
mStartPosition.y = (int)event.getY();
invalidate();
return true;
}
else
{
return super.onTouchEvent(event);
}
}
}
I'm not a programmer, but I'm trying to learn android development, and having a blast.
Lately I've hit a fork in the road, and I don't know that any of the directions I can identify will meet all my needs. This is where you (the experts) can help ;)
Endpoint: I want to have the user touch a ball, and drag it to any location on the screen. I would also like to animate this ball when it gets drawn, and when it gets dropped.
I can accomplish the dragging part using a custom class (that doesn't extend anything... just a class like is found in this tutorial: basic drag & drop, however, I don't know how to apply the tween animation to it since it's not a view.
I have also developed an animated version of an ImageView with my image in it, however, I can't manage to apply the same drag & drop functionality without using AbsoluteLayout, which I know is a no-no.
So... how do I move an ImageView around a ??? layout using MotionEvents, or how do I animate (using tweens defined in XML) a non-view based custom class?
Please ask questions if this is not clear. I don't know all the terminology as well as most of you might.
There is also a copy of this question on the anddev.org forums, so I'll keep this post updated with any responses I get over there.
Why can't you extend View? Then, you have complete control over how it draws because you can override the OnDraw() method. Just make the ColorBall class extend View. Change its position when you move and then invalidate just that one view and have it draw itself instead of having the DrawView class draw it.
Edit - Here is an example class
public class Card extends View
{
private Bitmap mImage;
private final Paint mPaint = new Paint();
private final Point mSize = new Point();
private final Point mStartPosition = new Point();
public Card(Context context)
{
super(context);
}
public final Bitmap getImage() { return mCardImage; }
public final void setImage(Bitmap image)
{
mImage = image;
setSize(mCardImage.getWidth(), mCardImage.getHeight());
}
#Override
protected void onDraw(Canvas canvas)
{
Point position = getPosition();
canvas.drawBitmap(mCardImage, position.x, position.y, mPaint);
}
public final void setPosition(final Point position)
{
mRegion.set(position.x, position.y, position.x + mSize.x, position.y + mSize.y);
}
public final Point getPosition()
{
Rect bounds = mRegion.getBounds();
return new Point(bounds.left, bounds.top);
}
public final void setSize(int width, int height)
{
mSize.x = width;
mSize.y = height;
Rect bounds = mRegion.getBounds();
mRegion.set(bounds.left, bounds.top, bounds.left + width, bounds.top + height);
}
public final Point getSize() { return mSize; }
#Override
public boolean onTouchEvent(MotionEvent event)
{
// Is the event inside of this view?
if(!mRegion.contains((int)event.getX(), (int)event.getY()))
{
return super.onTouchEvent(event);
}
if(event.getAction() == MotionEvent.ACTION_DOWN)
{
mStartPosition.x = (int)event.getX();
mStartPosition.y = (int)event.getY();
bringToFront();
onSelected();
return true;
}
else if(event.getAction() == MotionEvent.ACTION_MOVE)
{
int x = 0, y = 0;
if(mLock == DirectionLock.FREE || mLock == DirectionLock.HORIZONTAL_ONLY)
{
x = (int)event.getX() - mStartPosition.x;
}
if(mLock == DirectionLock.FREE || mLock == DirectionLock.VERTICAL_ONLY)
{
y = (int)event.getY() - mStartPosition.y;
}
mRegion.translate(x, y);
mStartPosition.x = (int)event.getX();
mStartPosition.y = (int)event.getY();
invalidate();
return true;
}
else
{
return super.onTouchEvent(event);
}
}
}