I have a class called OurView. I have 3 Buttons that call moveImage() and pass it two numbers depending on which Button it is.
moveImage() is supposed to change the value of xCoord and yCoord, which it seems to do. When xCoord and yCoord are printed from moveImage() they display the correct values.
But when printed from delay() or doDraw() they display the original value of 500.
Am I doing something incorrect that causes the variables to not be updated?
Here is the class OurView:
package com.thatoneprogrammerkid.gameminimum;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class OurView extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder holder;
private Handler handler = new Handler();
private Bitmap testimg;
private int xCoord = 500;
private int yCoord = 500;
int xPos;
int yPos;
public OurView(Context context) {
super(context);
init();
}
public OurView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public OurView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
holder = getHolder();
holder.addCallback(this);
testimg = BitmapFactory.decodeResource(getResources(),R.drawable.testimg);
}
void moveImage(int xChange, int yChange) {
this.xCoord = this.xCoord + xChange;
this.yCoord = this.yCoord + yChange;
System.out.println("Move Image");
printCoords();
}
void printCoords() {
System.out.println(xCoord);
System.out.println(yCoord);
}
void delay() {
System.out.println("Delay");
printCoords();
handler.postDelayed(new Runnable() {
public void run() {
Canvas canvas = getHolder().lockCanvas();
System.out.println("Run");
printCoords();
if(canvas != null){
synchronized (getHolder()) {
doDraw(canvas, xCoord, yCoord);
}
holder.unlockCanvasAndPost(canvas);
}
}
}, 33);
}
void doDraw(Canvas canvas, int x, int y) {
xPos = this.xCoord + (testimg.getWidth()/2);
yPos = this.yCoord + (testimg.getHeight()/2);
System.out.println("Draw");
printCoords();
canvas.drawARGB(255, 55, 255, 255);
canvas.drawBitmap(testimg, x, y, null);
delay();
}
#Override
public void surfaceCreated(final SurfaceHolder holder) {
delay();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {}
}
Here is the class the handles the button presses:
package com.thatoneprogrammerkid.gameminimum;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
public class SurfaceViewExample extends Activity {
OurView gameView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
gameView = new OurView(this);
setContentView(R.layout.activity_surface_view_example);
}
public void arrowPressed(View view) {
switch (view.getId()) {
case R.id.arrowLeft:
gameView.moveImage(-1,0);
break;
case R.id.arrowRight:
gameView.moveImage(1,0);
break;
case R.id.arrowUp:
gameView.moveImage(0,1);
break;
}
}
}
EDIT:
To clarify, after pressing the button 10 times the printCoords() in moveImage() displays the following:
510
500
and the printCoords() in all the other locations displays the following:
500
500
If what I guess is right , the reference you use to call moveImage() and delay() are not the same . Maybe you did something like:
ourView = new OurView();
after calling moveImage.
Related
I'm using the below Java class (Found on the web) as a countdown timer circle animation, The issue is that on some devices like Huawei Mate 10 Pro & Huawei G8 the animation finishes sooner than it is supposed to while on the other couple of devices that I've tested its working perfectly.
For example on Mate 10 pro, when I call the class to start the timer with '10' as the parameter (circle animation supposed to be completed in 10 seconds but it goes faster and finishes in exactly half the time-5 seconds!-) while in another device with same Android version (Android 10) it's working perfectly (Completes in 10 seconds).
So I figured the android version is not the problem here, Any idea what may be the issue ??
package com.maxwellforest.blogtimer;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;
import com.borsam.bleexample.R;
import java.util.concurrent.TimeUnit;
/**
* Countdown timer view.
*
* #author Mike Gouline
*/
public class TimerView extends View {
private static final int ARC_START_ANGLE = 270; // 12 o'clock
private static final float THICKNESS_SCALE = 0.03f;
private Bitmap mBitmap;
private Canvas mCanvas;
private RectF mCircleOuterBounds;
private RectF mCircleInnerBounds;
private Paint mCirclePaint;
private Paint mEraserPaint;
private float mCircleSweepAngle;
private ValueAnimator mTimerAnimator;
public TimerView(Context context) {
this(context, null);
}
public TimerView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public TimerView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
int circleColor = R.color.colorPrimary;
if (attrs != null) {
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.TimerView);
if (ta != null) {
circleColor = ta.getColor(R.styleable.TimerView_circleColor, circleColor);
ta.recycle();
}
}
mCirclePaint = new Paint();
mCirclePaint.setAntiAlias(true);
mCirclePaint.setColor(circleColor);
mEraserPaint = new Paint();
mEraserPaint.setAntiAlias(true);
mEraserPaint.setColor(Color.TRANSPARENT);
mEraserPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
}
#SuppressWarnings("SuspiciousNameCombination")
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec); // Trick to make the view square
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
if (w != oldw || h != oldh) {
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mBitmap.eraseColor(Color.TRANSPARENT);
mCanvas = new Canvas(mBitmap);
}
super.onSizeChanged(w, h, oldw, oldh);
updateBounds();
}
#Override
protected void onDraw(Canvas canvas) {
mCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
if (mCircleSweepAngle > 0f) {
mCanvas.drawArc(mCircleOuterBounds, ARC_START_ANGLE, mCircleSweepAngle, true, mCirclePaint);
mCanvas.drawOval(mCircleInnerBounds, mEraserPaint);
}
canvas.drawBitmap(mBitmap, 0, 0, null);
}
public void start(int secs) {
stop();
mTimerAnimator = ValueAnimator.ofFloat(0f, 1f);
mTimerAnimator.setDuration(TimeUnit.SECONDS.toMillis(secs));//(secs*1000);
mTimerAnimator.setInterpolator(new LinearInterpolator());
mTimerAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
drawProgress((float) animation.getAnimatedValue());
}
});
mTimerAnimator.start();
}
public void stop() {
if (mTimerAnimator != null && mTimerAnimator.isRunning()) {
mTimerAnimator.cancel();
mTimerAnimator = null;
drawProgress(0f);
}
}
private void drawProgress(float progress) {
mCircleSweepAngle = 360 * progress;
invalidate();
}
private void updateBounds() {
final float thickness = getWidth() * THICKNESS_SCALE;
mCircleOuterBounds = new RectF(0, 0, getWidth(), getHeight());
mCircleInnerBounds = new RectF(
mCircleOuterBounds.left + thickness,
mCircleOuterBounds.top + thickness,
mCircleOuterBounds.right - thickness,
mCircleOuterBounds.bottom - thickness);
invalidate();
}
}
There is an option in Developer options "Animator duration scale", by default this value is 1x if they are different for devices then you may experience slower or faster animations based on the value set.
I am new to coding and to java and android. I am making an app that has multiple canvas views (where a person can draw lines with their finger) in multiple fragments (requested to be like this). I have managed to get the fragments to work and to draw lines on each canvas. Next, I want to be able to save the lines drawn by the user when the user goes to a different fragment or closes the app and when the user comes back to a fragment, the drawing for that fragment will still be there, and can continue editing it by adding more lines or clear it by hitting Clear, the same should happen for other fragments that should have their respective drawings.
I was previously told about the interface Parcelable and have made some steps to implement it but I am finding it hard to understand what I am doing and having trouble reading in an ArrayList. The error is stating that it is expecting ClassLoader but being provided with an ArrayList (I hope in the right place), and that's if I make the getter static but that creates an error: Non-static field 'paths' cannot be referenced from a static context in the getter in the PaintView class (this controls the drawing). I get a similar static context message for the readArrayList method in the FingerPath class. Once this is figured out, I will need to find out how to bring the relevant, saved drawing back to the canvas when the fragment is opened which I am not sure how, I think when the Bundle isn't equal to null but not sure.
I'll show the code below (right now it is on a test app)
FingerPath class
import android.graphics.Path;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.ArrayList;
public class FingerPath implements Parcelable {
public int color;
public boolean emboss;
public boolean blur;
public int strokeWidth;
public Path path;
public FingerPath(int color, boolean emboss, boolean blur, int strokeWidth, Path path) {
this.color = color;
this.emboss = emboss;
this.blur = blur;
this.strokeWidth = strokeWidth;
this.path = path;
}
protected FingerPath(Parcel in) {
color = in.readInt();
emboss = in.readByte() != 0;
blur = in.readByte() != 0;
strokeWidth = in.readInt();
//line below causing me issues
path = in.readArrayList(PaintView.getPaths());
}
public static final Creator<FingerPath> CREATOR = new Creator<FingerPath>() {
#Override
public FingerPath createFromParcel(Parcel in) {
return new FingerPath(in);
}
#Override
public FingerPath[] newArray(int size) {
return new FingerPath[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeInt(color);
parcel.writeByte((byte) (emboss ? 1 : 0));
parcel.writeByte((byte) (blur ? 1 : 0));
parcel.writeInt(strokeWidth);
//parcel.writeParcelableArray(PaintView.getPaths(), 0);
}
}
PaintView
Controls what happens when the user starts drawing
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.EmbossMaskFilter;
import android.graphics.MaskFilter;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import java.util.ArrayList;
public class PaintView extends View {
public static int BRUSH_SIZE = 10;
public static final int DEFAULT_COLOR = Color.WHITE;
public static int DEFAULT_BG_COLOR = Color.GRAY;
private static final float TOUCH_TOLERANCE = 4;
private float mX, mY;
private Path mPath;
private Paint mPaint;
private ArrayList<FingerPath> paths = new ArrayList<>();
private int currentColor;
private int backgroundColor = DEFAULT_BG_COLOR;
private int strokeWidth;
private boolean emboss;
private boolean blur;
private MaskFilter mEmboss;
private MaskFilter mBlur;
private Bitmap mBitmap;
private Canvas mCanvas;
private Paint mBitmapPaint = new Paint(Paint.DITHER_FLAG);
public PaintView(Context context) {
this(context, null);
}
public PaintView(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(DEFAULT_COLOR);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setXfermode(null);
mPaint.setAlpha(0xff);
mEmboss = new EmbossMaskFilter(new float[] {1, 1, 1}, 0.4f, 6, 3.5f);
mBlur = new BlurMaskFilter(5, BlurMaskFilter.Blur.NORMAL);
}
//the getter in question
public ArrayList getPaths() {
return paths;
}
public void init(DisplayMetrics metrics) {
int height = metrics.heightPixels;
int width = metrics.widthPixels;
mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
currentColor = DEFAULT_COLOR;
strokeWidth = BRUSH_SIZE;
}
public void normal() {
emboss = false;
blur = false;
}
public void clear() {
backgroundColor = DEFAULT_BG_COLOR;
paths.clear();
normal();
invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
canvas.save();
mCanvas.drawColor(backgroundColor);
for (FingerPath fp: paths) {
mPaint.setColor(fp.color);
mPaint.setStrokeWidth(fp.strokeWidth);
mPaint.setMaskFilter(null);
if (fp.emboss)
mPaint.setMaskFilter(mEmboss);
else if (fp.blur)
mPaint.setMaskFilter(mBlur);
mCanvas.drawPath(fp.path, mPaint);
}
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.restore();
}
private void touchStart(float x, float y) {
mPath = new Path();
FingerPath fp = new FingerPath(currentColor, emboss, blur, strokeWidth, mPath);
paths.add(fp);
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
}
private void touchMove(float x, float y) {
float dx = Math.abs(x-mX);
float dy = Math.abs(y-mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
}
}
private void touchUp() {
mPath.lineTo(mX, mY);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN :
touchStart(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE :
touchMove(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP :
touchUp();
invalidate();
break;
}
return true;
}
}
Here's an example of a fragment
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
public class LineLHwFragment extends Fragment {
private PaintView paintView;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_line_l_hw, container, false);
paintView = v.findViewById(R.id.lineLPaintView);
DisplayMetrics metrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
paintView.init(metrics);
setHasOptionsMenu(true);
return v;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.main, menu);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.normal:
paintView.normal();
return true;
case R.id.clear:
paintView.clear();
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onSaveInstanceState(#NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelableArrayList("line test", paintView.getPaths());
}
}
This is my first time using Canvas in Android.
I am creating an app that would display circles at certain positions on the screen one at a time (positions are selected randomly). New circle should be drawn after the previous one was selected/touched, and the previous one should disappear.
I have some ideas about it: to keep an arraylist of Point objects(each object contains x,y coordinate of the centre of the circle) and randomly select one each time the circle is drawn on the screen. So first I am populating an array of points. I also know how to randomly select the element from arraylist.
My biggest confustion is how to connect onDraw and onTouchEvent methods with each other? I know I should check if the circle was selected and only then draw a new circle at the randomly selected position, but I m not sure how to make a call for onDraw() method from the onTouchEvent...
Could you please help with this issue?
My code is below:
package com.example.researcher.heatmap;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
/**
* TODO: document your custom view class.
*/
public class MyView extends View {
Paint paint;
ArrayList<Point> points = new ArrayList<>();
public MyView(Context context) {
super(context);
init();
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MyView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
// Load attributes
paint = new Paint();
paint.setColor(Color.BLUE);
paint.setStrokeWidth(5);
paint.setStyle(Paint.Style.STROKE);
populateArrayList();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setStyle(Paint.Style.STROKE);
canvas.drawColor(Color.WHITE);
int i=1; // should be random, will randomize later
for(Point p: points) {
p.x = points.get(i).x;
p.y = points.get(i).y;
canvas.drawCircle(p.x, p.y, 50, paint);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
int i=1;
for(Point p: points) {
Canvas canvas = new Canvas();
p.x = points.get(i).x;
p.y = points.get(i).y;
canvas.drawCircle(p.x, p.y, 50, paint);
}
postInvalidate();
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL: {
break;
}
}
postInvalidate();
return true;
}
public void populateArrayList(){
points.clear();
points.add(new Point(120, 120));
points.add(new Point(150, 320));
points.add(new Point(280, 200));
}
}
Thank you Chris for your help! I really appreciate it.
Here is my solution if someone will need it for reference
package com.example.researcher.heatmap;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* TODO: document your custom view class.
*/
public class MyView extends View {
Paint paint;
ArrayList<Point> points = new ArrayList<>();
private int pointsPos = 0; //Which point we will be drawing
public float x;
public float y;
public int radius = 150;
public MyView(Context context) {
super(context);
x = this.getX();
y = this.getY();
init();
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
x = this.getX();
y = this.getY();
init();
}
public MyView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
x = this.getX();
y = this.getY();
init();
}
private void init() {
// Load attributes
paint = new Paint();
paint.setColor(Color.BLUE);
paint.setStrokeWidth(5);
paint.setStyle(Paint.Style.STROKE);
populateArrayList();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setStyle(Paint.Style.STROKE);
canvas.drawColor(Color.WHITE);
canvas.drawCircle(points.get(pointsPos).x, points.get(pointsPos).y, radius, paint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
//Check if the point press is within the circle
if(contains(event, points.get(pointsPos))){
Random r = new Random(System.nanoTime());
pointsPos = r.nextInt(points.size());; //between 0 and points.length
postInvalidate();
}
case MotionEvent.ACTION_CANCEL: {
break;
}
}
postInvalidate();
return true;
}
private boolean contains(MotionEvent event, Point point) {
float xTouch = event.getX();
float yTouch = event.getY();
if ((xTouch - point.x) * (xTouch - point.x) + (yTouch - point.y) * (yTouch - point.y) <= radius * radius) {
return true;
}
else {
return false;
}
}
public void populateArrayList(){
points.clear();
points.add(new Point(220, 1020));
points.add(new Point(550, 320));
points.add(new Point(780, 500));
}
}
Class var
private int state = 0 //0 normal, 1 new circle
private int pointPos = 0; //Which point we will be drawing
onDraw was overwriting the x/y of all your other points
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setStyle(Paint.Style.STROKE);
canvas.drawColor(Color.WHITE);
if(state == 1){
pointPos = random(); //between 0 and points.length
state = 0;
}
canvas.drawCircle(points.get(pointsPos).x, points.get(pointsPos).y, 50, paint);
}
onTouchEvent: Drawing should only be done on the ondraw, use flags/states to keep track of what you should be doing on the next draw call
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//Though these days this is usually done on the up event
//Check if the point press is within the circle
if(contains(event, points.get(pointPos))){
state = 1;
postInvalidate();
}
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL: {
break;
}
}
postInvalidate();
return true;
}
a small time based question > I want to get timer in activity I already tryed this code but it runs so fast I offen get " 0 " I want to program to run with no sleep . but to count from 0 to 60 sec
package com.okok;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Handler;
import android.os.SystemClock;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.SurfaceHolder.Callback;
import android.widget.Chronometer;
class GameView extends SurfaceView {
//private Bitmap bmp;
// Chronometer mChronometer;
private SurfaceHolder holder;
private GameLoopThread gameLoopThread;
private List<Sprite> sprites = new ArrayList<Sprite>();
private long lastClick;
private Bitmap bmpBlood;
Handler m_handler;
Runnable m_handlerTask ;
private List<TempSprite> temps = new ArrayList<TempSprite>();
public GameView(Context context) {
super(context);
gameLoopThread = new GameLoopThread(this);
holder = getHolder();
holder.addCallback(new Callback() {
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
createSprites();
gameLoopThread.setRunning(true);
gameLoopThread.start();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
}
});
bmpBlood = BitmapFactory.decodeResource(getResources(), R.drawable.blast2);
}
private void createSprites() {
sprites.add(createSprite(R.drawable.greenenact));
// sprites.add(createSprite(R.drawable.greenenact));
// sprites.add(createSprite(R.drawable.greenenact));
}
private Sprite createSprite(int resouce) {
Bitmap bmp = BitmapFactory.decodeResource(getResources(), resouce);
return new Sprite(this, bmp);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.rgb(21, 181, 195));
for (int i = temps.size() - 1; i >= 0; i--) {
temps.get(i).onDraw(canvas);
}
final int count=0;
m_handler = new Handler();
m_handlerTask = new Runnable()
{
#Override
public void run() {
// do something
if(count=60)
{
m_handler.removeCallbacks(m_handlerTask);
}
count++;
m_handler.postDelayed(m_handlerTask, 5000);
for (Sprite sprite : sprites) {
sprite.onDraw(canvas);
}
}
};
m_handlerTask.run();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (System.currentTimeMillis() - lastClick > 500) {
lastClick = System.currentTimeMillis();
synchronized (getHolder()) {
float x = event.getX();
float y =event.getY();
for (int i = sprites.size() - 1; i >= 0; i--) {
Sprite sprite = sprites.get(i);
if (sprite.isCollition(x, y)) {
sprites.remove(sprite);
temps.add(new TempSprite(temps, this, x, y, bmpBlood));
break;
}
}
}
}
return true;
}
}
this is my program I have only one error
can not change count from int to a boolean error
I don't want to use sleep method because my application have sleep method that affect my animation
or give me a program that counts 0 to 60 sec and displays which runs without a sleep method
Use chronometer instead. Here is example ,
Example 2
Use a Handler
Handler m_handler;
Runnable m_handlerTask ;
int count=0;
m_handler = new Handler();
m_handlerTask = new Runnable()
{
#Override
public void run() {
// do something
if(count=60)
{
m_handler.removeCallbacks(m_handlerTask);
}
count++:
m_handler.postDelayed(m_handlerTask, 1000);
// repeat some task every 1 second
}
};
m_handlerTask.run();
I am trying to update the position of a bitmap with an onTouch event. The image displays in the initial spot correctly. The logs show that the onTouch event is updating the coordinate and also show that onDraw is being called.
My Activity:
package com.miker.haminvaders;
import android.app.Activity;
import android.os.Bundle;
public class HamInvadersActivity extends Activity
{
private DrawView drawView;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
drawView = (DrawView) findViewById(R.id.drawView);
}
#Override
public void onPause()
{
super.onPause();
drawView.stopGame();
}
#Override
protected void onDestroy()
{
super.onDestroy();
drawView.releaseResources();
}
}
My Thread Class:
package com.miker.haminvaders;
import android.graphics.Canvas;
import android.util.Log;
import android.view.SurfaceHolder;
public class MainThread extends Thread
{
private boolean running;
SurfaceHolder surfaceHolder;
DrawView drawView;
public void setRunning(boolean r)
{
this.running = r;
}
#Override
public void run()
{
Canvas canvas = null;
while(running)
{
//Log.v("HAM", "tick!");
try
{
canvas = surfaceHolder.lockCanvas();
synchronized(surfaceHolder)
{
drawView.onDraw(canvas);
drawView.updatePositions();
}
}
finally
{
if(canvas != null)
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
public MainThread(SurfaceHolder surface, DrawView draw)
{
super();
surfaceHolder = surface;
drawView = draw;
}
}
My SurfaceView class:
package com.miker.haminvaders;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.graphics.BitmapFactory;
import android.util.Log;
public class DrawView extends SurfaceView implements SurfaceHolder.Callback
{
private MainThread myThread;
private int screenWidth;
private int screenHeight;
private Paint textPaint;
private Paint backPaint;
private float x, y;
private Bitmap bmpHam;
public DrawView(Context context, AttributeSet attrs)
{
super(context, attrs);
SurfaceHolder holder = getHolder();
holder.addCallback(this);
textPaint = new Paint();
backPaint = new Paint();
myThread = new MainThread(holder, this);
bmpHam = BitmapFactory.decodeResource(getResources(), R.drawable.lilhamstrich);
}
#Override
protected void onSizeChanged( int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
screenWidth = w;
screenHeight = h;
textPaint.setTextSize(w/20);
backPaint.setColor(Color.WHITE);
newGame();
}
public void newGame()
{
x = screenWidth/2;
y = screenHeight/2;
}
public void updatePositions()
{
}
public void onDraw(Canvas canvas)
{
canvas.drawColor(Color.WHITE);
canvas.drawBitmap(bmpHam, x, y, null);
Log.v("HAM", "Draw! " + x + " " + y);
}
public void stopGame()
{
if(myThread != null)
myThread.setRunning(false);
}
public void releaseResources()
{
//soundPool stuff
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
}
#Override
public void surfaceCreated(SurfaceHolder holder)
{
myThread.setRunning(true);
myThread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder)
{
boolean retry = true;
myThread.setRunning(false);
while(retry)
{
try
{
myThread.join();
retry = false;
}
catch(InterruptedException e)
{
}
}
}
#Override
public boolean onTouchEvent (MotionEvent event)
{
int action = event.getAction();
if( action == MotionEvent.ACTION_DOWN)
{
x = event.getX();
y = event.getY();
Log.v("HAM","Down! " + x + " " + y);
}
return true;
}
}
Is there anything else that I need to include?
Call invalidate() in the onTouchEvent(), it should cause a redraw.