1

I want to display 60 different colors in 1 second in android. How I can do this that the duration of display(16ms) of all colors is same during 1 second?

  • You mean different color for each frame? – Alex Salauyou Apr 23 '15 at 22:54
  • Yes, Exaclty. I want to display different color for each frame. –  Apr 24 '15 at 08:50
  • 1
    Add some advice! This can not be "dangerous" for some type of people? Due epileptic seizure.. I don't know.. but poeple can be sensible to that fast change of colors... (I Thing) – Shudy Apr 24 '15 at 10:03
  • @Shudy,,This application is not for people. There are sensors fast enough to detect the change of colors at this frequency. –  Apr 24 '15 at 15:46
  • Agree with @Shudy , this is totally something some people might not want to look at. – natario Apr 26 '15 at 11:42
  • @mvai, As i alread commented above, this is application is for sensors which are fast enough to detect these changes. –  Apr 26 '15 at 23:42
  • @muhammadkiyani then is perfect ^^ . At first read , it seemed that was for public purposes, but If are for machines, then will be no problems. – Shudy Apr 27 '15 at 08:16

3 Answers3

1

What you need can be achieved in a custom View where you call invalidate() on each onDraw() invocation:

int framesToRedraw = 0;


public void startAnimation(int frames){
     framesToRedraw = frames;
     this.invalidate();
}


/**
 * onDraw override.
 * If animation is "on", view is invalidated after each redraw
 * to make android redraw it on the next frame
 */
@Override
public void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    if (framesToRedraw > 0) {
         // generate new color randomly
         float[] hsvColor = {0, 1, 1};
         hsvColor[0] = random.nextFloat() * 360f;
         this.setBackgroundColor(Color.HSVToColor(hsvColor));
         framesToRedraw--;
         this.invalidate();  // force the view to be redrawn on each frame
    } 
}
Alex Salauyou
  • 14,185
  • 5
  • 45
  • 67
  • @Sasha.How onDraw() will be called for each frame? –  Apr 26 '15 at 10:23
  • On each frame, android traverses the whole view tree, starting from the main fragment. If it sees a view invalidated, it calls its onDraw. – Alex Salauyou Apr 26 '15 at 11:01
  • 1
    That is purpose of `this.invalidate()` on each redraw. If you invalidate the view at the end of `onDraw()`, it will be redrawn on the next frame. – Alex Salauyou Apr 26 '15 at 11:03
  • @muhammadkiyani In updated answer I added check to limit of frames. – Alex Salauyou Apr 26 '15 at 15:43
  • -@Sasha, For me it is taking 1.6 seconds to complete the process for 60 times. Do you have any suggestion, how I can reduce this time to 1 second? I am measuring the time by System.nanoTime(). –  Apr 26 '15 at 22:48
  • @muhammad you want 60 frames or one second? They may be different, because timing between frames is not always exact. In `startAnimation()` just remember the current time in ns and put additional condition into `if` statement--to stop redraw if 1000M nanoseconds elapsed. – Alex Salauyou Apr 26 '15 at 23:03
  • I want 60 frames most preferably in one second. If android refresh rate is 60Hz, then we should be able to achieve these 60 variations in 1 Second. –  Apr 26 '15 at 23:38
  • @muhammad refresh rate may vary depending on system load... Try to measure timing between consequent onDraw invocations to see what's actual pause btw frames – Alex Salauyou Apr 27 '15 at 06:21
0

You can use the Handler class to manage delayed executions. Here you have an example on how to use it to generate a timer every n millis.

final Handler handler = new Handler();
handler.postDelayed(new Runnable(){
    private static final long INTERVAL = 16L;
    private long time = 0;

    @Override
    public void run(){
        time += INTERVAL;
        if(time <= 1000){
            handler.postDelayed(this, INTERVAL); //Make sure you are calling it after 16 millis
        }
        // Change your color here
        changeColor();
    }
}, INTERVAL);
Community
  • 1
  • 1
droidpl
  • 5,872
  • 4
  • 35
  • 47
0

you already have the math, so try the easy style

//assume im in a different Thread
for(int i=0; i < 17; i++){
    Thread.sleep(16); // add try catch
Color c = Color.argb(255, rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256)); }

pretty simple

Elltz
  • 10,730
  • 4
  • 31
  • 59
  • This is simple, but won't work as desired. First, being in another thread, you need to set view color via UI thread handler. Second, frame timing is not exactly accurate (pause can be 15, 16, 17 ms, or even more) so some frames will skip color updates. – Alex Salauyou Apr 26 '15 at 11:21
  • it is a for loop Sir, so if it suit your desire you can run it on UI thread, or you can use asyn task and use on progress update to change the View in question and post will notify you when its done, you can try that and see, and if the pause is really lengthy than you desier, you can sleep for lesser milie second so the delay can match up to your desired length, but if it doesn't suit your need, i'm sure the other answers will. @SashaSalauyou _sorry i tot you were the OP_ but thanks for the heads up, i just conjured a method for the OP, i didnt really try it. – Elltz Apr 26 '15 at 11:40
  • It is highly discouraged to call `Thread.sleep()` on the UI thread. – Alex Salauyou Apr 26 '15 at 11:46