First, I used animation to hide and show TextView. I saw that using animation costing memory. So I used another way:
SetVisibility(VISIBLE) and SetVisibility(INVISIBLE) with TaskTimer
it works well and it performs better considering the memory.
The main issue is that after a restarting the timer for many times, the TextView disappear.
I need to restart the app to get it back again!
this is the code snippet:
myTimerForAnimation = new Timer();
myTimerForAnimation.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() // run on ui thread
{
public void run() {
counter++;
if (counter < 7) {
if (counter % 2 == 1) {
list_textView[x].setVisibility(View.INVISIBLE);
} else {
list_textView[x].setVisibility(View.VISIBLE);
}
} else {
myTimerForAnimation.cancel();
myTimerForAnimation.purge();
list_textView[x].setVisibility(View.VISIBLE);
}
}
});
}
}, 1000, 600);
Dont use Timer use handler,something like this:
// init the runnables
// the runnable should be members
Handler hanlder = new Handler();//If you arent on the UI thread pass a correct looper
for (int i=1; i<7 ; i++){
long delay = i * 1000;
if (i%2==0)
{
handler.postDelayed(mVisibleRunnable,delay);
}else{
handler.postDelayed(mInVisibleRunnable,delay);
}
}
Whereas the get runnablebs should be memebers because if u choose to cancel the callbacks then call
handler.removeCallbacks(runnable);
Play with it. It should fix your issue.
thanks to #EE66 for the loop idea, I used this code to solve my problem:
private void animateView(final View view){
for (int counter = 0; counter < 7; counter++) {
long delay = counter * 1000;
if (counter % 2 == 0) {
view.postDelayed(new Runnable() {
public void run() {
view.setVisibility(View.VISIBLE);
}
;
}, delay);
} else {
view.postDelayed(new Runnable() {
public void run() {
view.setVisibility(View.INVISIBLE);
}
;
}, delay);
}
}
}
Related
I'm currently working on a weather project in Android Studio where I want to schedule image changes in my design background every 5 seconds, I have all the image resources in my #drawable directory. I watched a basic tutorial where they explained some things in the demo but it only helped a little and didn't quite suit me, I'm still confused because I'm getting a lot of errors but I've currently tried these few codes:
HomeActivity.java:
public class HomeActivity extends AppCompatActivity {
public static int count=0;
int[] drawablearray=new int[]{R.drawable.burj_khalifa,R.drawable.central_bank_of_nigeria,R.drawable.eiffel_tower,R.drawable.hong_kong,R.drawable.statue_of_liberty};
Timer _t;
ImageView imageView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
imageView = findViewById(R.id.imageView);
ImageView = (ConstraintLayout) findViewById(R.id.lnMain);
_t = new Timer();
_t.scheduleAtFixedRate(new TimerTask); {
public void run(); {
runOnUiThread(new Runnable() { // run on ui thread
#Override
public void run() {
if (count < drawablearray.length) {
lnMain.setBackgroundDrawable(drawablearray[count]);
count = (count + 1) % drawablearray.length;
}
}
});
}
}, 5000, 5000);
}
}
Any Idea on how to Organize it to suit the design?
final Handler h = new Handler();
Runnable r = new Runnable() {
public void run() {
Home.this.getWindow.setBackgroundDrawableResource(drawableArray[count]);
cout += (count + 1) % drawableArray.length;
h.postDelayed(this, 5000);
}
};
final Runnable r = new Runnable() {
public void run() {
imageView.setBackgroundDrawableResource(drawablearray[count]);
count += (count+1)%(drawablearray.length);
handler.postDelayed(this, 5000);
}
};
And the call is like this:
handler.postDelayed(r,0);
This will call the runnable to execute and handle.postDelayed will run the method every 5000 millsec.
I already fixed the error by using constraintlayout in place of imageview and inmain. I also got id for the layout:
constraintLayout = findViewById(R.id.layout);
constraintLayout.setBackgroundResource(R.drawable.burj_khalifa);
_t = new Timer();
_t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() { // run on ui thread
#Override
public void run() {
if (count < drawable.length) {
constraintLayout.setBackgroundResource(drawable[count]);
count = (count + 1) % drawable.length;
}
}
});
}
}, 5000, 5000);
}
}
Here is my Method i want to check a that a circle lies on the button for five seconds for this i have used a runnable.but a problem is that i want to check it every second that the position of the circle changes or not if the circle position have been changes then start the handler timer from start for the new position otherwise call the method
private Runnable createRunnable(int paramPosition)
{
Runnable aRunnable = new Runnable()
{
public void run()
{
handler.postDelayed(this, 1000);
if (numOfSeconds == 5)
{
handler.removeCallbacks(this);
numOfSeconds = 0;
if (paramPosition == circlePosition)
{
methodCall(paramPosition);
handler.removeCallbacks(this);
}
else
{
if (paramPosition == circlePosition)
{
numOfSeconds++;
}
else
{
numOfSeconds = 0;
}
handler.postDelayed(this, 5000);
}
}
}
return aRunnable;
};
}
so how i can perform this work please suggest a method to solve this problem.
thanks
It is a basic app where you click the shoot button when a picture appears. A picture appears once every 5 seconds. However, all of my images are loading at the same time using the code below.
I call loadImage to load an image, and then shootHandler to remove it after 5 seconds. I'm not sure if I need to use AsyncTask or something like that.
void run() {
int i;
for(i = 0; i < imageList.length; i++) {
loadImage(i);
shootHandler(i);
}
}
private void shootHandler(final int trialNumber) {
loadImage(trialNumber);
handler.postDelayed(new Runnable() {
public void run() {
resetButtons(trialNumber);
}
}, 5000);
}
private void loadImage(int trialNumber) {
Glide.with(getApplicationContext()).load(R.drawable.red_btn).into(shoot);
int resID = getApplication().getResources().getIdentifier(imageList[trialNumber].name, "drawable", getApplicationContext().getPackageName());
Glide.with(getApplicationContext()).load(resID).into(imageList[trialNumber].image);
}
You seem to expect that postDelayed blocks the calling thread, but that is false.
If you want to call these one after another, each call should schedule the next one. See https://stackoverflow.com/a/5996270/4388512
i couldn't figure out what is your point but to load Images in the prettiest way you can use this:
final Handler handler = new Handler();
new Runnable(){
int counter = 0;
#Override
public void run() {
counter++;
if(counter == list.size()){
return;
}
Picasso.with(context).load(list.get(counter - 1)).into(imageView);
handler.postDelayed(this, 5000);
}
}.run();
I want to create 10 ImageViews with a delay of 5 seconds between, I created this code:
new Timer().scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
if (counter <= 10)
newimg();
else
// here I want to stop the timer so it will not try to create any more `ImageViews` (the array contains only 10).
}
}, 0, 5000);
private void newimg() {
ball[counter] = new ImageView(this);
ball[counter].setTag(counter);
ball[counter].setBackgroundResource(R.mipmap.ball);
int randomx = rand.nextInt(layoutwidth);
int randomy = rand.nextInt(layoutheight);
ball[counter].setX(randomx);
ball[counter].setY(randomy);
rlt.addView(ball[counter]);
counter++;
}
How can I stop the timer inside the else statement?
Call Timer cancel to stop the timer.
Call cancel() on timer
My Solutions is :
Handler handler = new Handler();
handler.postDelayed(createImageView, 5000);
Runnable createImageView=new Runnable() {
#Override
public void run() {
if (counter <= 10){
handler.postDelayed(this,5000);
newimg();
}
}
};
I'm developing an application to do the following:
When you pressed a button, the application plays a sound lasting two seconds, five times. After playing the sound for the fifth time the application sleeps for thirty seconds. After sleeping, the cycle is repeated two more times.
My problem is that I can not stop the sound after it plays for the fifth time. I think I need to use the for loop or a while loop, but I cannot program them correctly.
The loop:
for(i=0; i==5; ) {
sound.start();
if(sound.isPlaying()) {
if(false) {
sound.stop();
i++;
}
}
}
sound.stop();
well, now I built this code, but his only fault is the 'for' not working properly ... he is not repeat the code that is inside of him twice.
someone can tell me why?
for( counter=0; counter<2; ++counter){
new CountDownTimer(20000, 2000) {
public void onTick(long millisUntilFinished) {
//call to my UI thread every 2 seconds
sound.start();
}
public void onFinish() {
//final call to my UI thread after 10 seconds
chrono2.setBase(SystemClock.elapsedRealtime());
chrono2.start();
chrono2.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener() {
public void onChronometerTick(Chronometer chronometer) {
// TODO Auto-generated method stub
long elapsedTime = SystemClock.elapsedRealtime()-chronometer.getBase();
Log.i(this.getClass().getName(), "" + elapsedTime);
if (elapsedTime > 10000){
chrono2.stop();
chrono2.setBase(SystemClock.elapsedRealtime());
Toast.makeText(getApplicationContext(), "" , Toast.LENGTH_SHORT).show();
}
}
});
} // end onFinish
}.start(); // end count down
}
for(i=0; i==5; ) {
sound.start();
if(sound.isPlaying()) {
if(false) {
sound.stop();
i++;
}
}
}
sound.stop();
The second part of the for loop header is a condition which has to hold for the body to be entered. i=0 and i == 5 don't match, so the condition is wrong from the start and never entered.
You want to experess
for(i=0; i!=5; ) {
or
for(i=0; i<5; ) {
instead.
But where is i incremented or somehow else changed? In a block which is always false, in other words: Never.
Maybe you want to express that, if the statement before is false, do ...
You do so by negating the statement:
if (! sound.isPlaying ()) {
sound.stop();
i++;
}
Without knowing whether sound-playing is blocking or not it is hard to know how to control it.
Let's read the requirements and do it from scratch:
When you pressed a button, the application plays a sound lasting two
seconds, five times. After playing the sound for the fifth time the
application sleeps for thirty seconds. After sleeping, the cycle is
repeated two more times.
You have an outer loop of 3 times, and an inner loop of 5 times.
for (int i=0; i < 3; ++i) {
for (int j=0; j < 5; ++j) {
sound.start();
sleep (2); // seconds of sound
}
sleep (30); // seconds of silence
}
Just keep a counter variable that will tell the application to sleep when it has reached 5, in your while loop. Pseudo code is something like this :
final int REPEAT_RATE = 5;
int counter = 0;
while(counter < 3 * REPEAT_RATE)
{
if(counter == REPEAT_RATE)
{
//Sleep for thirty seconds
}
//Here Play the sound for 2 seconds
}
That is easy all you need is to use a count down timer:
new CountDownTimer(10000, 2000) {
public void onTick(long millisUntilFinished) {
//call to my UI thread every 2 seconds
playSound();
}
public void onFinish() {
//final call to my UI thread after 10 seconds
}
}.start();
And use a simple timer to sleep 30 seconds:
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
//do after 30 seconds
}
}, 30000);
By adjusting and combining these two you can make your effect...
EDIT: a solution (untested)
int repeatAlarm = 3; //above onCreate
....
playSoundFiveTimes(); //in onCreate
.......
private void playSoundFiveTimes(){
new CountDownTimer(10000, 2000) {
public void onTick(long millisUntilFinished) {
sound.stop();
sound.start();
}
public void onFinish() {
repeatAlarm--;
if(repeatAlarm > 0) wait30seconds();
}
}.start();
}
private void wait30seconds(){
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
playSoundFiveTimes();
}
}, 30000);
}
this is my solution:
you can use seekTo(0) function
then mp start again!
private void startCountDownTimer() {
cdTimer = new CountDownTimer(total, 1000) {
public void onTick(long l) {
mp.seekTo(0);
mp.start();
}
public void onFinish() {
mp.stop();
MediaPlayer doneMp = MediaPlayer.create(getApplicationContext(), R.raw.finished_challenge);
doneMp.start();
}
}.start();
}