I want to create a basic "pokemon evolution" animation in my app , something like this:
I've been playing with this:
private void evolveAnimation(Pokemon selectedToEvolvePokemon) {
Drawable backgrounds[] = new Drawable[2];
Resources res = getResources();
backgrounds[0] = res.getDrawable(selectedPokemon.getImage(getContext()));
backgrounds[1] = res.getDrawable(selectedToEvolvePokemon.getImage(getContext()));
TransitionDrawable crossfader = new TransitionDrawable(backgrounds);
evolveTransition.setImageDrawable(crossfader);
crossfader.setCrossFadeEnabled(true);
crossfader.startTransition(3000); //The animation starts slow
crossfader.reverseTransition(3000);
crossfader.startTransition(2000);//It gets faster slow
crossfader.reverseTransition(2000);
crossfader.startTransition(1000); //And faster
crossfader.reverseTransition(1000);
}
However , this is not working as expected in the GIF posted below , how can I fix this?
EDIT:
I've changed the method to this:
private void doEvolve(TransitionDrawable crossfader, int durationMills) {
crossfader.startTransition(durationMills);
Handler h = new Handler(Looper.getMainLooper());
h.postDelayed(new Runnable() {
#Override
public void run() {
crossfader.reverseTransition(durationMills);
}
}, durationMills);
if (durationMills != 0) {
doEvolve(crossfader, durationMills - 100);
} else {
crossfader.startTransition(0);
}
}
However , works a bit strange.
currently you are starting all transitions at once, they should be queued
for example you may use some Handler and its postDelayed method, e.g.
crossfader.startTransition(3000);
Handler h = new Handler(Looper.getMainLooper());
h.postDelayed(new Runnable() {
#Override
public void run() {
crossfader.reverseTransition(3000);
}
}, 3000); // will start after startTransition duration
pack this code into some method which will take duration param and some callback informing that start/reverse pattern ended, then call this method again with shorter duration
Related
Hello I'm trying to delay imageviews to give a perception that they are being taken out one by one. I've tried
Thread.Sleep
CountDownTimer
Runnable/Handler
But they either only delay once and both imageviews change at the same time or do not delay at all. For some reference I'm trying to do something like
private void delaycard(final int Card) {
newcard(Card); //Delay this before it is called
}
Willing to try/retry anything at this point
Off the top of my head, try something like this:
Handler h = new Handler();
//for the number of images we have
for (int i = 0; i < numImages; i++) {
//we create a runnable for that action
Runnable r = new Runnable() {
#Override
public void run() {
newCard(card);
}
};
//this is the amount of time to delay it by
delay = delay + 500;
//effectively, we're creating a series of runnables at the same time
//but they activate one after the other in .5s intervals
h.postDelayed(r, delay);
}
put this inside your method
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
newCard(Card);
}
}, 100);
I would like to set a background of a table to blink with the collors red + white every 500 millisec for start.The ideea is I want it to implement in this loop inside the program and I don't know how.
if(Integer.parseInt(feedback.getText().toString()) == 0)
{
showup.setText("0");
btnbool.setBackgroundColor(Color.RED);
btnbool.setText("FALSE");
}
I have searched on previous topics but I couldn't find something that work in my code, I don't know how to use a handler to make this happen.There won't be a problem if I call a function to do this.
In top of your Activity class implement these:
// isRed flag to set bg to red or white
boolean isRed = true;
Handler handler = new Handler();
MyThread thread = new MyThread();
private class MyThread implements Runnable {
public void run() {
showup.setText("0");
if (isRed){
btnbool.setBackgroundColor(Color.WHITE);
isRed=false;
}
else{
btnbool.setBackgroundColor(Color.RED);
isRed=true;
}
btnbool.setText("FALSE");
// will run every 500 milliseconds or whatever you wish
handler.postDelayed(thread, 500);
}
}
run your thread in your onCreate() :
handler.post(thread);
to start/stop thread onClick of Button:
on top of your activity:
boolean threadStart = true;
inside your onclick event:
if (threadStart){
handler.removeCallbacks(thread);
threadStart=false;
}
else{
handler.post(thread);
threadStart=true;
}
Timer or ScheduledExecutorService.
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
when you want to launch it
executorService.schedule(blinkRunnable, 500, TimeUnit.MILLISECONDS);
the runnable to execute:
private Runnable blinkRunnable = new Runnable(){
#Override
public void run() {
if(Integer.parseInt(feedback.getText().toString()) == 0)
{
showup.post(new Runnable() {
#Override
public void run() {
showup.setText("0");
btnbool.setBackgroundColor(Color.RED);
btnbool.setText("FALSE");
}
});
}
executorService.schedule(blinkRunnable, 500, TimeUnit.MILLISECONDS); // start again
}
}
P.S You could put the colors in an array, use an index and make something more flexible.
I am building an android board game which features AI. The AI gets a turn and has to invoke a series of actions after which it posts invalidate to my custom view to update.
I need to slow down these actions so the user gets to see the AI having its turn rather than it flashing by.
I have tried something along these lines
try {
doFirstThing();
Thread.sleep(500)
//post invalidate
doNextThing();
Thread.sleep(1000)
//post invalidate
}
catch (Exception e) {
}
However this is having absolutely no effect. Also this is running in a separate thread if this wasn't obvious.
Whats my best option I've looked at handler but they don't need right as i need to execute a series of tasks in sequence updating the view each time.
Using a Handler, which is a good idea if you are executing from a UI thread...
final Handler h = new Handler();
final Runnable r2 = new Runnable() {
#Override
public void run() {
// do second thing
}
};
Runnable r1 = new Runnable() {
#Override
public void run() {
// do first thing
h.postDelayed(r2, 10000); // 10 second delay
}
};
h.postDelayed(r1, 5000); // 5 second delay
Just to add a sample :
The following code can be executed outside of the UI thread.
Definitely, Handler must be use to delay task in Android
Handler handler = new Handler(Looper.getMainLooper());
final Runnable r = new Runnable() {
public void run() {
//do your stuff here after DELAY milliseconds
}
};
handler.postDelayed(r, DELAY);
I am trying to create the illusion of AI through automated clicking of buttons.
I know I can use the animation framework and use performClick on Button views, but can you recommend a way of adding a performClick() call into the animation sequence?
Thanks for any help you can give!
My solution (MVC inspired approach):
We can create a stack of pre-determined actions:
Stack<AIAction> replay = new Stack<AIAction>(); (AIAction is the model)
We can then add in each new action to our stack to be replayed later:
replay.add(new AIAction(AIAction.SELECT,...));
All the logic and decisions are done here. (controller)
After we have the set of actions, we can replay them and display the animations for the user (view):
for (int i=0;i<replay.size();i++,start+=pause()){
AIAction thisAction = replay.get(i);
switch(thisAction.getAction()){
case AIAction.SELECT:
scheduleSelect(start,...);
break;
case AIAction.REENABLE_CLICKING:
scheduleReEnableClicking(start);
break;
case AIAction.TOAST:
if (thisAction.getToast())
scheduleToast(thisAction.getMessage(),start,true);
else
scheduleToast(thisAction.getMessage(),start,false);
break;
}
}
We now need functions like scheduleSelect(), scheduleReEnableClicking(), and scheduleToast():
This gives the impression of a "thinking" AI, and allows the user to follow.
// for example:
private void scheduleSelect(int start,...){
Handler handler = null;
handler = new Handler();
handler.postDelayed(new Runnable(){
// select logic after 'start' milliseconds
...
}, start);
}
private void scheduleReEnableClicking(int start){
Handler handler = null;
handler = new Handler();
handler.postDelayed(new Runnable(){
public void run(){
// set clickable logic after 'start' milliseconds
setClickable(true);
}
}, start);
}
private void scheduleToast(final String message,int start){
Handler handler = null;
handler = new Handler();
handler.postDelayed(new Runnable(){
public void run(){
toast(message,pause());
}
}, start);
}
I have read several forums and examples on using invalidate() in order to update views immediately but I still do not understand why what I am doing will not work. The code below uses image buttons defined by "red", "blue", "green", and "yellow". I set a 1 second delay between each time I try and change a button's appearance. Please someone tell me what i'm doing wrong.
private void showPattern() {
if (correct == true) {
for (int k = 0; k < temp_basket.length; k++) {
if (temp_basket[k] == 0) {
red.setPressed(true);
red.invalidate();
final Handler handler = new Handler();
Timer t = new Timer();
t.schedule(new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
red.setPressed(false);
red.invalidate();
}
});
}
}, 1000);
There are 3 more or these blocks after this one that are blue, green, and yellow.
Invaliadate puts a redraw message in the queue
As I see in your code, there are multiple redraws happening on after the other... the OS will try to optimize the rendering by clubbing multiple redraw messages into one (under the condition that there's no other message between them).
What you may want to do is:
private Handler myHandler = new Handler() {
public void handleMessage(Message msg)
{
switch(msg.what) { /* do your work */ }
}
};
Message msg = Message.obtain(myHandler);
msg.what = <some-number>;
msg.obj = <your-data-to-process>
if(myHandler.containsMessage(<same-number>) {
myHandler.removeMessages(<same-number>);
}
myHandler.sendMessage(msg);
You can also try using postInvalidate() method, which will cause the invalidate in the UI thread.