loop is not working, why is this the case? - java

I am having trouble understanding this java code. I want the image to twinkle a couple of times, with some delay. The image twinkle once and thats it. Can someone give me an explanation would be great!
private void RunAnimations(int[]melodiTakten) {
for (int i = 0; i < 4; i++) {
ImageView markeringspilen = (ImageView) findViewById(R.id.markeringspil);
markeringspilen.setVisibility(View.VISIBLE);
markeringspilen.postDelayed(new Runnable() {
public void run() {
ImageView markeringspilen = (ImageView) findViewById(R.id.markeringspil);
markeringspilen.setVisibility(View.INVISIBLE);
}
}, 2000);
}

If I understand your idea right, your implementation is wrong in that it sets delayed actions to take place all at the same time. You can space them out like this:
for (int i = 0; i < 4; i++) {
markeringspilen.postDelayed(new Runnable() {
public void run() {
ImageView markeringspilen = (ImageView) findViewById(R.id.markeringspil);
markeringspilen.setVisibility(View.VISIBLE);
}
}, 4000*i);
markeringspilen.postDelayed(new Runnable() {
public void run() {
ImageView markeringspilen = (ImageView) findViewById(R.id.markeringspil);
markeringspilen.setVisibility(View.INVISIBLE);
}
}, 4000*i+2000);
}
This loop sets up eight delayed visibility changes - a group of four pairs of set visible at 4000*i followed by set invisible at 4000*i+2000.

the loop is executed, but it's executed very fast and you can't see it. You should put some delay in the loop, not only in the runnable.

That's because you call setVisibility(View.VISIBLE) four times in a row and then, after a 2s delay, four times setVisibility(View.INVISIBLE).
What you need to do is add eight runnables with ever increasing delays that in turn toggle the visibility.

Related

Android method executing and results not on time

I have noticed that Android code is being executed by chunks, take this code for example
actionButton.setOnClickListener(new View.OnClickListener() {
#Override public void onClick(View view) {
revealButton.setVisibility(View.VISIBLE);
final LayoutInflater inflater = getLayoutInflater();
for(int i = 0; i <= 50; i++)
{
View child = inflater.inflate(R.layout.item, mainLinear, false);
mainLinear.addView(child, 2);
}
}
});
The Reveal button is not being visible untill the rest of the code is completed and delivered which in this case takes a second or two. So i tried to put it in chunks of code like:
{
revealButton.setVisibility(View.VISIBLE);
}
{
final LayoutInflater inflater = getLayoutInflater();
for(int i = 0; i <= 50; i++)
{
View child = inflater.inflate(R.layout.item, mainLinear, false);
mainLinear.addView(child, 2);
}
}
I have also tried to make a two different static method trying to go too far to get this right which resulted in the same behaviour. The problem comes when i need to do some work but have to update the UI with instant results.
What is it that you're trying to do, exactly?
From the code it looks as if you're trying to render a list of views and show a reveal button to the user. Is that correct?
Either way, it seems to me the reason it's not updating immediately is because all the instructions are being executed on the same thread, which seems to be the Main Thread, so it will only update after it leaves the onClick block.
But I can't be sure on my answer. Could you give more details as to what you want to do, exactly? Is it to render a list of sorts or something else?

Bukkit Delayed Task Inside a For Loop

I've been trying to make gun plugin for Bukkit, and I'm trying to build a burst fire feature. I have a for loop that contains a delayed task, and inside that delayed task is the code to create a bullet and all that. Theoretically, the code would add some bullets, wait one tick, and add some more bullets, wait one tick, etc until the for loop is done.
public void fire(final Player p, final Gun g) {
for(int i=0; i<shotsPerBurst; i++) {
Bukkit.getServer().getScheduler().scheduleAsyncDelayedTask(plugin, new Runnable() {
public void run() {
for(int i=0; i<bulletsPerShot; i++) {
Bullet b = new Bullet(p, g);
GunsV1.bullets.add(b);
}
}
}, 1L);
}
}
Eclipse demands that Player p and Gun g both be final, I don't know why, and when I try to run fire(p, g), nothing happens. How can I set up my code so the for loop will run with a delay of 1 tick between cycles?
To resolve one question:
Eclipse demands that Player p and Gun g both be final, I don't know why
You are passing the Player p and the Gun g to an new Thread/new Runnable and Eclipse tells you that those 2 Object's shouldn't be modified or changed because the Thread/Runnable also uses these 2 Object's inside the run method (as you can see).
I would suggest you to write your issue directly in here: http://bukkit.org/forums/plugin-development.5/ because there are also developer which know more and in detail about the Bukkit Server for Minecraft.
I will try to find a solution that fit's your needs now - but maybe you already try to find a solution in the forum.
Found this link for you - it may help you a little bit: http://www.programcreek.com/java-api-examples/index.php?api=org.bukkit.scheduler.BukkitScheduler
There's no easy way to run the for loop with a delay without freezing Bukkit's main thread. The best thing to do in this case is to use plugin.getServer().getScheduler().runTaskLater():
plugin.getServer().getScheduler().runTaskLater(plugin, new Runnable(){
public void run(){
//shoot the gun
}
},1L);//run after 1 tick
But, if you use this, the gun will only fire one shot. To fix this, you should keep running the scheduler:
public static void runTask(){
plugin.getServer().getScheduler().runTaskLater(plugin, new Runnable(){
public void run(){
//shoot the gun
runTask(); //run the task again
}
},1L);//run after 1 tick
}
But this way, the gun will keep firing every tick, and never stop. So, you should count the number of times it has ran, and stop running the task once the number is reached:
public static void runTask(final int timesLeft){
plugin.getServer().getScheduler().runTaskLater(plugin, new Runnable(){
public void run(){
//shoot the gun
if(timesLeft > 0){
runTask(timesLeft - 1); //run the task again after removing from the times left
}
}
},1L);//run after 1 tick
}
So, in the end, your loop method could look something like this:
public static void fire(final Player player, final Gun gun, final int timesLeft){
plugin.getServer().getScheduler().runTaskLater(plugin, new Runnable(){
public void run(){
Bullet bullet = new Bullet(player, gun);
GunsV1.bullets.add(bullet);
if(timesLeft > 0){
fire(player, gun, timesLeft - 1); //run the task again after removing from the times left
}
}
},1L);//run after 1 tick
}
and you could call it by using:
fire(player, gun, shotsPerBurst);
After experimenting with some longer delays and looking at the spigot reference, I realized that the ticks of delay are not ticks until the next task, but until the runnable runs. Knowing this, I was able to use the for loop to increase the ticks of delay proportionally:
public void fire(final Player p, final Gun g) {
for(int i=0; i<shotsPerBurst; i++) {
Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
public void run() {
for(int i=0; i<bulletsPerShot; i++) {
Bullet b = new Bullet(p, g);
GunsV1.bullets.add(b);
}
}
}, i*3);
}
}
Now it runs each task three ticks after the previous one, and fires in a burst

Android animation blink

The code is for making a text color change evenly every 200 ms. Why is the first version change uneven/flickering, and the second one evenly changes?
//first version
long lt = System.currentTimeMillis();
TextView tv = ...
for (int i = 1; i < 120; i++) {
final int cl = i % 2 == 0 ? 0xFFFF0000 : 0x00000000;
Message w = Message.obtain(handler, new Runnable() {
public void run() {
tv.setTextColor(cl);
tv.requestLayout();
}
});
handler.sendMessageDelayed(w,i * 200L - (System.currentTimeMillis()-lt));
}
//second version
Animation anim = new AlphaAnimation(0.0f, 1.0f);
anim.setDuration(200); //You can manage the time of the blink with this parameter
anim.setStartOffset(20);
anim.setRepeatMode(Animation.RESTART);
anim.setRepeatCount(Animation.INFINITE);
tv.startAnimation(anim);
I have had this problem before when creating/using animations. After you are done with your animation, simply call clearAnimation().
This will insure that it has fully stopped and should be nice and smooth, giving the user the experience you desire.
How to stop an animation (cancel() does not work)
Read more:
http://developer.android.com/reference/android/view/View.html
Regards,

Changing images in a Loop - Android

I'm wondering why still I couldn't to figure out a way to do this. Although it seems like very simple, I spent my entire day for this. But couldn't do that.
I have set of dice images. 1.png,2.png,.... and 6.png.
There is an ImageView in my layout. That is,
ImageView dice = (ImageView) findViewById(R.id.imageViewrollingdiceOne);
Here I want to change this imageView rapidly to see a some kind of a visual/animation using above 6 images. For that I wrote following piece of code.
Code 1:
for (int j=0;j<10;j++){
int randomNum = random.nextInt(6);
System.out.println("Random Value " + randomNum);
dice.setImageResource(images[randomNum]);
}
Output:
There is not a visual. imageView remains unchanged and suddenly changes at the loop last iteration.
I thought that it is because the loop is executing very fast.
Then I did the following.
Code 2:
for (int j=0;j<10;j++){
int randomNum = random.nextInt(6);
System.out.println("Random Value " + randomNum);
dice.setImageResource(images[randomNum]);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Output:
Again there is not a visual. imageView remains unchanged and suddenly changes at the loop last iteration.
Then I did the following.
Code 3:
final Handler localHandler = new Handler();
Runnable runnableObject = new Runnable() {
public void run() {
final ImageView dice = (ImageView) findViewById(R.id.imageViewrollingdiceOne);
int randomNum = random.nextInt(6);
System.out.println("Random Value" + randomNum);
dice.setImageResource(images[randomNum]);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
for (int j=0;j<10;j++){
localHandler.postDelayed(runnableObject, 1000);
}
Again there is not a visual. imageView remains unchanged and suddenly changes at the loop last iteration. There are no any errors in logcat in all three cases.
I found that threading also doesn't do the trick.
First of all there is already an animation set in android that can help you achive what you are after it is called FrameAnimation, here is an example on how to use it:
FrameAnimation Example
Your First, second and third code are running in the main thread, you should never use sleep in the main thread !.
If you still want to set the image resource manually you can use this code:
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
int randomNum = random.nextInt(6);
dice.setImageResource(images[randomNum]);
handler.postDelayed(this, 500);
}
}, 500);
This is helpful when you're using list of items and changing according time interval one by one. Initially i value should be 0, size of list depends.
final Handler handler = new Handler();
handler.postDelayed(new Runnable(){
public void run(){
if(i<4) {
galleryImg.setImageResource(myImageList[i]);
i++;
} else {
i=0;
}
handler.postDelayed(this, 10000);
}
}, 500);
The reason you're probably not seeing changes is because the final callback to the main UI thread happens after your thread finishes its execution and you only see the final result. Now, this is my (probably poor) understanding and someone more versed in it can probably correct me.
That said you should probably look to using an AnimationDrawable object:
ImageView sImage = (ImageView)findViewById(R.id.imageViewrollingdiceOne);
AnimationDrawable anim = new AnimationDrawable();
for (int j=0;j<6;j++) {
anim.addFrame(new BitmapDrawable(images[j], 200);
}
sImage.setBackgroundDrawable(anim);
anim.setOneShot(false);
anim.start();
This assumes you've generated images[] with the images in random order already. If you want to change that up put whatever code you need in the for-loop.
What it does is creates an animation object much like how you'd see a gif work with a set delay interval between changes (in this code its 200ms). You can elect to change that number if you wish. The setOneShot call makes sure it loops instead of finishing the animation and stopping on the last image.

Display sequence of words on BlackBerry screen

I have ten words in a string array. As an example: {"A B","C D","E F","G H"......}.
I have to display these words in succession, holding each word on screen for 2 seconds. With each new word displayed, the font size needs to get smaller as well.
How do I do this on a BlackBerry?
You can use a Timer to control the timing:
import java.util.Timer
int index;
String[] words;
...
TimerTask task = new TimerTask() {
public void run()
{
// TODO: Check the bounds and kill the timer when we're done.
// Invoke the code in the UI Thread
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run()
{
// Code to enumerate and concat the string...
}
});
}
};
timer timer = new Timer();
timer.scheduleAtFixedRate(task, 0, 2000);
To change font size:
// in the class body:
final int minFontSize = 5;
int maxFontSize = minFontSize + words.length();
// in the timer's run method:
net.rim.device.api.ui.Font defaultFont = this.getFont();
net.rim.device.api.ui.Font myFont = defaultFont.derive(0, maxFontSize - index)
// change the font of the ui control
field.setFont(myFont);
I haven't checked the code to see if it compiles, but I hope you get the idea.

Categories