In Android, I need to start and display multiple CountDownTimers at the same time, on the same screen, one after another. How can I proceed implementing this? Will using threads help?
you can define and array or list for each timer you want to run,
and define a timer that decrements them every second.
https://chat.stackoverflow.com/users/443141
has an example on how to schedule tasks every second. In the method that gets
called every second, decrement the values of all arrays and update a text-label.
...
for ( int i=0; i < timers.length; i++) {
if ( timers[i] > 0 ) {
timers[i]--;
// update your textlabel
} else {
// change the text color, flash,vibrate,...
}
}
...
to reset a timer simply set a new seconds left value.
Related
I have implemented scroll view and I need to detect the visibility of the view when scrolling and trigger that event once per screen initialization.
But, at random times, I get it triggered multiple times in a very short time (a few ms), and it messes up with my logic in VM.
Is there a way to restrict this triggering and make it trigger once every 100ms or something similar?
An easy way to do this is something like this right where the trigger happens
if (System.currentTimeMillis() - lastTime < 100)
return
else {
lastTime = System.currentTimeMillis()
// rest of your code
}
where lastTime is just some variable you keep in your class
i have a question, i have a for loop, that loops through an arraylist and checks if a value is something, and if so, it deletes an row in a listview....I am having trouble though, this is the code...
for (int i=0; i<displayList.size(); i++)
{
Object toRemove = mAdapter.getItem(i);
Log.e("Counter+++",String.valueOf(i));
if (!firstname.equals("")) {
if (firstnamefilterstring.equals("Contains"))
{
if (!displayList.get(i).getFirstname().contains(firstname))
{
//displayList.remove(listView.getItemAtPosition(i)); doesnt work
// displayList.remove(toRemove); doesnt work either
L.e("1");
}
The problem is through debugging I have realized this loop only runs 6/12 times (the for loop is 12 elements big), and I have no clue why... Through some additional debugging, I realized that the two lines with "doesnt work" if you comment them out, it runs fine (12 times), but with either of those two lines it doesnt....Im at a lost here,
The reason it runs half the time is you are removing items from your display List, hence displayList.remove.
The java.util.ArrayList.remove(int index) method removes the element
at the specified position in this list. Shifts any subsequent elements
to the left (subtracts one from their indices).
I played a little around with CountDownTimer. However, for a special app I need the following functionality:
Start CountDownTimer with random runtime
Beep when finished
Wait 5 Seconds
Beep again
GOTO 1.
This procedure should be startet with a button and should also be canceled with a button. I found post here with a looped CountDownTimer, but this doesn't work with random runtime.
Okay, I'm not going to give you the code. That's your homework. I will however explain how the countDownTimer will work.
Once you've set up the CDT class create a new object.
private static myCDT newTime;//static makes sure there's only one instance of the variable in the entire program
newTime = new myCDT(randNum*1000, 1000);
Say randNum is 10, then the count down is for 10 seconds.
To generate the random number find out what you want the max limit to be. I'm assuming it to be 50. So the CDT will have an option from 0-50s.
int randNum=50*Math.random();
If you want to exclude 0 and want the minimum to be 1s
int randNum=1+49*Math.random();
Now also set a boolean variable for the button. The first time it's clicked let it be set to true. Use this variable as the condition in a while. Now, if the user clicks the button again, set the variable to false. Call the cancel() function for your CDT object newTime. Now call onFinish() function for your CDT. This will bring back flow of control to the while loop, the condition will now be false and so the loop stops. Make sure this loop is in the click listener function of the button. Or in any other function but be sure to call it from the click listener.
I'm trying to find some kind of elegant solution for fading in/out a TextView that is part of an item in a ListView.
To give you some context, the listview shows a list of players in a basketball game. The user taps on a name and is provided with a dialog to log an event, for example a shot or a foul for that player. Once the dialog is dismissed the user is brought back to the listview and it is here that I'd like to provide some feedback about the event that has just been logged.
The way I'd like to do it is to have a small string appear for about 5 seconds in the view of the item (player) that has just been tapped on. The small string would display something like "3rd foul" or "4 turnovers".
A naive implementation is straightforward. Change the text of the view to the required string and then start an animation that fades in the view, keeps it there for a while and then fades it out. Problems arise however when a second event for the same player is logged shortly after the first. Ideally the first feedback string should be allowed to stay for the allotted 5 seconds and the second string should fade in/out in the next 5 seconds.
This queueing of animation and text changes on a per-player bases I'm not quite sure how to implement. Furthermore, I'm concerned by the interaction between the animations and the Activity's life cycle. What happens (or should happen) to the queued animations when the activity is sent to the background, stopped or even removed from memory? Or when an item is removed from the ArrayAdapter behind the listview?
Thoughts?
Manu
Don't worry about the lifecycle of the activity. There will be no adverse effects. However if the activity goes into the background during the animation, the animation will take place and you will not see it.
As for haveing one animation wait for the next, simply do this:
// here we will keep track of any listView and when the last animation took place.
// The keys will be your listView identifiers. Here I assumed an integer, but use whatever is a good ID for your listView
private HashMap<Integer, Long> listViewLastAnimations;
// the length of the animation in milliseconds
private static long ANIMATION_LENGTH_MS = 5000;
// put this code where you would start your animation
// get when the last event animation occurred
Long lastAnimation = listViewLastAnimations.get(YOUR_LIST_ITEM_IDENTIFIER);
Date new = new Date();
if (lastAnimation == null ||
new.currentTimeMillis () - lastAnimation > ANIMATION_LENGTH_MS ){
listViewLastAnimations.put(YOUR_LIST_ITEM_IDENTIFIER, new.currentTimeMillis ());
// perform animation as normal
}else{
// set a delay to your animation with
long delay = ANIMATION_LENGTH_MS - (new.currentTimeMillis () - lastAnimation);
listViewLastAnimations.put(YOUR_LIST_ITEM_IDENTIFIER, new.currentTimeMillis () + delay);
setStartOffset(delay) ;
}
Creating a layout in Java as the number of TableLayouts required is not known as designtime.
I get an IllegalStateException telling me to remove the View (from it's current parent) before assigning it to another parent, when I call createPlayerTables()
The exception is thrown at the first line in this loop, when I try to add an ImageView from the List of ImageViews to the first TableRow:
for (int i = 0; i < 3; i++) {
tableRowsLst.get(0).addView((ImageView) imageViewsLst.get(i));
tableRowsLst.get(1).addView((ImageView) imageViewsLst.get(i+3));
}
The error suggests that the ImageView has already been added to a ViewGroup, but seeing the code below, I create new ImageViews, and I only add them to an ViewGroup at the line that it errors at, so I'm not sure why it's failing.
// List<ImageView> imageViewsLst = new ...
// List<TableRow> tableRowsLst = new ...
/**
* Initialises the TableLayouts, one per player
*/
private TableLayout createPlayerTables(int playerNum) {
...
for (int i = 0; i < 6; i++) {
imageViewsLst.add(new ImageView(this));
...
}
for (int i = 0; i < 3; i++) {
tableRowsLst.add(new TableRow(this));
...
}
for (int i = 0; i < 3; i++) {
tableRowsLst.get(0).addView((ImageView) imageViewsLst.get(i));
tableRowsLst.get(1).addView((ImageView) imageViewsLst.get(i+3));
}
...
}
In this loop:
for (int i = 0; i < 3; i++){
tableRowsLst.add(new TableRow(this));
tableRowsLst.get(i).setLayoutParams(
new TableLayout.LayoutParams(LayoutParams.FILL_PARENT, dipToPixels(55)));
tableRowsLst.get(i).setOrientation(LinearLayout.HORIZONTAL);
}
you just keep adding new TableRows to tableRowsLst, but you always only use the first three elements.
Clear the list before the loop:
tableRowsLst.clear();
Although not the case in this example, another common cause of this problem is not correctly utilizing onCreateDialog() and onPrepareDialog(). The onCreateDialog() is called only once and anything done here will persist. If you are adding dynamic content to a layout (Dialog), you probably want to use onPrepareDialog() which will happen after create but before each display. To quote from the Android documentation:
Before the dialog is displayed, Android also calls the optional callback method onPrepareDialog(int, Dialog). Define this method if you want to change any properties of the dialog each time it is opened. This method is called every time a dialog is opened, whereas onCreateDialog(int) is only called the very first time a dialog is opened. If you don't define onPrepareDialog(), then the dialog will remain the same as it was the previous time it was opened. This method is also passed the dialog's ID, along with the Dialog object you created in onCreateDialog().
Aha! Okay, after a couple false starts, here's the problem.
imageViewsList is a member variable. You're adding 6 views every time you call createPlayerTables, THEN USING THE FIRST 6 each time. First pass (player 0), no problem. Second pass (player 1): boom.
Option 1) Don't save them. The given code doesn't need them, though that doesn't cover all the bases by any stretch. You could dig them out of the table rows and cast them in a pinch.
Option 2) Offset your access to imageViewsList by playerNum * 6 (which will == imageViewsList.size() when createPlayerTables() is first called)
Friendly advice: You could have found the problem in a couple different ways:
Log.d() with the object ID before each call to TableRow.add() would have revealed the same object ID used in the second pass immediately followed by your exception.
Stepping through your code in the Handy Dandy Debugger. Yes, that's a lot of code to step through to figure out what was going on in this case. A couple different break points would have made it easier to see which call to createPlayerTables() was throwing and allowed you to step into cpt() only when it was going to throw.
Asking yourself "what could I have done to catch this" every time you've figured out a bug will improve your debugging skills IMMENSELY.