I try to display series of png images in a single ImageView using Timer (e.g. change pic every 1 sec.).
The app keep crashing, Here is my code, please help.
There is ImageView in the main.xml , for some reason i cant post the full xml file here. Anyway it just a standard main.xml with extra ImageView within the Linear Layout.
public class AniImgTest extends Activity {
ImageView iv;
public int i=0;
Timer timer = new Timer();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
this.iv=(ImageView)findViewById(R.id.imageView1);
timer.scheduleAtFixedRate(new TimerTask(){
#Override
public void run() {
Log.v("","myDebug "+i);
if(i<2)
i++;
else
i=0;
switch(i){
case 0:iv.setImageResource(R.drawable.a1);
break;
case 1:iv.setImageResource(R.drawable.a2);
break;
case 2:iv.setImageResource(R.drawable.a3);
break;
}
}
}, 0, 5000);
}
}
Your task is running on a different thread than main thread, so it can't change the GUI and causes crashes. Use handler to perform those tasks on the main thread.
One more thing (which is not related, but...), instead of:
if(i<2)
i++;
else
i=0;
switch(i){
you can write:
switch(++i % 3){
use this block of code to change UI components
AniImgTest.this.runOnUiThread(new Runnable() {
public void run() {
// change your image here.
}
});
Related
I want to change the image of an Image view using a for loop, a String array and the png images in drawable folder.One Image should rest for 5 seconds then the next should appear.Here is the code I used.And it's not working properly.The images are not changing.It waits 5 seconds per each loop but the images are not changing.At last the last image is loaded.Please someone help me...
private String [] array1 = {"card2c","card2d","card2h","card2s",
"card3c","card3d","card3h","card3s",
"card4c","card4d","card4h","card4s",
"card5c","card5d","card5h","card5s",
"card6c","card6d","card6h","card6s",
"card7c","card7d","card7h","card7s",
"card8c","card8d","card8h","card8s",
"card9c","card9d","card9h","card9s",
"card10c","card10d","card10h","card10s",
"cardjc","cardjd","cardjh","cardjs",
"cardqc","cardqd","cardqh","cardqs",
"cardkc","cardkd","cardkh","cardks",
"cardac","cardad","cardah","cardas",};
for(int j=0;j<52;j++)
{
int resID_temp1 = getResources().getIdentifier(array1[j] , "drawable", getPackageName());
Drawable image_temp1 = getResources().getDrawable(resID_temp1);
Player1.setImageDrawable(image_temp1); // Player1 is the ImageView
try {
Thread.sleep(5000);
}
catch(InterruptedException ex)
{
Thread.currentThread().interrupt();
}
}
Tried the Timer
(for(int j=0;j<52;j++)
{
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
//switch image here
int resID_temp1 = getResources().getIdentifier(array1[j] , "drawable", getPackageName());
Drawable image_temp1 = getResources().getDrawable(resID_temp1);
Player1.setImageDrawable(image_temp1);
}
}, 0, 5000);
Based on your code example, you're changing the image resource, but then immediately sleeping the same thread that changed the image resource which will block it and prevent the image from visibly changing (particularly bad if this is the UI thread as this will lock up your app).
You should do as JohnyTex suggests and use a TimerTask to change the image every 5 seconds which does not require sleeping and so will not block the current thread.
Try using timers instead:
//Declare final variable here
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
//Switch (declared final) image variable here
}
});
}
}, 0, 5000);
Something like that... I am not by my computer though.
Concepts: runOnUithread and final variables might also be of interest to read about. final is because otherwise the variable cant be manipulated on another thread (actually Its only another scope really here). RunOnUiThread is because graphical components must only be manipulated on the main UI thread, although the TimerTask is run on another separate thread.
I know the title is somewhat confusing, my problem is this: I want to "pause" my program multiple times (via a loop) using sleep(ms) and make changes to several buttons that the user has pressed. I understand that changes to the UI can only be made in the main thread, so I am wondering how to convert this code into an Async task. I also remember reading somewhere that Async task can only be called once? If this is so, what other solutions could I look into?
View.OnClickListener SimulateButtonHandler = new View.OnClickListener() {
#Override
public void onClick(View v) {
for(int j=0;j<169;j++) //169 buttons to click
{
if(ClickedPoints[j]!=null) //how I keep track of which buttons has clicked
{ //clear button color
Drawable d2 = ClickedPoints[j].getBackground();
ClickedPoints[j].invalidateDrawable(d2);
d2.clearColorFilter();
}
}
Timer timer = new Timer();
for(int i=0;i<169;i++)
{
if(ClickedPoints[i]!=null)
{ //change the color after some time
Simulate(timer, i);
//clear color again
Drawable d2 = ClickedPoints[i].getBackground();
ClickedPoints[i].invalidateDrawable(d2);
d2.clearColorFilter();
}
}
}
};
public void Simulate(Timer timer, final int index)
{
timer.schedule(new TimerTask()
{
public void run() {
Sim(index);
}
}, 1000); //delay for some amount of time, then rehighlight the button
}
private void Sim(int i)
{
Drawable d1 = ClickedPoints[i].getBackground();
PorterDuffColorFilter filter = new PorterDuffColorFilter(Color.RED, PorterDuff.Mode.SRC_ATOP);
d1.setColorFilter(filter);
}
You'd be better off using a Thread to run your background work (and pausing) and a Handler to access the UI thread.
Here's a good tutorial on using handlers with threads.
I'm very new to Android. I've used Java before but not for around a year and a half. I'm having problems getting the screen to update, or rather the TextView. I have looked around the net for hours for solutions and I sort of know why its not working, but I don't know how to fix it.
public class PreliminaryActivity extends Activity {
//private static final int MENU_QUIT = Menu.FIRST;
int i = 0;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
getWindow().setBackgroundDrawableResource(R.drawable.background);
mainComputations();
}
public void mainComputations(){
runOnUiThread(new Runnable(){
//#Override
public void run(){
TextView tv = (TextView) findViewById(R.id.time_display);
tv.setText(new Integer(i).toString());
i++;
}
});
}
I've cut my program down so it should just increment an int value on the screen for testing and it still will not work. Instead it just displays '0'. If I add a for loop before the runOnUiThread() method, it will increment the i value but I have a feeling it is simply increasing the value then displaying it rather than it updating in real time. Any help would be greatly appreciated.
Go for TextSwitcher
http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/view/TextSwitcher1.html
If you want your textview to update with some delay.
use something like this.
final int length = 10;
Thread t = new Thread(new Runnable() {
#Override
public void run() {
for(int i=0 ; i<length; i++) {
runOnUiThread(new Runnable() {
#Override
public void run() {
tv.setText(new Integer(i).toString());
}
}) ;
i++;
Thread.sleep(500);
}
}
});
t.start();
In android, You can not update the UI from another thread. This is the restriction (which I consider a feature to remove unncecessary bugs) in android development. You can use AsyncTask for this...
In use, you can perform long task inside donInBackground() and than UI can be updated using onProgressUpdate()... see the AsyncTask example here
EDIT
see this similar question for more information...
Your problem is because you call the mainComputations() only once. You should take a look at AsyncTask and the Android Developer resource Updating the UI from a Timer
You can not Update Main UI Thread from another thread for that you need to use Handler. Refer this link for more details
http://www.vogella.com/articles/AndroidPerformance/article.html
What I see is that you call mainComputations only one time, so it is 0.
I have an "Activity" with three images. When one image is clicked, all the images are to switch to another picture. Is there a way to make the switches such that there is a 2 second delay before the images actually change (i.e. a 2 second delay in every 'for loop' below)? I am trying to do this with a timer but it does not actually to the delay when I run my program:
protected void onCreate(Bundle savedInstanceState) {
image1.setOnClickListener(this);
#Override
public void onClick(View arg0)
{
do_switches();
}
private void do_switches()
{
//loop through all images and change them
for(int j=1 ;j<=3; j++)
{
final int curr2=current;
final Handler handler = new Handler();
Timer t = new Timer();
t.schedule(new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
switch(curr2){
case 1:
image1.setImageResource(ImageArray[1]);
break;
case 2:
image2.setImageResource(ImageArray[2]);
break;
case 3:
image3.setImageResource(ImageArray[3]);
break;
}
}
});
}
}, 2000);
}
}
I have also tried using just SystemClock.sleep(2000) instead of the timer but I that didnt work either.I also tried setting up a Thread with a try/catch with no luck or maybe I didn't implement it properly. Is there a way to put this delay on every iteration of my for loop?
Thanks
Not one of best option, but still you can try CountDownTimer.
http://developer.android.com/reference/android/os/CountDownTimer.html
You can use handler.postDelayed(Runnable r, long timeInMillis). Make your runnable that changes the pictures and then call postDelayed() and pass in the runnable and 2000 for the time delay.
Edit: Ahh I see what you are trying to do. As far as I know you aren't going to be able to make a for loop pause for 2 seconds each time through. You can get the same effect though if you chain the postDelayed() calls. Just set up the next runnable and call postDelayed() on it inside the first one, and same for the third one from inside the second one. You will end up with the same functionality as a for loop that pauses for 2 seconds each iteration.
I have an array of drawables, that I would like to change by my own timer to a imageview.
(i tried the other option with xml and setBackgroundResource, but does not work for me as I have hundret of pics and always got memory problem as it looks android assign already the whole memory for all pics at once. (just in this demo i shorted it to 4 images)
Ok, so first i make my array
private static int[] draws = {
R.drawable.frankiearmevor_0001,
R.drawable.frankiearmevor_0002,
R.drawable.frankiearmevor_0003,
R.drawable.frankiearmevor_0002
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
imgView = (ImageView) findViewById(R.id.fredi);
// create timer
Timer updateProgressTimer = new Timer();
updateProgressTimer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
myloop();
}
}, 0, 150);
}
int mycounter;
public void myloop()
{
mycounter++;
if (mycounter > 4) mycounter = 1;
imgView.setImageResource(draws[mycounter-1]);
String hallo; hallo = "now: "+mycounter;
Log.d("1",hallo);
}
when I assign only a fixed image: imgView.setImageResource(draws[2]);
it shows that fine and I see also my thread is logged fine, but when I exchange the
fixed resource draws[2] into a dynamic draws[mycounter-1] .. i just get a black screen, no error, nothing.
what to do, so i will show the images :)
thx
chris
EDIT: 22. August:
I tried now with the comment I got, it compiles fine, but somehow there is an error i guess.. it crash:
imgView = (ImageView) findViewById(R.id.fredi);
Timer updateProgressTimer = new Timer();
updateProgressTimer.scheduleAtFixedRate(new TimerTask()
{
#Override
public void run()
{
//myloop();
imgView.post (new Runnable()
{
public void run()
{
mycounter++;
if (mycounter > 10) mycounter = 1;
imgView.setImageResource(draws[1]);
//imgView.invalidate();
String hallo; hallo = "now: "+mycounter;
Log.d("1",hallo);
}
});
}
}, 0, 150);
The ImageView update should happen on the UI Thread...
Refer this answer. The TimerTask runs on a different thread, so you've to use the imgView.post() to update the UI Component.
Are you sure you need to update the Component every 150ms? That's very expensive.
Good Luck.