How to draw line slowly in Android? - android

I am trying to draw points to android canvas slowly. I want to use canvas.drawline function however drawing one point to another i want to have small delay. Can you help me please?

Here's the general pattern:
// PSEUDOCODE
// in a class created in a Looper thread, e.g., the main thread
private final Handler handler = new Handler();
static class DrawTask implements Runnable {
// final fields for start point, end point, number of segments, interval, etc.
// mutable field for progress
// constructor with appropriate params
#Override
public void run() {
// draw the current line segment
if(!finished) {
handler.postDelayed(this, interval);
}
}
}
// in some draw method
handler.post(new DrawTask(...));
You might want to hang onto a reference to the DrawTask so you can cancel it with Handler#removeCallbacks(...) in case it's still running when your activity is paused.

Related

How to use android handler in a loop

I am building my first android application and I am trying to make a memory game. Anyhow, I need to make an array of buttons change color for 1 second and then return to its original color in order, for example: button1 changes to yellow, stays like that for 1 second then returns to gray, then button2 changes to yellow for 1 second then returns, and so on. I tried using the handler but it always works only after the last iteration, this is my code:
for (i = 0; i < 9; i++) {
buttonList.get(i).setBackgroundColor(Color.YELLOW);
runnable =new Runnable(){
#Override
public void run() {
buttonList.get(i).setBackgroundColor(Color.GRAY);
}
};
handler.postDelayed(runnable,1000);}
what am I doing wrong?
EDIT
Found How to do it. First I need to make a runnable class that takes paramaters ex MyRunnable implements Runnable (using Runnable interface), then writing a method that uses this paramater, I can't do it with the regular one because it depends on i and i changes with the iteration.
You need to create a new Runnable inside each loop because all 9 delayed posts are running the same runnable that you create on the 9th and final loop since the loop no doubt takes less than a second to complete. So try something like this:
for (i = 0; i < 9; i++) {
buttonList.get(i).setBackgroundColor(Color.YELLOW);
Runnable runnable = new Runnable(){
#Override
public void run() {
buttonList.get(i).setBackgroundColor(Color.GRAY);
}};
handler.postDelayed(runnable,1000);
}
You're synchronously (at the same time) setting all buttons' colors to yellow, and also creating 9 asynchronous tasks (one for each button) to change color to gray after one second. It means all buttons will change colors back to gray after around 1 second, (more or less) at the same time.
Think of the handler as a queue that you add tasks to. The call postDelayed() is scheduling your tasks to be executed in the future, but all of them are scheduled at the same time, so all of them will be executed at the same time in the future.
I haven't run it, but I think this approach is more of what you are looking for:
// Those are fields
private int buttonIndex = 0;
private boolean yellow = false;
private final Handler handler = new Handler(new Handler.Callback() {
#Override
public void handleMessage(Message msg) {
if (!yellow) {
buttonList.get(buttonIndex).setBackgroundColor(Color.YELLOW);
handler.sendEmptyMessageDelayed(0, 1000);
} else {
buttonList.get(buttonIndex).setBackgroundColor(Color.GRAY);
if (++buttonIndex < 9) handler.sendEmptyMessage(0);
}
yellow = !yellow;
}});
// Call this to start the sequence.
handler.sendEmptyMessage(0);
Note that I'm using sendEmptyMessage*() instead of post*(), but either approach could be used. Additionally, handler's messages (tasks) can have input parameters, so it'd be nice to use them.

Draw on a canvas with delay - "make onDraw() slow down"

I use functions for canvas like drawCircle and drawPoint in android.
This works fine.
But the problem now is to draw these different items with a delay, so it looks like an animation.
What kind of mechanism should I use? Have tried with async but I dont like that way of doing it.
Should I use some kind of timer that just draw with an interval or is there other clever ways to do this?
I use this strategy, first I declare a Handler and a Runnable that way:
private final Observable mObservable = new Observable();
private final static int TIME_STEP_MS = 5;
private final Handler mHandler = new Handler();
private final Runnable mTimeManager = new Runnable()
{
public void run()
{
mObservable.notifyObservers(TIME_STEP_MS);
mHandler.postDelayed(mTimeManager, TIME_STEP_MS);
}
};
Then when I want to start my time manager I just call the mTimeManager.run() and it will start to notify my Observer s (previously added) periodically.
If you need for some reason stop the timer or something you just do that:
mHandler.removeCallbacks(mTimeManager);
[ EDIT - More complete code ]
Ok than let's make it clearer, first I made a custom Observable object like that [that's optional]:
private final Observable mObservable = new Observable()
{
public void notifyObservers()
{
setChanged();
super.notifyObservers();
};
#Override
public void notifyObservers(Object data)
{
setChanged();
super.notifyObservers(data);
};
};
the reason for that is just because I can't call setChanged() outside Observable class - it's protected, if it's not changed it doesn't notify any observer.
The other declarations keep the same as shown before, now I need to start this TimeManager somewhere, my app is a LiveWallpaper and I make all rendering stuff into a class that extends a Thread but you don't need that necessarily, I made a method called resumeDrawing(), this one is called right after super.start(); at my #Override of public synchronized void start() from Thread class, the method looks like that:
public void resumeDrawing()
{
if (!mTimeManagerRunning) // just a boolean field in my class
{
System.err.println("Resuming renderer."); // just for debug
mTimeManager.run();
mTimeManagerRunning = true;
}
else
{
System.err.println("Renderer already running."); // just for debug
}
}
and it's dual:
public void pauseDrawing()
{
if (mTimeManagerRunning)
{
System.err.println("Pausing renderer.");
mHandler.removeCallbacks(mTimeManager);
mTimeManagerRunning = false;
}
else
{
System.err.println("Renderer already paused.");
}
}
Ok, now we can start and stop the time manager, but who's listening? Nobody! so let's add'em: On the constructor of my Renderer I add some Observer s to my mObservable object, one of those is the Renderer itself, so my renderer extends Thread and implements Observer:
#Override // from Observer interface
public void update(Observable arg0, Object arg1)
{
mElapsedMsRedraw += (Integer) arg1;
if (mElapsedMsRedraw >= mDrawingMsPerFrame)
{
mElapsedMsRedraw = 0;
drawEm(); // refresh the canvas and stuff
}
}
to add observers you simply do mObservable.addObserver(THE_OBJECT - Implements Observer)
you can see that I don't re-render my stuff each time I'm notified, that's because I use this TimeManager for other thinks than just refresh the Canvas like updating the position of the objects I want to draw just internally.
So, what you need to slow down the drawing is to change the way your objects change internally while the time passes, I mean your circles and points etc, or you can chance your time step, I recommend the first one.
Was it clearer? I hope it helps.
I would use a timer, or create Animations. You can create Animations that will do all sorts of things including changing transparency over time.
Here's the Android Documentation for Animation Resources
I believe there may be sophisticated ways of doing this, but for my needs I used a simple method that has a lot of advantages:
I first create records of coordinates (and any other data needed) for every point of the drawing -- instead of drawing the points on the spot -- and then reproduce them using a timer (Android handler, preferably). This also offers a lot of possibilities while actual drawing: pause, go faster/slower, go backwards, ...
I don't know if this method can be used for complicated drawings, but it is fine for drawing shapes, curves, surfaces, etc.

How does HandlerThread process messages?

I'm implementing my own SurfaceView which contains a Thread object whose purpose is to draw various graphical objects to the Canvas. In the constructor of my SurfaceView, I set up the objects to be drawn and the Thread object (currently) only positions them to the Canvas as appropriate.
I have need now to change one of the objects created in the constructor of my SurfaceView (the object is a Bitmap) after the user has performed a particular action (i.e. the Thread object is running). This means communication between the app's GUI thread and the thread executing my Thread object. I discovered this page which details the use of the HandlerThread class, perfect for what I need to achieve. However I need to be sure of how this class works to ensure there is no memory consistency errors.
The following is psuedo code of my own class with a lot stripped out for clarity:
public MyThread extends Thread {
boolean _run = true;
public void run(){
// Create HandlerThread object
// Create Looper object
// Create Handler object
while (_run){
// DRAW the Bitmap in this loop
}
}
public boolean handleMessage(Message message){
/*
ALTER the Bitmap here as required
*/
}
}
public MyThread extends Thread {
boolean _run = true;
public void run(){
// Create HandlerThread object
// Create Looper object
// Create Handler object
while (_run){
// DRAW the Bitmap in this loop
}
}
public boolean handleMessage(Message message){
/*
ALTER the Bitmap here as required
*/
}
}
As I understand it the handleMessage() method is executed by the same thread executing the run() method. However because handleMessage() ALTERS the the Bitmap whereas run() DRAWS the bitmap. Can I be sure that handleMessage() will complete in its entirety before the thread returns to the run() method?
Not sure if i understand the question??
you're extending a regular Thread class in both cases, which don't inherently do anything special. process execute in serialized fashion unless you otherwise specified run and handleMessage to be run from different CALLING threads. so my guess is yes. that should be a fairly straightforwards thread safe execution pattern - if you're calling handleMessage and run in the same thread, then there's not reason they shouldn't be synchronized. if you're calling the two methods from different threads, (or if you're super worried and can't find the answer anywhere else), you can always lock on an object monitor by using synchronized(myLock) in both methods like:
public MyThread extends Thread {
boolean _run = true;
public void run(){
synchronized(this) {
while (_run){
// DRAW the Bitmap in this loop
}
}
}
public boolean handleMessage(Message message){
synchronized(this){...}
}
}

SurfaceView onDraw skips drawing

My surfaceview onDraw method sometimes skips drawing some bitmaps on the screen and once it skips it never draws the particular bitmaps again.
My code
public class Board extends SurfaceView implements SurfaceHolder.Callback{
//varaibles declared here
public Board(){
//initaializations here
getHolder().addCallback(this);
}
//my onDraw method
protected void onDraw(Canvas canvas){
for(int u = 0;u<6; u++){
ai.get(u).draw(canvas);//each of these objects draws something on the screen.
human.get(u).draw(canvas);
}
postInvalidate();
}
public void surfaceCreated(SurfaceHolder holder){
gameLoop = new GameLoop(this);
gameLoop.start();
}
The onDraw() method is called every 100milliseconds in a thread that runs the game loop.
public class GameLoop extends Thread{
Board board;
private final int DELAY = 100;
public GameLoop(Board board){
this.board=board;
}
protected void run(){
long beforeTime,timediff,sleep;
beforeTime = System.currentTimeMillis();
while(running)
{
Canvas c = null;
try{
c=board.getHolder.lockCanvas();
synchronized(board.getHolder()){
board.onDraw(c);
}finally{
if(c!=null)
board.getHolder.unlockCanvas(c);
}
timeDiff = System.currentTimeMillis - beforeTime;
sleep = DELAY - timeDiff;
if(sleep<0)
sleep = 10;
try{
Thread.sleep(sleep);
}catch(InterruptedException e){}
beforeTime = System.currentTimeMillis();
}
}
So this skips happen like this: sometimes(in the onDraw() method) when u=0 does not draw or u = 5, it could be u = any of the possible values and the rest draws and once it skips that values it keeps skipping it everytime the onDraw method is called. I hope I have been able to make it clear enough.
I would appreciate help to resolve this problem. Thanks
As is, you are updating your main UI thread from another thread. Android docs indicate that this leads to unpredictable behavior, which you are experiencing.
Consider subclassing AsyncTask to do your threading for you. There are routines for doing background work and posting to the main UI thread from the UI thread itself.
Basically, you call execute on the task, which then calls it's doInBackground routine and when it is done, it calls onPostExecute routine with the results of the task.
These sources should be useful in helping to understand the problem and subclass AsyncTask:
http://developer.android.com/guide/topics/fundamentals/processes-and-threads.html
http://developer.android.com/reference/android/os/AsyncTask.html

How to call onDraw periodically?

I use ScrollView class in my application. I draw some data on canvas from the compass, these data are periodically updated by user's interaction.
How can I periodically call onDraw method without user's touch on the display? Can I periodically refresh content of the canvas without other thread and calling view.postInvalidate()?
The Handler class is very handy for things like this.
Handler viewHandler = new Handler();
Runnable updateView = new Runnable(){
#Override
public void run(){
globalView.invalidate();
viewHandler.postDelayed(updateView, MILLISECONDS_TILL_UPDATE);
}
};
Call viewHandler.post(updateView); anywhere in the UI thread and it will infinitely call that Runnable every x number of milliseconds specified in MILLISECONDS_TILL_UPDATE. Call viewHandler.removeCallbacks(updateView); to end it or use a boolean flag to prevent another post.

Categories

Resources