Multiple button animations in sequence -- only last one shows - android

I have a view in android in which I need to sequentially highlight and unhighlight buttons when a particular control is pressed. This is a usability feature -- as each button is highlighted, it is read aloud to the user. I use the AlphaAnimation class to accomplish the highlighting. However, now matter how many invalidate calls or callback threads I put in, only the last animation is actually presented to the user. The others are still called but overridden by the last animation so only one is shown. I have also tried simply setting the opacity/alpha properties of the buttons, but all of these modifications end up being batched and performed all at once. I need these animations to occur in a sequence. I have not yet found a good way to update the main view before control flow is returned to it (i.e. update it multiple times before the method it calls returns). Does anyone have any ideas?

For everyone else who runs into this problem, I finally found a solution.
The documentation:
http://developer.android.com/reference/android/os/AsyncTask.html
http://www.anddev.org/tut_updating_ui_from_a_thread-t11125.html
My solution: create an AsyncTask that takes in an array of buttons. In its doInBackground method, it highlights/dims and then pushes an update of the effected buttons to the onProgressUpdate method during each iteration in the button highlighting scheme. The onProgressUpdate method calls invalidate() on all the buttons passed in. Then for easy access to the highlighting functionality, I created a static highlight(buttons...) method that creates a new instance of the AsyncTask and calls execute on it.

Related

Animate a dynamic number of Views and then set them invisible/gone

In an Activity, I am retrieving data from a server. There are a limited number of TableRows containing further Views pre defined in the layout xml file, all set to android:visibility="gone". Further there's an array in the java class with all IDs of these TableRows.
For each entering "data entry", I fill such a TableRow, set it visible and animate it (the animation is a 'push in' from a randomly choosen vertical side). As an further hint, which is important later in this question, every data packet retrieving from the server is related to a month.
Whenever I get data, I do following process
Fill the still invisible TableRows with the information
For every time step 1 is executed, a value in a boolean array is set to true
call showAnimation()
for every entry that is true in the boolean array, get TableRow at index i in the id array, set an Animation and set visibility to visible
This works fine. Even if the visibility is set before starting the Animation, it doesn't matter, since this takes so few time, that the Animation has already begun in our eyes.
Now comes the problem: the reverse way doesn't work. Let me clarify: I want, that the TableRows are pushed out of the window, and THEN set to invisible resp. gone whenever I change the actual month, and the new entries are pushed then in. The problem is, that as soon the Animation starts, the Views are set to invisible / gone. I tried to solve this with an AnimationListener like explained here in the first answer. This leads to two possible ways:
Define such an AnimationListener for each TableRow and set the visibility in the onAnimationEnd(). I find this is very ugly, since it is not dynamical.
Have access to a kind of index in the AnimationListener and set the same Listener to every TableRow's Animation. Here I don't know how possibly solve this. As I discovered earlier, setting Animations on Views set in a loop (a for loop in my case) results in the Animations beeing started when the loop has finished, and not whenever it is set. So even if I would carry a global index variable in that for loop to be used in the onAnimationEnd(), it obviously would came to nothing.
Do someone knows a better way to implement this? Solving it with a Handler.postDelayed() does not do the trick, since it is possible that the new data has already come from the server, and therefor the new entries are already visible (and thus the new ones are set to invisible).
ok I thought a lot about it and honestly I agree with you that it's not the nicest way, but due to the framework limitations the 1st way is still the best one.
It will be nice if we could from the listener call back do:
public void onAnimationEnd (Animation animation){
animation.getView().setVisibility(View.Visible);
}
// but this doesn't exist.
Just make sure every time you're setting an animation to start to do:
Animation anim = row.getAnimation()
if(anim!=null){
anim.setListener(null); // to avoid the listener to be called
anim.cancel(); // to stop it from running
}
// and then go ahead and setup a new animation with new listener
anim = new MyAnimation();
anim.setListener(new SetToInvisibleListener());
row.startAnimation(anim);

How To Determine When ListView is Done Populating

I need to manipulate a ListView's children when it is done loading, but I can't seem to find a way to find out when this happens. When I set the adapter of my ListView, the method returns immediately, but the population of it's children views happens asynchronously. Is there a way to handle the event when my list is full of views?
You can either do a periodic polling to see if the list has been populated: write a while() loop to check once in a while. Or you could wait for a fixed amount of time (say 30 ms) before doing your next operation. These are not recommended methods, but should solve your problem.
Use getChildCount() to retrieve the shown views and also use a counter to keep track of how many views have been loaded asynchronously. I think I understand your question right.

notifyDataSetChanged being called prevents user interaction (Android development)

I have a problem where calling notifyDataSetChanged() a bunch of times will freeze interaction with a listview for a brief second.
Basically my app loads a bunch of images into a listview. After each is loaded it posts to the ui thread. The ui thread adds the image to a listarray and then calls notifyDataSetChanged().
When you select an image in the list it highlights. When I call notifyDataSetChanged() per image, every one of three taps on the list might actually select. If I throttle down notifyDataSetChanged(), I get a much better rate of tapping and having it select the item.
Anyone have hints on this?
It seems like the 6 thumbs visible (which are unchanged) get thrown out really quick and swapped in again, but the UI shows no indication of them being deleted. During which tapping is an invalid data set.
Don't call notifyDataSetChange() in the UI Thread. it will definitely block the User interaction if it is doing the data call and update the ListView. so do it in the AsyncTask do in background thread which is not doing on the UI thread so it will update the listview when user scroll it

What event is fired after all views are fully drawn?

I need to capture the absolute positions of some ImageViews to use as drop targets. I can't seem to find what event I need to put my code in to read the screen and get the Left(), Top() .. positions. I do not want monitor the inflation of each individual view. There must be some sort of onScreenFinsihed type of event, but I can't find it. onMeasure and onDraw seem to fire at the start of their work, I need to know when they are done. TIA.
There is no such event. You can simply post a message/Runnable in the UI events queue at the beginning of a drawing sequence to have this message/Runnable executed after drawing is complete (see View.post(Runnable) for instance.) Also, getLeft/getTop return the correct value after measurement and layout, you don't need to wait for drawing to end to use them.

Android - fancy ListView background problem

I have a ListView backed by customized ArrayAdapter where each item has 2 LinearLayouts - one I call head, and the other one - body.
The body is hidden (gone) until user clicks on the row at which time it slides out. The second click (on the head) will hide the body. However if user clicks on the body it brings another activity. All of this works just fine, here comes the problem:
When user presses on body I want a visual indication of the action just the same way as regular list item will flicker an orange background when pressed. I'm not getting this by default since (my theory) the onPress event is intercepted by body's view and not processed by the list item.
The first thing I tried was to execute body.setBackground('#ff00ff') (never mind the color) in onPress event. That didn't work since (I suspect) there's no repainting after the call. Then I dig a little bit more and decided to use <selector/>-based background. I defined body_background.xml in drawable folder and assigned that to the body's background property.
There I noticed that background will only change if the even is processed by the list. For example if I set <item android:state_selected="true" android:drawable="#drawable/selected"/> then when I press on the head - the background of both elements (head and body) will change, however when I press on body - nothing.
So to summarize my question - how do I change background of the child element in the list item if I assign custom onClick handler to it? Any hints will be greatly appreciated
OK. Here's some more info I dig along the way.
I'm currently trying to switch implementation to ExpandableListView which provides the functionality I had to coded in (sliding body). The problem I may have here is that I have a fancy "endless" list implementation and I'm using ArrayAdapter#add method to dynamically add items to the list while scrolling (see my tutorial on androidguys.com) Well, the add method is missing from the BaseExpandableListAdapter so I need to see if adding items to internal array will work (it didn't for ArrayAdapter) possibly doing ExpandableListView#notifyChanged() will take care of that
The fact that I don't see anything when I'm directly using setBackgroundColor method is probably due to the subsequent call to startActivity call that halts all painting until new Activity is displayed
P.S. this has been resolved by switching to ExpandableListView. And may I add - it's beautiful! No need to invent anything

Categories

Resources