I am trying to make a image slider in android that scrolls automatically after every 2000s. I have written the code ,but i don't know to loop the code automatically after every 2000s. Now I have 2 static images to test the slider scroll ,it just scrolls to the second image and stops.but it is not looping continuosly to 1st one when it reaches the last image.
Here is my code(i want to loop this code continuously)
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
mRecyclerViewTwo.smoothScrollToPosition(1);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
if (2 <= mPostad.size()) {
mRecyclerViewTwo.smoothScrollToPosition(2);
} else {
mRecyclerViewTwo.smoothScrollToPosition(1);
}
}
}, 2000);
}
}, 2000);
Please help.
Any help is appreciatable.
You can use a ScheduledExecutorService:
Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(this::codeToExecute, 0, 2, TimeUnit.SECONDS);
private void codeToExecute() {
if (2 <= mPostad.size()) {
mRecyclerViewTwo.smoothScrollToPosition(2);
} else {
mRecyclerViewTwo.smoothScrollToPosition(1);
}
}
Edit: That said, from reading your question you may well find a pre-existing widget that does this job for you. Maybe a ViewFlipper?
Related
I'm using this code to change between different images, but the only image that is visualized is the last one. The TextView "vista_aterrizaje" does not show the expected value in each loop.
I have tried to use invalidate() method before the sleep() one, to try to visualize it in each different loop of the for. But it does not work.
establecerImagen() method is used for changing the imageView.
for (int i = 0; i < 15; i++) {
cur_aterrizaje = aterrizajes[rand.nextInt(aterrizajes.length)];
vista_aterrizaje.setText(cur_aterrizaje);
establecerImagen(cur_aterrizaje);
vista_aterrizaje.();
mapa.invalidate();
try{
Thread.sleep(50);
} catch (Exception e) {
e.printStackTrace();
}
}
I think that the problem is in the sleep() method but I don't know how to wait a few seconds after every change of the views in order to visualize every change.
Try using CountDownTimer.
// here interval 1000 stands for 1sec,
//so onTick() will be called 15 times, each call after 1 sec interval. so you can set your own values as per your need.
int i=0;
long interval = 1000;
new CountDownTimer((15 * interval), interval){
#Override
public void onTick(long l) {
vista_aterrizaje.setText(i+"");
establecerImagen(cur_aterrizaje);
i++;
}
#Override
public void onFinish() {
}
}.start();
The parameter to sleep() is in milliseconds. So if you want to show each image for 1 second, the parameter should be 1000.
A better way to do it would be like this:
handler=new Handler();
Runnable r=new Runnable() {
public void run() {
//display your image here -- it will be displayed after a 1-second delay
}
};
handler.postDelayed(r, 1000);
I have a for loop in which I would like to call the setText method. This works without any errors except for the fact that the text does not change until the script is done running. What I want it to do is change the code every time I call the setText method. I attached my code below, it should be pretty strait forward.
code:
package com.example.zoe.andone;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import java.util.concurrent.TimeUnit;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void startLoop(View view) {
String string = getString(R.string.hello);
((TextView)findViewById(R.id.hello)).setText("starting...");
for (int i = 0; i < 10; i++) {
String updated = Integer.toString(i);
((TextView)findViewById(R.id.hello)).setText(updated);
try {
Thread.sleep(250);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
((TextView)findViewById(R.id.hello)).setText("done!");
}
}
That's what is called "dropping frames".
It's time to learn!
Before going to the answer, let's explain what's going on here.
You probably already know that android has a frame-rate of 60fps (60 frames per sec), which means that every 1/60 sec the screen is rendered and displayed to the user (in order to provide the best definition). It does that by running some rendering code on your app (and everywhere else where there's something to be rendered) every 1/60 sec to compute how the displayed screen should look like at this particular ms (it's is called a frame).
However, the code doing that is running on the UI thread, and if you're doing anything when the rendering tick kicks in, the android framework simply drops that frame (it won't compute it).
In your case Thread.sleep(250); is what causes your frames to be dropped cause it's holding the UI thread for 250 ms in every iteration of your for loop (so it's 250 ms * (10 - 1), that's many frames).
Dropping a frame means seeing no update on the UI.
Solution
Instead of using Thread.sleep(250); and dropping frames, you should schedule your update tasks to run every 250 ms. That's it.
private int i = 0; // Does the trick!
public void startLoop(View view) {
String string = getString(R.string.hello);
((TextView)findViewById(R.id.hello)).setText("starting...");
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
if (i < 10) {
String updated = Integer.toString(i);
i++;
updateHelloOnUiThread(updated);
} else {
updateHelloOnUiThread("done!");
handler.removeCallbacksAndMessages(null);
i = 0; // For future usages
}
}
},250);
}
private void updateHelloOnUiThread(final String text) {
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
((TextView)findViewById(R.id.hello)).setText(text);
}
});
}
Further reading
Android UI : Fixing skipped frames
High Performance Android Apps, Chapter 4. Screen and UI Performance
this.runOnUiThread(new Runnable() {
#Override
public void run() {
int globalTimer = 0;
int limitTimer = 10;
int i = 0;
// create Timer
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
globalTimer++;
//run your code
((TextView)findViewById(R.id.hello)).setText(i+"");
i++;
//check if globalTimer is equal to limitTimer
if (globalTimer == limitTimer) {
timer.cancel(); // cancel the Timer
}
}
}, 0, 250);
}
});
The problem is, you're calling Thread.sleep on the UI thread.
If the thread is sleeping, it can't update the UI(what's displayed on the screen).
I'm developing my first android game without xml files for layouts in eclipse. This is calling MyGameView.class(extends View) from MyGameActivity.class(extends View implements OnTouchListener)
MyGameView myView;
myView = new MyGameView(this);
myView.setOnTouchListener(this);
setContentView(myView);
Everytime, I touch (MotionEvent.ACTION_DOWN), I update the Canvas in MyGameView.class with the following code. This is the code I use to update MyGameView.class from MyGameActivity.class.
myView.invalidate();
Yes it works!But I got a serious problem now.I need to move Canvas in MyGameView.class by every 0.3 second.I use Thread to update but it forced stop!!!! I tried again and again and again! I failed!
public void runtime() {
i = 0;
Thread timer = new Thread(new Runnable() {
#Override
public void run() {
while (i<1500) {
try {
Thread.sleep(300);
}
catch (InterruptedException e) {
e.printStackTrace();
}
finally {
if (right) {
i++;
//This is static int a from MyGameView.
MyGameView.a += 2;
myView.invalidate();
}
else {
i = 1500;
}
}
}
}
});
timer.start();
}
Updating Static int or boolean to MyGameView.class from MyGameActivity.class with myView.invaldate(); is working. But I can't control it with Thread! Is there something wrong with my Thread running code?
It's probably up to Thread because I can move +2 along X-axis to right everytime I press (MotionEvent.ACTION_DOWN).
//I can Move with this code but not with Thread!
case MotionEvent.ACTION_DOWN:
MyGameView.a += 2;
myView.invalidate();
break;
With Thread, it stops! Please give me a solution for this! In other words, I need to count with time without error and update canvas on every count!
Invalidate must be called from the UI thread. Try calling
postInvalidate()
instead.
See this for reference.
I am programming a game where as one image changes place with another and I want the second image to be removed after 200ms, something I really could use some help with.
I'm still a beginner and all help is appreciated! Answer as if you were talking to a five year old!
public void setVisible(Boolean visible) {
ImageIcon ii = new ImageIcon(this.getClass().getResource(explode));
image = ii.getImage();
//this.visible = visible;
/*WITH THIS LINE OF CODE THE EXPLODE DOES NOT SHOW AT ALL,
I WANT TO MAKE SURE IT SHOWS BUT ONLY FOR 200MS*/
}
Thanks in advance!
You can use a scheduled thread for it. You can use the ScheduledExcecutorService for it
private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
public void displayImageFor200Ms(){
ImageIcon ii = new ImageIcon(this.getClass().getResource(explode));
image = ii.getImage();
scheduler.schedule(new Runnable() {
public void run() {
// remove image now!
}
}, 200 , TimeUnit.MILLISECONDS);
}
don't forget to shut down the scheduler when you don't need it anymore (you could use a global, pooled Scheduler for all your delayed actions and shut it down when your game is over)
Since you shouldn't do these time blocking methods like Thread.sleep(200) in the EDT, here is another solution with the Timer and TimerTask classes:
public void setVisible(boolean visible) {
ImageIcon ii = new ImageIcon(this.getClass().getResource(explode));
// show / hide image
ii.setVisible(visible);
if (visible) { // only hide image, if it's previously set to visible
new Timer().schedule(new TimerTask() {
public void run() {
ii.setVisible(false);
}
}, 200); // hide it after 200 ms
}
}
Thanks #AndrewThompson for the advice!
I'm attempting to make a basic app and for part of that app I needed a delay after a button is pressed to allow for a text view to show a word for a second, and then change to another word and then have that display for a second and show another word. S0 3 words, 2 delays. i achieve the first delay using postDelayed() which works fine.
#Override
public void onClick(View view) {
// TODO Auto-generated method stub
switch(view.getId())
{
case R.id.bStart:
display.setTextColor(Color.YELLOW);
display.setText("READY");
start.setText("Restart");
timer.postDelayed(makePattern, 1000);
break;
}
}
The app displays "READY" for one second then opens a new thread and then starts the makePattern runnable which is where the problem is.
makePattern = new Runnable()
{
#Override
public void run() {
display.setTextColor(Color.GREEN);
display.setText("GO!");
for(int x = 0; x < level; x++) {
pattern[x] = crazy.nextInt(4);
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
display.setText("IT WORKED");
}
}
};
Here it should be displaying "GO!", pausing the thread for a second and then displaying "IT WORKED". However when I run it on both my phone and the emulator it displays "READY" for 2 seconds and then skips to "IT WORKED" either displaying "GO!" for such a short amount of time that it can't be seen of skipping over it all together. I have already tried moving the setText("GO!") inside of the catch and that didn't work either. Any Help would be much appreciated.
THANK YOU!
You could create a second Runnable and schedule that using postDelayed, like you're doing for the first. In the same place you schedule the first for 1 second later, you could schedule the second to occur 2 seconds later, which would be 1 second after the first. Or, you could schedule it from within the first runnable for 1-second later. See the "OPTION" comments in the code below.
#Override
public void onClick(View view) {
// TODO Auto-generated method stub
switch(view.getId())
{
case R.id.bStart:
display.setTextColor(Color.YELLOW);
display.setText("READY");
start.setText("Restart");
timer.postDelayed(makePattern, 1000);
timer.postDelayed(showItWorked, 2000); // <-- OPTION 1
break;
}
}
makePattern = new Runnable()
{
#Override
public void run() {
display.setTextColor(Color.GREEN);
display.setText("GO!");
for(int x = 0; x < level; x++) {
pattern[x] = crazy.nextInt(4);
}
timer.postDelayed(showItWorked, 1000); // <-- OPTION 2
}
};
showItWorked = new Runnable()
{
#Override
public void run() {
display.setText("IT WORKED");
}
};
And just to clarify what's going wrong in your existing code...
As Mael mentioned in his comment, your use of Thread.sleep is blocking the UI thread. Just because the the code is within a Runnable does not necessarily mean that it's running on another thread. From the Android documentation for Handler.postDelayed (I'm assuming "timer" is a Handler): "Causes the Runnable r to be added to the message queue, to be run after the specified amount of time elapses. The runnable will be run on the thread to which this handler is attached."