I have a ListView with a custom adapter, displaying information from a database.
When I start the app, the data is read from the database, given to the adapter, which is then attached to the ListView. A LayoutAnimationController is run on the ListView, displaying the contents smoothly.
this._lvList = (ListView)_v.findViewById(R.id.lvList);
this._lvList.setAdapter(new TableAdapter(getActivity(),R.layout.tablerow,Category.getCategories()));
LayoutAnimationController lac = new LayoutAnimationController(AnimationUtils.loadAnimation(getActivity(), R.anim.slide_in_left));
lac.setDelay(0.2f);
this._lvList.setLayoutAnimation(lac);
this._lvList.startLayoutAnimation();
No problem at all.
Now when I click on any entry of the ListView, the entries which were not clicked disappear, the clicked entry becomes the one and only entry in the list and is displayed at the top, as expected.
View v;
for(int i = 0;i<_lvList.getChildCount();i++) {
v = this._lvList.getChildAt(i);
if(v!=clickedView) {
Animation animSlideOut = AnimationUtils.loadAnimation(getActivity(), i%2==0?R.anim.slide_out_left:R.anim.slide_out_right);
animSlideOut.setStartOffset(i*50);
// some more stuff
}
v.startAnimation(animSlideOut);
}
This works as well, but now the problem, if I click again on that single list entry, I want the list to repopulate, displaying all items again.
I thought I could use the code from the start (the first snippet), as it works fine when starting the app, but...this time...it doesn't. No animation happening. The reason is, there are no views to animate in my ListView (except the one from the previous step).
Instead of creating a new Tableadapter I already tried to clear it, fill it new, called notifyDataSetChanged()... no use, as
_lvList.getChildCount();
stills returns 1 view, while the adapter holds all 18 entries.
I as well tried
requestLayout();
forceLayout();
invalidate();
invalidateViews();
to force the ListView to generate its child views before the animation, but it's not working. So atm the ListView just appears instantly, somewhen after my call to the layout animation.
Summary : my ListView contains no child views before the start of the layout animation, how can I force it to generate them?
Thx in advance :)
Hmm... have you done this yet? (below)
in your custom adapter, override the method:
#Override
public View getView(int position, View convertView, ViewGroup parent){
//the position of the item, the convertView is the view layout of what that row is
}
to change how the listview is updated. this getView method gets called by Android every once a while to refresh the view (you don't call it manually)
also, i think you only need to call
listView.notifiyDataSetChanged() and listView.invalidate() to force the update, after you repopulate the list
you can read more on listviews here:
http://www.vogella.com/articles/AndroidListView/article.html
http://developer.android.com/guide/topics/ui/layout/listview.html
Related
I have a question about some behavior in an AdapterView.OnItemClickListener that has me a bit flummoxed.
I have a ListView backed by a custom CursorAdapter. The Cursor is being managed by a LoaderManager. The ListView also has an OnItemClickListener. The data loads properly and the ListView is correctly populated - in this case with many items.
What I'm finding is that the position argument to onItemClick is 0-based relative to the items showing on the screen, not the entire list. So for example if I scroll down and select the first viewable item, I'll actually get the first item in the list (which is not visible) instead of the one I selected. When I use a debugger, I see that position actually has a value of 0 even though the item selected was much further down in the list.
What's odd is that this worked fine until I started using the LoaderManager.
I'm using the v4 support library.
If I do something like this:
public void onItemClick( AdapterView<?> parent, View listItem, int position, long id ) {
Cursor c = myListAdapter.getItem( parent.getFirstVisiblePosition() + position );
// do stuff
Then I get the data I actually selected, but I somehow feel this is wrong. I shouldn't have to use getFirstVisiblePosition().
Any ideas?
Thanks
I guess you might be using the convertView parameter of the getView() method to recycle the views. Using this might be causing the issues here. Kindly try using an alternative and check whether the issue still exists or not
I want to highlight the selected item in list view. There is one scenario in which if user selects any item from list view, list view freezes and if user again comes to that screen that item will show as selected. (Note that this is not the case every time). So Is there some way by which I can show some item selected say via some background color. But this need to be done in activity class file NOT IN ADAPTER.
I tried
MYListAdapter adapter = (GenericListAdapter) lvList.getAdapter();
View view = adapter.getView(position, null, null);
view.setBackgroundColor(color.holo_orange_dark);
But its not working as expected. Can any body suggest me any thing.
adapter.getView(position, null, null) creates a new view, and not return view which is used in listView. You can try to get listView and get its child by position. Smth like that:
lvList.getChildAt(position).setBackgroundColor(color.holo_orange_dark);
But I think it's not the right way, because ListView can recreate view at any time.
So the right way is adapter..
you can see apiDemo->Views->Lists->Activate items.It's very simple,just setChoiceMode and provide a backgroud selector.
By the way,you should see android4.x apiDemo.
I've working on app that need custom list view...
List view should act like some kind of vertical gallery.
In gallery selected item is always on center.
In my app I use navigation keys only or remote controller.
So there is no fling or regular scrolling effect.
I need for example second element in my list to be selected always.
If I want to move up, all elements are scrolled one place up, and selected item has to be changed, but on same place on the screen like previous selected item.
It's the same thing like gallery only vertical.
Is there a simple way to do this?
Is there a vertical gallery implementation?
How can I make gallery widget vertical?
Or how to customize list view to act like that?
Tnx!
try setting onClick Listener on ListView
ListView listView1=(ListView) findViewById(R.id.listView1);
then implemt a class class SearchItemClickListener implements OnItemClickListener
and set listview.onItemClickListenr you will get position and view.
Hope this helps
You can get the current visible first postion by using,
mListView.getFirstVisiblePosition();
after getting the current visible position and its respective data, you can perform your desired task (i.e. display the large image after getting the thumbnail or something like this).
OR
If you don't want to depend on only first or last position and want to select some other visible row then you can do something like this,
public View getView(int position, View convertView, ViewGroup parent)
{
int visiblePosition = position % nObjects; // nObjects if the total number of objects to display
if(visiblePosition == yourDesiredPosition){
// do your custom work here.
}
}
Here is a demo for vertical slide show,
Hope this will give you some hint about implementing your functionality.
I've managed this using setSelected() method on ListView item...and managing key listener.
Didn't found smarter way to handle this.
I want to have one ListView that when I click on the item the view slide out to the left.
So I have:
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1,
int arg2, long arg3) {
arg1.startAnimation(openAnimation);
}
});
However, animation applied to the different item in the list instead of the one being clicked on. The behavior seems to be random as sometime it happened to more than one item at the same time.
As I suspected this is because of the way Adapter reuse it's view to create item. I went to modify the getView method in my Adapter to inflate new view every time it's being called. Then the animation doesn't happen any more.
Is there a way to resolve this? I tried to move the animation to inside my Adapter but then I can not associate it with other action on the Listview.
Ultimately, I want the item to be clickable but when swipe left/right reveal delete button (iOS delete behavior). Am I on the wrong track here? This should be possible though as Android can implement swipe to remove in the Notification bar.
I recommend that you check this thread also.
I don't think, that this is possible without having to modify your adapter to suit this type of behavior. For what I understand, you don't have any problems with implementing the code recognizing the swipe gestures on different ListView-rows, only with the animation the should follow this gesture on according row(s).
I'd rewrite the adapter to suit at least 2 row types: normal rows, and rows to be deleted. In the "getView()" method of your adapter, you should only reuse the convertView of normal Views. Rows that are to be deleted should not reuse them, so that animating one would not modify the others.
Upon clicking a normal row, you should first tell the adapter that the row on the clicked position is now of type to-be-deleted, call .notifyDatasetChanged(), and then start the animation on that row.
I'm currently making a SMS Application in Android, the following is a code snippet from Inbox Listactivity, I have requested a cursor from the contentresolver and used a custom adapter to add custom views into the list.
Now, in the custom view i've got 2 TextViews (tvFullBody,tvBody)...
tvFullBody contains the Full SMS Text while tvBody contains a short preview (35 characters)
The tvFullBody Visibility is by default set to GONE.
My idea is, when the user clicks on a list item, the tvBody should dissappear(GONE) and the tvFullBody should become visible (VISIBLE). On Clicking again, it should revert back to its original state.
//isExpanded is a BitSet of the size = no of list items...keeps track of which items are expanded and which are not
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
if(isExpanded.get(position))
{
v.findViewById(R.id.tvFullBody).setVisibility(View.GONE);
v.findViewById(R.id.tvBody).setVisibility(View.VISIBLE);
}else
{
v.findViewById(R.id.tvFullBody).setVisibility(View.VISIBLE);
v.findViewById(R.id.tvBody).setVisibility(View.GONE);
}
isExpanded.flip(position);
super.onListItemClick(l, v, position, id);
}
The Code works as it is supposed to :) except for an undesired sideeffect....
Every 10th (or so) List Item also gets "toggled".
eg. If i Expand the 1st, then the 11th, 21th list items are also expanded...Although they remain off screen, but on scrolling you get to see the undesired "expansion".
By my novice analysis, i'm guessing Listview keeps track of 10 list items that are currently visible, upon scrolling, it "reuses" those same variables, which is causing this problem...(i didn't check the android source code yet.)
I'd be gratefull for any suggestion, on how i should tackle this! :)
I'm open to alternative methods aswell....Thanks in advance! :)
Your diagnosis of the problem almost correct. What's happening is that Android is reusing the Views it creates to display the list to save memory. Instead of creating a new View for every item in your list, Android creates just enough to fill the screen, updating them to show the relevant data for the items which are currently visible.
So when you show tvFullBody when the user clicks on an item, when that View is re-used later tvFullBody is still visible.
You may have to write you own ListAdapter to make sure the Views are displayed how you want. It should be as simple as extending the ListAdapter you are currently using and overriding the getView() method to ensure that tvFullBody is hidden.