Adapter "holding on" to view when I animate it - android

I'm using a custom adapter for a GridView, and feeding it an ArrayList of my custom data class.
The idea is, when the user presses (+) on an item, its number goes up, and when they press (-), it goes down.
This has worked perfect with the following code:
Activity:
//playerLayouts is the ArrayList of my Player class.
playerLayouts.get(position).changeLife(-1); //All this does is decrement life by 1.
adapter.notifyDataSetChanged();
Adapter:
holder.textLife = (TextView) row.findViewById(R.id.player.text_life);
...
holder.textLife.setText(Integer.toString(player.life));
So this works great. I press plus, it goes up, I press minus, it goes down. All is well.
But, if I want to put a little "-1" popup in the view that shows that 1 has been subtracted, and I animate the view, a problem arises.
...
//textLifeChange is a different TextView in the layout. Also, I'm using NineOldAndroids.
textLifeChange.setText(Integer.toString(player.lifeChange));
animate(holder.textLifeChange).setDuration(2000).alpha(0); //There are a few more animations in addition to this one.
Basically, whenever the animation is playing (which is a full two seconds), the view doesn't do any more updates.
For example, say "life" = 20. I hit (-), and now it says 19, and my little popup shows "-1" and fades out. Then, just ONE second later, I hit (-1) again. Nothing happens. The "life" TextView still says 19, and the popup just keeps playing its animation with no change. So I wait another second, and the animation is finished. NOW if I press (-) again, it updates properly again.
Interestingly, if I log my setText method, I see that it is updating with the correct number, and getView is being called, but it's just.. not updating visibly.
What's wrong?

I daresay that your animation is hogging UI Thread, and thus prevents changes in other parts of interface. This asnwer shoud help you:
Android: Running thread preventing animation from starting

Related

Android RecyclerView items empty when being swiped after switching apps

First of all, I have looked at similar questions (for example, this one: Android RecyclerView ItemTouchHelper revert swipe and restore view holder). This already helped a great deal, until I - more or less, accidentally - noticed my current (and hopefully, final) issue with this screen of mine.
Let's start with the setup:
I have a fragment with a RecyclerView filled with some CardView items (it's a little fancier, but that's what is important right now). I also created an ItemTouchHelper with the implementation of SimpleCallback (nothing in onMove()) to make swiping the items (right) possible. For the record: I am using API 27 right now.
So far, so good.
What I want to achieve:
I want to be able to swipe the items to be notified through the onSwiped() method of my SimpleCallback implementation. Also, I do NOT want the items to disappear, be removed, or otherwise taken out of my list of items in the RecyclerView. I just want to swipe them and have them return to their original position afterward (and yes, I know that it is sort of assumed that swiped items get removed). I am using the notifyItemChanged() method of my adapter in the onSwiped() method (also tried using notifyDataSetChanged()).
The problem:
Funnily enough, that works (mostly thanks to the aforementioned question) - until I hit that "app switch" button (don't know if there's actually one official name for it) and send the app to the background. Once I put it in the foreground again and start swiping, the items will not (visually) return. They are still on the list, and if I scroll or click the "app switch" button again, they will be displayed properly again (but won't return on swiping). Same if I navigate back one screen and come back to the list.
That makes me think something happens when I send the app to the background and recover it. Something different than navigating to that screen (in which case everything works as intended) - which I thought would more or less produce the same results. Any ideas what I might be overlooking here?
After some testing, I finally found the source of the issue:
I had both the RecyclerView and its Adapter initialised through onStart() of the Fragment and not onViewCreated(). After changing that, I got the proper results I wanted.
Lesson learned: Set your RecyclerView's Adapter as early as possible, unless you want to deal with sometimes strange issues.

Edit button in listview item depending on other listview items

I would like to start by saying if you can think of a better title for this problem, feel free to change it since I have no clue how to explain this in a short way.
So here is my problem:
For the application I am trying to make I have these schedules, one schedule for today, and one for upcoming days. Both of these are a listview inside a fragment.
(I used those fragments to create tabs to seperate the two.)
Each game (let's call them games because calling them activities would be confusing) on the schedule has a status, and here is where the annoying part comes. I have been asked to check if any game has been started, and if so I need to disable the buttons to start any other game than the one that is already ongoing.
EDIT: The main problem is that I cannot use findViewById on the listview item because apparently it is a null object reference
I made a little "paint"ing to give you more of a graphical representation.
So long story short, I need a way to check the status inside of every listview item inside of the listview inside of the fragment inside the activity to use said status to disable every button except for the one of the ongoing game.
Little side note: If no games have been started yet, all buttons are enabled.
I hope this made sense.
If you want some code to go with this, feel free to ask but be warned, I am making this inside a testing app so a lot of useless testing data and sloppy code.
EDIT:
This is where I am stuck in a more clear example:
The start buttons are enabled but should be disabled.
Scrolling further down the list, there is a started 'game' and right below it, a game with the same status as in the previous picture where the button is disabled as it should be.
This is because the "isStartable" boolean in my code goes to false after the game with status "start" has passed and the following items are disabled.
When I scroll back up, it is how it should be, the items are all disabled but I need them to be like this when the listview gets filled. Any way to refresh the data in this listview and taking the "isStartable" boolean with it?
This is what it looks like after I scroll back up.
create a model class for your listview data items. Set a boolean variable in model class like isGameStarted. Set that variable as per your result.Then in your listview adapter, put a condition as below
if(isGameStarted){
holder.startButton.setEnable(true);
else
holder.startButton.setEnable(false);

Settext issue in ViewPager particular version - 5.1.1 android?

I am building android application where I am using Custom ViewPager. The Problem is explain below in the following steps:
When I open new activity of ViewPager and click on any button and setText any particular value to it. It's working fine.
Problem occurs when I swipe left-right and then click on button to setText on particular TextView; the value gets set as I can toast the value of TextView using getText. But the value does not change in the UI. For exmaple - I swipe any page and now the TextView contains my current position as 2. If I click button and try to do setText(position++) and toast the value, the incremented value is shown in the toast
But still TextView showing 2.
This issue is coming particular in 5.1.1.
I've also been fighting this one for several hours. Best I can determine ViewPager is really designed for a single view where nothing changes after the first time it appears (which hides the bug where SetView stops working). Think of it as showing fixed pages in a book.
If you have an adapter (in my case a CursorAdapter) in the Fragment, you can get it to update using a notifyDataSetChanged() on the adapter after an update is made. This still doesn't fix the setText being ignored after the first time the page is rendered.
Another solution may be to use Action Tabs with Activities instead of Fragments, but this has been depreciated. Still looking for a better solution.

OnClickListeners not consistently firing

I have a listview where each list item can contain 1 or more clickable images. Clicking them starts an activity that shows a full screen version of the image.
The following code (slightly simplified) sets up the OnClickListeners within my GetView() implementation, for each image in each ListItem. This worked perfectly.
ImageView imageView = (ImageView)convertView.findViewById(R.id.image_res);
imageView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
ActivityLauncher.startPhotoViewerActivity(mContext, item);
}
});
However, to improve performance, I decided to store each view in memory after constructing it the first time. I do this instead of using convertView because there are 4-5 different types of Views and they are sometimes dynamically constructed in code hence making re-use difficult.
As soon as I start storing the views in memory and then returning the already constructed views during subsequent calls to getView() based on the position, the performance significantly improves but the OnClickListeners start behaving funky.
Specifically, now when a given image is tapped, the OnClickListener for it may fire immediately or not at all. In the cases where it does not fire immediately, it may fire as soon as one starts scrolling. If this doesn't trigger the OnClickListener to run, clicking back (to quit the activity) may trigger it. If this doesn't trigger it, then closing all activities by pressing BACK) and then re-entering the app will trigger all the queued OnClickListeners. In one case I clicked 25 times on various images with no result. Then I closed all the activities and then clicked the application icon once again which opened all 25 image previews.
Any idea as to what is causing this? What is interesting to me is that the OnClickListeners are obviously set correctly because they do open the photo viewer activity at some point in time. The wrong image is never opened and there is never a case where they NEVER fire. The problem is that they may fire immediately or much later.
Is it not recommended to save the Views for each list item and return them based on position from within getView() like I am doing? Any help is greatly appreciated.
Watch the talk on ListViews given at Google I/O. At 13:45, they specifically warn against caching views and returning them. If one does this, it can lead to strange behavior, which is exactly what I am experiencing. Given this, the question is moot.
http://www.youtube.com/watch?v=wDBM6wVEO70
Hope this helps someone in the future avoid the same pitfalls. Caching views is NOT RECOMMENDED!!!

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