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.
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'm having an awful time trying to get a simple Android app to work properly. I've very little experience in Java, having come from C, and I'm trying to start small with a simple clock app that will update the display every second. Here's my Java code:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String currentdatetime =
DateFormat.getDateTimeInstance().format(new Date());
final TextView textview = new TextView(this);
Handler handler = new Handler();
Runnable runnable = new Runnable() {
#Override
public void run() {
String currentdatetime =
DateFormat.getDateTimeInstance().format(new Date());
textview.setText(currentdatetime);
}
};
textview.setGravity(Gravity.CENTER);
textview.setTextSize(20);
textview.setText(currentdatetime);
setContentView(textview);
handler.postDelayed(runnable, 1000);
runnable.run();
}
I'm running this in Debian Linux with the Google-provided ADT bundle, and have followed all the suggestions Eclipse gives for fixing these problems, to no avail. The program compiles fine and displays exactly as I'd expect it to, except that it does not update at all. I've scoured Google as best I can and have followed many different ways of doing this, but I've not been successful.
What I'd expect this program to do is, on creation, set "currentdatetime" to the current date and time, stick it in a TextView, and then change the TextView to the main view. I'd expect it to then hit handler.postDelayed and do this again every thousand milliseconds. Clearly, though, that's not what's happening.
I'm afraid I'm completely lost. Can anyone point me in the right direction?
Well, appears that I was on rather the wrong track. I've got the code working now, rather more neatly, with the following:
protected void onCreate(Bundle savedInstanceState) {
final Handler handler = new Handler();
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView textview = new TextView(this);
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
String currentDateTimeString =
DateFormat.getDateTimeInstance().format(new Date());
textview.setGravity(Gravity.CENTER);
textview.setTextSize(60);
textview.setText(currentDateTimeString);
setContentView(textview);
}
});
}
},1000,1000);
}
So thanks to anyone who was getting ready to answer.
I am using Eclipse for Android. I am trying to make a simple repeating Timer that has a short delay.
It will start after a TextView timerTV is clicked. This code is in the onCreate method:
timerTV = (TextView) findViewById(R.id.timerTV);
timerTV.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Timer gameTimer = new Timer();
TimerTask doThis;
int delay = 5000; // delay for 5 sec.
int period = 1000; // repeat every sec.
doThis = new TimerTask() {
public void run() {
Toast.makeText(getApplicationContext(), "timer is running", Toast.LENGTH_SHORT).show();
}
};
gameTimer.scheduleAtFixedRate(doThis, delay, period);
Everytime I try to run it, a "Class File Editor" pops up with the error:
"Source not found"
The JAR file C:\Program Files\Android\android-sdk\platforms\android-8\android.jar has no source attachment.
You can attach the source by clicking Attach Source below:
[Attach Source...]
When I click this, Eclipse asks me to select the location folder containing 'android.jar'
I tried to do this, but cannot navigate all the way to the folder it is located in anyway.
I presume the issue is in my code somewhere.
I have been searching for hours, even copied and pasted code many times.
Using an actual Timer (java.util.Timer) in conjunction with runOnUiThread() is one way to solve this issue, and below is an example of how to implement it.
public class myActivity extends Activity {
private Timer myTimer;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
myTimer = new Timer();
myTimer.schedule(new TimerTask() {
#Override
public void run() {
TimerMethod();
}
}, 0, 1000);
}
private void TimerMethod()
{
//This method is called directly by the timer
//and runs in the same thread as the timer.
//We call the method that will work with the UI
//through the runOnUiThread method.
this.runOnUiThread(Timer_Tick);
}
private Runnable Timer_Tick = new Runnable() {
public void run() {
//This method runs in the same thread as the UI.
//Do something to the UI thread here
}
};
}
SOURCE: http://steve.odyfamily.com/?p=12
Try using Project -> Clean then right click your project and find Fix Project Properties. Check your Build Path. It could be any one of these things. Restart eclipse, make sure your Android Manifest is targeting the correct API, 8 I assume?
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 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.
}
});