In the code below I have 3 images stored in an imageArray. I'm animating images using a handler, but it's looping continuously, and I want it to only to run the animation once.
What I want to do is to see if it gets to the 3rd image, then stop the animation.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_grade_four__place_value);
final ImageView image1 = (ImageView) findViewById(R.id.im1);
final int[] imageArray = {(R.drawable.pl1),
(R.drawable.pl2),
(R.drawable.pl3)};
final Button btn2 = (Button) findViewById(R.id.button2);
btn2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final Handler handler = new Handler();
Runnable runnable = new Runnable() {
int i = 0;
public void run() {
image1.setImageResource(imageArray[i]);
i++;
if (i > imageArray.length - 1) {
i = 0;
}
handler.postDelayed(this, 300); // for interval...
}
};
handler.postDelayed(runnable, 500); // for initial delay..
btn2.setVisibility(View.INVISIBLE);
}
});
Have you considered using a Drawable Animation as opposed to a Handler?
You'd basically create an animation set in xml as follows:
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/pl1" android:duration="300" />
<item android:drawable="#drawable/pl2" android:duration="300" />
<item android:drawable="#drawable/pl3" android:duration="300" />
</animation-list>
Let's call this file animation_drawable.xml and put it in the drawable folder. Afterwards, just use the following code to start the animation:
final AnimationDrawable drawable = (AnimationDrawable) getResources().getDrawable(R.drawable.animation_drawable);
image1.setImageDrawable(drawable);
drawable.start();
image1.postDelayed(new Runnable() {
#Override
public void run() {
image1.clearAnimation();
// Handle your animation ending here
}
}, drawable.getDuration());
That's it! I know it's a hack solution, but I thing Drawable animation makes the code clearer and more compact, but listening to the end of the animation requires a bit of workaround.
Schedule the Runnable only if the end of the image array is not reached:
public void run() {
image1.setImageResource(imageArray[i]);
i++;
if (i < imageArray.length) {
handler.postDelayed(this, 300); // for interval...
}
}
Try changing
i++;
if (i > imageArray.length - 1) {
i = 0;
}
handler.postDelayed(this, 300);
to
if (i < imageArray.length - 1) {
handler.postDelayed(this, 300);
}
i++;
Your Runnable code posts itself into handler with delay after each pass. Just instead setting i=0; when your i variable is bigger or equal array size - return from run() method. It will not reach handler.postDelayed(this, 300), so next frame will be not displayed.
Sample:
final int[] imageArray = {R.drawable.ic, R.drawable.ic, R.drawable.ic};
final Handler handler = new Handler();
final Runnable runnable = new Runnable() {
private int i = 0;
#Override
public void run() {
i++;
if(i > imageArray.length - 1) {
Log.e("ASD", "Done");
return;
}
Log.e("ASD", "Preparing next iteration");
handler.postDelayed(this, 300);
}
};
handler.postDelayed(runnable, 500);
Anyway, it's not best way to provide frame animation.
Related
I have a button that I want its text appear for 1 second then disappear for 1 second, loop for 6 seconds, here is what I tried:
for(int i = 0 ; i < 6 ; i++) {
button.setTextSize(18);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
button.setTextSize(0);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
first is it appear that the button's text size became 36 instead of 18,
second is it is does not act as I expected, never show the text,
note: the text size from start is 0.
How can I achieve this?
okey as you suggested you want to just blink your TextView, here what you can do.
create on folder under res called "anim", now create one xml file under that say
blink.xml and copy this code in it.
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:fromAlpha="0.0"
android:toAlpha="1.0"
android:duration="1000"
android:repeatMode="reverse"
android:repeatCount="infinite" />
</set>
Now in your Java class just apply this animation to your TextView
Animation anim = AnimationUtils.loadAnimation(getActivity(),
R.anim.blink);
yourtextview.startAnimation(anim);
Done.
Instead of blocking thread using Thread.sleep(1000) you can use handler post delayed and after 1 second and make it visible and post another one to make it disappear .
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
/* Make it visible here. */
button.setVisibility(View.VISIBLE);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
/* Make it disappear here. */
button.setVisibility(View.GONE);
}
}, 1000);
}
}, 1000);
This simple code can help you blink your textview:
final String text = yourTextView.getText().toString();
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (yourTextView.getText().length() == 0) {
yourTextView.setText(text);
} else {
yourTextView.setText("");
}
}
});
}
};
Timer timer = new Timer();
timer.scheduleAtFixedRate(timerTask,1000,1000);
i am new to app development and i am currently trying to make a counter app.
i have set up the buttons so that the text changes with the button pressed.
although, i am trying to make the text display the adding or subtracting value and then show the total number afterwards.
For example, my counter starts at 20;
if i press the add button i want the textview text to change to +1, +2, +3 and so on for however many times the button is pressed within a time of 2 seconds. After 2 second i want the textview to show the total again. So if i pressed it 3 times, after 2 seconds on the 3rd press i want it to display "23" and not "+3" anymore.
Then, if i pressed the minus button just once the textview will display "-1" and then after 2 seconds change to "22", etc. I also want the text color to change to green when the add button is pressed, red when the minus is pressed and white when displaying the total or at default.
Here is my code so far, i am probably off by a mile but i would really like some help to be shown in the right direction.
public class MainActivity extends Activity {
private Thread timer;
TextView lifepointsP1;
ImageButton p1AddL, p1SubL;
int counter1;
int count;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
counter1 = 20;
count = 0;
lifepointsP1 = (TextView) findViewById(R.id.tvP1LP);
p1AddL = (ImageButton) findViewById(R.id.bP1add);
p1SubL = (ImageButton) findViewById(R.id.bP1take);
//the timer
timer = new Thread() {
#Override
public void run(){
try {
synchronized(this){
wait(2000);
}
} catch(InterruptedException e){
e.printStackTrace();
}
count = 0;
lifepointsP1.setTextColor(Color.argb(0, 0, 0, 0));
}
};
p1AddL.setOnClickListener(new View.OnClickListener() {
//the buttons
public void onClick(View v) {
counter1++;
count++;
if (count == 0) {
if (counter1 >= 9|counter1 <= -1) {
lifepointsP1.setText("" + counter1);
} else {
lifepointsP1.setText("0" + counter1);
}
} else if (count > 0) {
lifepointsP1.setText("+" + count);
lifepointsP1.setTextColor(Color.argb(0, 0, 188, 0));
}
}
});
p1SubL.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
counter1--;
count--;
if (count == 0) {
if (counter1 >= 9|counter1 <= -1) {
lifepointsP1.setText("" + counter1);
} else {
lifepointsP1.setText("0" + counter1);
}
} else if (count < 0) {
lifepointsP1.setText("-" + count);
lifepointsP1.setTextColor(Color.argb(0, 214, 0, 0));
}
}
});
}
//the counter reset if pressed
#Override
public boolean onTouchEvent(MotionEvent evt) {
if(evt.getAction() == MotionEvent.ACTION_DOWN) {
synchronized(timer){
timer.start();
}
}
return true;
}
}
Ive also set it up so that if the button is pressed while the timer is counting it will reset the count to start again.
Thanks in advanced for any help, its really appreciated!
What you need is a CountdownTimer
You can implement your logic in the onFinish() method then.
You should go with Handler class
A Handler allows you to send and process Message and Runnable objects
associated with a thread's MessageQueue. Each Handler instance is
associated with a single thread and that thread's message queue. When
you create a new Handler, it is bound to the thread / message queue of
the thread that is creating it -- from that point on, it will deliver
messages and runnables to that message queue and execute them as they
come out of the message queue.
There are two main uses for a Handler: (1) to schedule messages and
runnables to be executed as some point in the future; and (2) to
enqueue an action to be performed on a different thread than your own.
public int i = 0;
Then:
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
if(i != 20) {
text.append(" " + i);
i++;
handler.postDelayed(this, 1000);
} else {
handler.removeCallbacks(this);
text.append(" Stopped");
}
}
}, 1000);
}
In my application i'm changing image of button for 1sec.how to compare image of button.i tried a lot.please help me.when i chang image 1st tyme after 1sec its not changing agian.its remain the same.below is the code-
myTimer = new Timer();
myTimer.schedule(new TimerTask() {
#Override
public void run() {
if(time==-1){
onStop();
}
else
runOnUiThread(new Runnable() {
public void run() {
Random rand=new Random();
System.out.println("timer...."+time);
time=time-1;
int num = rand.nextInt(buttonIds.length);
int buttonId = buttonIds[num];
Button bb=(Button) findViewById(buttonId);
if((bb.getBackground()).equals(button.getBackground()))
{
bb.setBackgroundResource(R.drawable.happy);
wrong++;
System.out.println("llllllllllll"+wrong);
}
else
{
bb.setBackgroundResource(R.drawable.whoa);
count++;
System.out.println("mmmmmm"+count);
}
}
});
}
},0, 1000);
}
Edit
you are getting the button freshly like this
Button bb=(Button) findViewById(buttonId);
so it will always remains whoa....because the condition is always false.....
I would suggest you to set Content Description while setting the background resource and then compare the content Description....You can't compare by bb.getBackground()).equals(button.getBackground())
do something like this
but1=(Button) findViewById(R.id.b1);
but1.setBackgroundResource(R.drawable.happy);
but1.setContentDescription("happy");
and
if(bb.getContentDescription().equals(button.getContentDescription())
I am working on making a clock similar to an abacus. My problem is that I cannot understand why my image resets after each second instead of continuing on to the right. My idea is that I need to use a different type of animation possibly? Here is my code so far:
public class MainActivity extends Activity implements AnimationListener {
Button start, stop;
TextView time;
LinearLayout layout;
Animation movement;
private Handler mHandler = new Handler();
private long startTime;
private long elapsedTime;
private final int REFRESH_RATE = 1000;
private String seconds;
private long secs;
private boolean stopped = false;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
start = (Button) findViewById(R.id.buttonStart);
start.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
// Start animation on each image
if(stopped){
startTime = System.currentTimeMillis() - elapsedTime;
}
else{
startTime = System.currentTimeMillis();
}
mHandler.removeCallbacks(startTimer);
mHandler.postDelayed(startTimer, 0);
}
});
stop = (Button) findViewById(R.id.buttonStop);
stop.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
mHandler.removeCallbacks(startTimer);
stopped = true;
}
});
time = (TextView) findViewById(R.id.textTime);
// Get the layouts
layout = (LinearLayout) findViewById(R.id.linearLayout1);
// Create animation for right image
movement = AnimationUtils.loadAnimation(this, R.layout.animation_test);
movement.setAnimationListener(this);
}
// Listen for animations to be finished
// There are more efficient ways, I'm just being lazy.
public void onAnimationEnd(Animation animation) {
// or do whatever it is you wanted to do here, like launch another activity?
}
public void onAnimationRepeat(Animation animation) {
}
public void onAnimationStart(Animation animation) {
}
private Runnable startTimer = new Runnable() {
public void run() {
elapsedTime = System.currentTimeMillis() - startTime;
update(elapsedTime);
mHandler.postDelayed(this,REFRESH_RATE);
}
};
private void update (float time){
secs = (long)(time/1000);
layout.startAnimation(movement);
secs = secs % 60;
seconds=String.valueOf(secs);
if(secs == 0){
seconds = "00";
}
if(secs <10 && secs > 0){
seconds = "0"+seconds;
}
/* Setting the timer text to the elapsed time */
((TextView)findViewById(R.id.textTime)).setText(seconds);
}
}
My animation.xml is as follows
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="0"
android:toXDelta="15%p"
android:fromYDelta="0"
android:toYDelta="0%"
android:duration="500"
android:zAdjustment="top"/>
I am at a standstill, been trying to read through the Development Sections, I just can't find the right solution or must be overlooking something.
Try adding:
android:fillEnabled="true"
android:fillAfter="true"
to your animation.
If you are targeting Android 3.0 or later, you can use the new animation framework instead: http://developer.android.com/guide/topics/graphics/prop-animation.html
I have a handler and a runnable, Handler has a loop that runs from 0 to 5. when i start the runnable in handler it runs and increment value to 0 to 5. But if i double click or click more than 1 time than it takes the value of temp above 5. How can i reset (0) the value of temp on every click of handler.
final Handler deneme = new Handler();
final Runnable post_score = new Runnable(){
public void run(){
Log.i("TAG", Integer.toString(temp));
temp++;
}
};
Button tv = (Button )findViewById(R.id.button1);
tv.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
temp = 0;
for(int i=0; i < 5;i++){
deneme.postDelayed(post_score, i *250);
}
}
});
the best way is to use removecallback