Im making a game on android where theres an image and u have to drag and move it. however as i drag it several images are created on the path where the image is dragged. please look at my code and help
package com.saad.alien;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.RectF;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnTouchListener;
public class Game extends Activity implements OnTouchListener {
CustomView Cview;
float x, y, left = 0, top = 0, right = 0, bottom = 0;
float dx, dy;
Bitmap man;
int done = 0;
RectF rman = new RectF(50, 50, 150, 150);
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
Cview = new CustomView(this);
Cview.setOnTouchListener(this);
x = 50;
y = 600;
dx = dy = 0;
man = BitmapFactory.decodeResource(getResources(), R.drawable.man);
setContentView(Cview);
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
Cview.pause();
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
Cview.resume();
}
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// x = event.getX();
// y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
dx = event.getX();
dy = event.getY();
float length = x + man.getWidth();
float height = y + man.getHeight();
if (dx > x && dx < length && dy > y && dy < height) {
done = 1;
}
break;
case MotionEvent.ACTION_MOVE:
if (done == 1) {
x = event.getX();
y = event.getY();
}
break;
case MotionEvent.ACTION_UP:
if (done == 1) {
x = event.getX();
y = event.getY();
done = 0;
}
break;
}
return true;
}
public class CustomView extends SurfaceView implements Runnable {
SurfaceHolder ourHolder;
Thread ourThread = null;
boolean isRunning = false;
public CustomView(Context context) {
super(context);
ourHolder = getHolder();
}
public void pause() {
isRunning = false;
while (true) {
try {
ourThread.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
ourThread = null;
}
public void resume() {
isRunning = true;
ourThread = new Thread(this);
ourThread.start();
}
public void run() {
while (isRunning) {
if (!ourHolder.getSurface().isValid())
continue;
Canvas can = ourHolder.lockCanvas();
left = x;
right = (x + man.getWidth());
top = y;
bottom = (y + man.getHeight());
rman.set(left, top, right, bottom);
can.drawBitmap(man, null, rman, null);
ourHolder.unlockCanvasAndPost(can);
}
}
}
}
You need to clear the canvas at each frame before drawing on it.
For instance, something like:
Canvas.drawColor(Color.BLACK)
Related
How to put an image on another imageview (already an set image ) and save it as combined image?
Below MoveBitmap class Moves bitmap but nothing return i just want to make return a bitmap
i want to Achieve that
:put an image on image (which already set in imageview) and then want to make movable inner image (second image) and save these both as combined image ..... i m confused how to accomplish that .... can anyone tell me ?
A class that moves the bitmap
package "name";
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
public class MoveBitmap extends Activity {
public class TouchView extends View {
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
private float x, y;
boolean touching = false;
Bitmap bm = BitmapFactory.decodeResource(
getResources(),
R.drawable.n);
int bm_x = 0;
int bm_y = 0;
int bm_w = bm.getWidth();
int bm_h = bm.getHeight();
int bm_offsetx;
int bm_offsety;
boolean dm_touched = false;
public TouchView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(1);
paint.setColor(Color.WHITE);
if(touching){
canvas.drawRect(x, y, x+bm_w, y+bm_h, paint);
}
canvas.drawBitmap(bm, bm_x, bm_y, paint);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec),
MeasureSpec.getSize(heightMeasureSpec));
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
int action = event.getAction();
switch(action){
case MotionEvent.ACTION_MOVE:
x = event.getX();
y = event.getY();
touching = true;
if(dm_touched){
bm_x = (int)x - bm_offsetx;
bm_y = (int)y - bm_offsety;
}
break;
case MotionEvent.ACTION_DOWN:
x = event.getX();
y = event.getY();
touching = true;
//check if bm touched
if((x > bm_x)
&& (x < bm_x+bm_w)
&& (y > bm_y)
&& (y < bm_y+bm_h)){
bm_offsetx = (int)x - bm_x;
bm_offsety = (int)y - bm_y;
dm_touched = true;
}
break;
case MotionEvent.ACTION_UP:
default:
dm_touched = false;
touching = false;
}
invalidate();
return true;
}
}
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new TouchView(this));
}
}
public Bitmap screenShot(View view) {
Bitmap bitmap = Bitmap.createBitmap(view.getWidth(),
view.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
return bitmap;
}
You can use drawing cache from view with this method:
public static Bitmap loadBitmapFromView(View v) {
Bitmap bitmap;
v.setDrawingCacheEnabled(true);
bitmap = Bitmap.createBitmap(v.getDrawingCache());
v.setDrawingCacheEnabled(false);
}
But you need to have a layout (for example, Frame Layout) with two ImageViews. First as background (initial image) and second as movable image. Then place views in way you need and then make a screenshot with a function above using a FrameLayout as view.
I have created two different projects in android for rotating and Drag and drop. Those are working fine. But, I need to integrate those in a single project. Please help,
Thanks in advance.
Both MainActivity code displayed below:
//This is draganddrop MainActivity.java code
package com.example.draganddrop;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnTouchListener;
public class MainActivity extends Activity implements OnTouchListener
{
MySurfaceView MSV;
float x, y;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
MSV = new MySurfaceView(this);
MSV.setOnTouchListener(this);
x = 0;
y = 0;
setContentView(MSV);
}
protected void onPause()
{
super.onPause();
MSV.pause();
}
protected void onResume()
{
super.onResume();
MSV.resume();
}
#Override
public boolean onTouch(View v, MotionEvent event)
{
x = event.getX();
y = event.getY();
return true;
}
public class MySurfaceView extends SurfaceView implements Runnable
{
SurfaceHolder ourHolder;
Thread ourThread = null;
boolean isRunning = false;
public MySurfaceView(Context context)
{
super(context);
ourHolder = getHolder();
}
public void pause()
{
isRunning = false;
while(true)
{
try
{
ourThread.join();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
break;
}
ourThread = null;
}
public void resume()
{
isRunning = true;
ourThread = new Thread(this);
ourThread.start();
}
#Override
public void run()
{
while(isRunning)
{
if(!ourHolder.getSurface().isValid())
continue;
Canvas canvas = ourHolder.lockCanvas();
canvas.drawRGB(12, 12, 150);
if(x != 0 && y != 0)
{
Bitmap test = BitmapFactory.decodeResource(getResources(), R.drawable.colorball);
canvas.drawBitmap(test, x-(test.getWidth()/2), y-(test.getHeight()/2), null);
}
ourHolder.unlockCanvasAndPost(canvas);
}
}
}
}
//This is rotate MainActivity.java code
package com.example.rotatetest;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
public class MainActivity extends Activity implements OnTouchListener {
private ImageView mCircle;
private double mCurrAngle = 0;
private double mPrevAngle = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mCircle = (ImageView) findViewById(R.id.imageView1);
mCircle.setOnTouchListener( this); // Your activity should implement OnTouchListener
}
#Override
public boolean onTouch(View v, MotionEvent event) {
final float xc = mCircle.getWidth() / 2;
final float yc = mCircle.getHeight() / 2;
final float x = event.getX();
final float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
mCircle.clearAnimation();
mCurrAngle = Math.toDegrees(Math.atan2(x - xc, yc - y));
break;
}
case MotionEvent.ACTION_MOVE: {
mPrevAngle = mCurrAngle;
mCurrAngle = Math.toDegrees(Math.atan2(x - xc, yc - y));
animate(mPrevAngle, mCurrAngle, 0);
break;
}
case MotionEvent.ACTION_UP : {
mPrevAngle = mCurrAngle = 0;
break;
}
}
return true;
}
private void animate(double fromDegrees, double toDegrees, long durationMillis) {
final RotateAnimation rotate = new RotateAnimation((float) fromDegrees, (float) toDegrees,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
rotate.setDuration(durationMillis);
rotate.setFillEnabled(true);
rotate.setFillAfter(true);
mCircle.startAnimation(rotate);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
I want to draw circle, whenever user taps on a custom view, and based on tap count circle color changes.
Single Tap : YELLOW CIRCLE
Double Tap : GREEN CIRCLE
Triple Tap : RED COLOR
Problem is that, i made one custom view that will count tap event based on time, but some time it miss the first tap. which cause the problem in view.
Following code shows all my effort to make above custom view.
TripleTapView
package com.slk.car_rating_app;
import java.util.ArrayList;
import java.util.Date;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.RectF;
import android.os.CountDownTimer;
import android.view.MotionEvent;
import android.view.View;
public class TripleTapView extends View {
// Set the tap delay in milliseconds
protected static final long TAP_MAX_DELAY = 500L;
// Radius to capture tap within bound
final static int RADIUS = 30;
// Store all points with tap count
public ArrayList<CustomPoint> point = new ArrayList<CustomPoint>();
// Context to access view
Context context;
Paint paint;
private long thisTime = 0, prevTime = 0;
private boolean firstTap = true, doubleTap = false;;
float stopX, stopY, startX, startY;
RectF area_rect;
TapCounter tapCounter = new TapCounter(TAP_MAX_DELAY, TAP_MAX_DELAY);
public TripleTapView(Context context) {
super(context);
this.context = context;
paint = new Paint();
paint.setColor(Color.GREEN);
paint.setAntiAlias(true);
paint.setDither(true);
paint.setStyle(Paint.Style.FILL);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStrokeWidth(2);
}
#SuppressLint("DrawAllocation")
#Override
protected void onDraw(final Canvas canvas) {
super.onDraw(canvas);
for (CustomPoint point_temp : point) {
// For changing tap circle color based on tap count
switch (point_temp.count) {
case 1:
paint.setColor(Color.YELLOW);
break;
case 2:
paint.setColor(Color.GREEN);
break;
case 3:
paint.setColor(Color.RED);
break;
}
canvas.drawCircle(point_temp.point.x, point_temp.point.y, 10, paint);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
stopX = event.getX();
stopY = event.getY();
if (firstTap) {
addFirstTap();
} else if (doubleTap) {
prevTime = thisTime;
thisTime = new Date().getTime();
if (thisTime > prevTime) {
if ((thisTime - prevTime) <= TAP_MAX_DELAY) {
if (area_rect.contains(stopX, stopY))
doubleTap = false;
else {
addPoint(1);
addFirstTap();
}
} else {
addPoint(1);
firstTap = true;
}
} else {
firstTap = true;
}
} else {
prevTime = thisTime;
thisTime = new Date().getTime();
if (thisTime > prevTime) {
if ((thisTime - prevTime) <= TAP_MAX_DELAY) {
if (area_rect.contains(stopX, stopY)) {
addPoint(3);
firstTap = true;
} else {
addPoint(2);
addFirstTap();
}
} else {
addPoint(2);
firstTap = true;
}
} else {
firstTap = true;
}
}
}
return true;
}
void addPoint(int tapCount) {
point.add(new CustomPoint(new PointF(startX, startY), tapCount));
invalidate();
}
void addFirstTap() {
thisTime = new Date().getTime();
firstTap = false;
doubleTap = true;
startX = stopX;
startY = stopY;
area_rect = new RectF(stopX - RADIUS, stopY - RADIUS, stopX + RADIUS,
stopY + RADIUS);
tapCounter.resetCounter();
}
class TapCounter extends CountDownTimer {
public TapCounter(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onFinish() {
if (doubleTap) {
prevTime = thisTime;
thisTime = new Date().getTime();
if (thisTime > prevTime) {
if ((thisTime - prevTime) <= TAP_MAX_DELAY) {
doubleTap = false;
} else {
addPoint(1);
firstTap = true;
}
} else {
firstTap = true;
}
} else if (!firstTap && !doubleTap) {
prevTime = thisTime;
thisTime = new Date().getTime();
if (thisTime > prevTime) {
if ((thisTime - prevTime) <= TAP_MAX_DELAY) {
addPoint(2);
firstTap = true;
}
} else {
firstTap = true;
}
}
}
#Override
public void onTick(long millisUntilFinished) {
}
public void resetCounter() {
start();
}
}
}
Please help me to fix this issue.
This code will do what you need. I simplified your class.
import java.util.ArrayList;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.RectF;
import android.os.CountDownTimer;
import android.view.MotionEvent;
import android.view.View;
public class TripleTapView extends View {
// Set the tap delay in milliseconds
protected static final long TAP_MAX_DELAY = 500L;
// Radius to capture tap within bound
private final static int RADIUS = 30;
// Store all points with tap count
public ArrayList<CustomPoint> _points = new ArrayList<CustomPoint>();
Context _context;
Paint _paint;
TapCounter _tapCounter = new TapCounter(TAP_MAX_DELAY, TAP_MAX_DELAY);
public TripleTapView(Context context) {
super(context);
_context = context;
_paint = new Paint();
_paint.setAntiAlias(true);
_paint.setDither(true);
_paint.setStyle(Paint.Style.FILL);
_paint.setStrokeJoin(Paint.Join.ROUND);
_paint.setStrokeCap(Paint.Cap.ROUND);
_paint.setStrokeWidth(2);
}
#Override
protected void onDraw(final Canvas canvas) {
super.onDraw(canvas);
for (CustomPoint point_temp : _points) {
// For changing tap circle color based on tap count
switch (point_temp.count) {
case 1:
_paint.setColor(Color.YELLOW);
break;
case 2:
_paint.setColor(Color.GREEN);
break;
case 3:
_paint.setColor(Color.RED);
break;
}
canvas.drawCircle(point_temp.point.x, point_temp.point.y, 10,
_paint);
}
}
private RectF _lastTapArea;
private int _lastTapCount = 0;
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
_tapCounter.resetCounter();
float x = event.getX();
float y = event.getY();
if (_lastTapArea != null) {
if (_lastTapArea.contains(x, y)) {
if (_lastTapCount < 3) {
_lastTapCount++;
} else {
addPoint(_lastTapArea.centerX(),
_lastTapArea.centerY(), _lastTapCount);
_lastTapCount = 1;
}
} else {
addPoint(_lastTapArea.centerX(), _lastTapArea.centerY(),
_lastTapCount);
_lastTapCount = 1;
_lastTapArea = new RectF(x - RADIUS, y - RADIUS,
x + RADIUS, y + RADIUS);
}
} else {
_lastTapCount = 1;
_lastTapArea = new RectF(x - RADIUS, y - RADIUS, x + RADIUS, y
+ RADIUS);
}
return true;
}
return false;
}
void addPoint(float x, float y, int tapCount) {
_points.add(new CustomPoint(new PointF(x, y), tapCount));
invalidate();
}
class TapCounter extends CountDownTimer {
public TapCounter(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onFinish() {
if (_lastTapArea != null) {
if (_lastTapCount > 0)
addPoint(_lastTapArea.centerX(), _lastTapArea.centerY(),
_lastTapCount);
_lastTapCount = 0;
_lastTapArea = null;
}
}
#Override
public void onTick(long millisUntilFinished) {
}
public void resetCounter() {
start();
}
}
}
I am making an android game that should display a message that you have lost a certain point. But however, its failing of some reason that i cant possibly figure out. On checkLivesLeftValue(), it calls onMethod() if the user has used up all of the three lives he got. But then, when i am creating a toast, the application fails, why???
This is my java code:
import java.util.ArrayList;
import android.app.AlertDialog;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.TextView;
import android.widget.Toast;
public class ExampleView extends SurfaceView implements SurfaceHolder.Callback
{
class ExampleThread extends Thread
{
private ArrayList<Parachuter> parachuters;
private Bitmap parachuter;
private Paint black;
private boolean running;
private SurfaceHolder mSurfaceHolder;
private Context mContext;
private Handler mHandler;
private GameScreenActivity mActivity;
private long frameRate;
private boolean loading;
public float x;
public float y;
public MediaPlayer mp1;
public int parachuterIndexToResetAndDelete;
public int canvasGetWidth;
public int livesLeftValue;
public ExampleThread(SurfaceHolder sHolder, Context context, Handler handler)
{
mSurfaceHolder = sHolder;
mHandler = handler;
mContext = context;
mActivity = (GameScreenActivity) context;
parachuters = new ArrayList<Parachuter>();
parachuter = BitmapFactory.decodeResource(getResources(), R.drawable.parachuteman);
black = new Paint();
black.setStyle(Paint.Style.FILL);
black.setColor(Color.WHITE);
running = true;
// This equates to 26 frames per second.
frameRate = (long) (1000 / 26);
loading = true;
}
#Override
public void run()
{
while (running)
{
Canvas c = null;
try
{
c = mSurfaceHolder.lockCanvas();
synchronized (mSurfaceHolder)
{
long start = System.currentTimeMillis();
doDraw(c);
long diff = System.currentTimeMillis() - start;
if (diff < frameRate)
Thread.sleep(frameRate - diff);
}
} catch (InterruptedException e)
{
}
finally
{
if (c != null)
{
mSurfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
protected void doDraw(Canvas canvas)
{
canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), black);
canvasGetWidth = canvas.getWidth();
//Draw
for (int i = 0; i < parachuters.size(); i++)
{
canvas.drawBitmap(parachuter, parachuters.get(i).getX(), parachuters.get(i).getY(), null);
parachuters.get(i).tick();
}
//Remove
for (int i = 0; i < parachuters.size(); i++)
{
if (parachuters.get(i).getY() > canvas.getHeight()) {
parachuters.remove(i);
onPlaySound();
onMethod();
checkLivesLeftValue();
}
}
}
public void onPlaySound()
{
try {
mp1 = MediaPlayer.create(getContext(), R.raw.bombsound);
mp1.start();
} catch (Exception e) {
e.printStackTrace();
mp1.release();
}
}
public void onMethod() {
Toast.makeText(getContext(), "You lost!", 15).show();
}
private void checkLivesLeftValue() {
// TODO Auto-generated method stub
if (livesLeftValue == 3) {
//Message to display: "You lost!"
onMethod();
}
else {
livesLeftValue = livesLeftValue + 1;
}
}
public boolean onTouchEvent(MotionEvent event)
{
if (event.getAction() != MotionEvent.ACTION_DOWN)
return false;
float x1 = event.getX();
float y1 = event.getY();
initiateDrawParachuters();
return true;
}
public void initiateDrawParachuters()
{
drawParachuter1();
}
private void drawParachuter1() {
// TODO Auto-generated method stub
//Parachuter nr. 1
x = 68;
y = 40;
Parachuter p = new Parachuter(x, y);
parachuters.add(p);
drawParachuter2();
}
private void drawParachuter2() {
// TODO Auto-generated method stub
//Parachuter nr. 2
x = 100;
y = 80;
Parachuter p = new Parachuter(x, y);
parachuters.add(p);
drawParachuter3();
}
private void drawParachuter3() {
// TODO Auto-generated method stub
//Parachuter nr. 3
x = 150;
y = 120;
Parachuter p = new Parachuter(x, y);
parachuters.add(p);
drawParachuter4();
}
private void drawParachuter4() {
// TODO Auto-generated method stub
//Parachuter nr. 4
x = 170;
y = 150;
Parachuter p = new Parachuter(x, y);
parachuters.add(p);
drawParachuter5();
}
private void drawParachuter5() {
// TODO Auto-generated method stub
//Parachuter nr. 5
x = 180;
y = 170;
Parachuter p = new Parachuter(x, y);
parachuters.add(p);
drawParachuter6();
}
private void drawParachuter6() {
// TODO Auto-generated method stub
//Parachuter nr. 6
x = 200;
y = 180;
Parachuter p = new Parachuter(x, y);
parachuters.add(p);
}
public void drawParachuters()
{
Parachuter p = new Parachuter(x, y);
parachuters.add(p);
Toast.makeText(getContext(), "x=" + x + " y=" + y, 15).show();
}
public void setRunning(boolean bRun)
{
running = bRun;
}
public boolean getRunning()
{
return running;
}
}
/** Handle to the application context, used to e.g. fetch Drawables. */
private Context mContext;
/** Pointer to the text view to display "Paused.." etc. */
private TextView mStatusText;
/** The thread that actually draws the animation */
private ExampleThread eThread;
public ExampleView(Context context)
{
super(context);
// register our interest in hearing about changes to our surface
SurfaceHolder holder = getHolder();
holder.addCallback(this);
// create thread only; it's started in surfaceCreated()
eThread = new ExampleThread(holder, context, new Handler()
{
#Override
public void handleMessage(Message m)
{
// mStatusText.setVisibility(m.getData().getInt("viz"));
// mStatusText.setText(m.getData().getString("text"));
}
});
setFocusable(true);
}
#Override
public boolean onTouchEvent(MotionEvent event)
{
return eThread.onTouchEvent(event);
}
public ExampleThread getThread()
{
return eThread;
}
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3)
{
// TODO Auto-generated method stub
}
public void surfaceCreated(SurfaceHolder holder)
{
if (eThread.getState() == Thread.State.TERMINATED)
{
eThread = new ExampleThread(getHolder(), getContext(), getHandler());
eThread.start();
}
else
{
eThread.start();
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder)
{
boolean retry = true;
eThread.setRunning(false);
while (retry)
{
try
{
eThread.join();
retry = false;
}
catch (InterruptedException e)
{
}
}
}
}
And this is my logcat output:
03-24 16:32:59.442: W/dalvikvm(363): threadid=7: thread exiting with uncaught exception (group=0x4001d800)
03-24 16:32:59.641: E/AndroidRuntime(363): FATAL EXCEPTION: Thread-8
03-24 16:32:59.641: E/AndroidRuntime(363): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
03-24 16:32:59.641: E/AndroidRuntime(363): at android.os.Handler.<init>(Handler.java:121)
03-24 16:32:59.641: E/AndroidRuntime(363): at android.widget.Toast.<init>(Toast.java:68)
03-24 16:32:59.641: E/AndroidRuntime(363): at android.widget.Toast.makeText(Toast.java:231)
03-24 16:32:59.641: E/AndroidRuntime(363): at com.mysoftwaremobileapps.ParachuteHunter.ExampleView$ExampleThread.onMethod(ExampleView.java:135)
03-24 16:32:59.641: E/AndroidRuntime(363): at com.mysoftwaremobileapps.ParachuteHunter.ExampleView$ExampleThread.doDraw(ExampleView.java:116)
03-24 16:32:59.641: E/AndroidRuntime(363): at com.mysoftwaremobileapps.ParachuteHunter.ExampleView$ExampleThread.run(ExampleView.java:79)
03-24 16:33:03.842: I/Process(363): Sending signal. PID: 363 SIG: 9
You are creating a Toast from Thread, which is not having a Looper attached to it. The simplest solution is to create a Toast from UI thread which is having Looper by default.
Also, you already having a Handler, which is created inside a View constructor. You can use this Handler to post some Runnable to UI thread and create Toast there.
public void onMethod() {
mHandler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getContext(), "You lost!", 15).show();
}
});
}
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;
}
}