I developd a viewpager with custom list views in android. I followed the tutorial View Pager Part 1-3. The major difference in my development is that i used a customlistview in the views of the paager. The list items in the listview also support click events to display more info about an item.
Here is the problem; I handled the onItemClick inside the instantiateItem method but i noticed that when an item is clicked, the content displayed is that of the adjacent listview (i.e if item 2 of page 2 is clicked the info displayed is item 2 of page 3).
I realised this happens because the pager loads adjacent lists so as to make rendering faster for the user so my code uses the preloaded list instead of the list in current display.
I thought to find out the appropriate way to handle listview click events in viewpager, code snippets, links,.. will really be of help. The appropriate method to use to handle the click events.
Thank you
You have to get it from the adapter of the listview (the first parameter of the onItemClick method):
#Override
public void onItemClick(AdapterView<?> a, View v, int position, long id) {
// NOT THIS!: mValue = (HereYourClass) listView.getItemAtPosition(position);
mValue = (HereYourClass)a.getAdapter().getItem(position);
}
Related
I am wondering why ListView or GridView used old items during scroll? I have a list view more than 500 products i am showing in list view . Each list item has 4 columns the last column is a ImageView showing status as active or inactive. Whenever i marked ImageView as active then after scrolling periodically every item automatically changed its ImageView as active.
Let suppose if i clicked on 6th Items and make its ImageView as active then during scroll i see that 12th , 18th , 24th and so on also changed as active
In order to optimize the scrolling experience, ListView and GridView will re-use item views to avoid having to inflate/instantiate a view for every list item.
That's why getView has a parameter of type View called convertView. When convertView is null, you need to inflate a new view for the item. When it is not null, that means you can re-use this view to avoid the overhead of inflation.
The downside is that this "recycled" item view will have garbage in it from the last time it was displayed, and you have to reset everything in the view to match the list item.
So a common mistake that new Android developers make is to not have a model representation of everything in the view. For example, if your list item can show a status of active or inactive, then the model for your list item should probably have a boolean property called mActive.
The model for the list has to have the entire current state of the list at any given time, so that it can be recreated whenever the ListView decides it needs to redisplay its list items.
So what you need to do is basically four things:
Add the property to your list item model:
boolean mActive; // this can be private with getter/setter
Create an adapter method for changing the state. For example:
public void toggleItemActive(int position) {
mListItem.get(position).mActive = ! mListItem.get(position).mActive;
notifyDataSetChanged();
}
Calling notifyDataSetChanged() here is very important.
Use this property in your getView override:
imageView.setImageResource(item.mActive ? R.drawable.active : R.drawable.inactive); // or however you are doing it
Set the property from your event handler:
listView.setOnItemClickListener(new OnItemClickListener) {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
MyAdapter adapter = (MyAdapter) parent.getAdapter();
adapter.toggleItemActive(position);
}
});
Now your ListView will correctly display your list items.
I think you are using viewholder inside getView() method of your custom adapter. When you are using view holder you will be reusing the views. From your description it looks like, your device can diaply 6 list items at a time. So 6th, 12th (6th position + 6-size of screen), 18th (12th position + 6-size of screen), 24th etc will all be using the same view. Therefore, when 6th item is changed the related 12th, 18th, 24th etc items will also be changed.
i will attempt to keep this short and concise. I am currently developing an android application, and am stuck on a particular element.
The below is an example code i have been reading through, from my understanding it is taking a list of values inserting them in to the db / table, then cycling through them with the cursor and displaying with the list view.
On running the application all items are displayed in a list as expected.
I would like it so that when an item in the list is clicked a new page is opened via intent, or a different set of database values is displayed on the current page.
How could this be achieved
Thank you!
Implement this method
protected void onListItemClick(ListView l, View v, int position, long id)
This method will be called when an item in the list is selected. Subclasses should override. Subclasses can call getListView().getItemAtPosition(position) if they need to access the data associated with the selected item.
Parameters:
l ListView: The ListView where the click happened
v View: The view that was clicked within the ListView
position int: The position of the view in the list
id long: The row id of the item that was clicked
ListActivity - Documentation
Currently I am trying to implement a ListFragment or ListView navigation system where a user clicks on an item in the listview which then transitions and replaces it with another listview.
So Container Activity A has a screen. You press a button and it replaces that container with a ListView. You then choose one of the items and it then replaces the screen with a new fragment Listview. This repeats until a user gets to the end of the line to the product itself.
The Amazon APP currently has this implemented for their Item Navigation.
I am just looking for ideas on how to start a design pattern to create an app like amazon.
Does anyone know how they execute this? I am having problems finding the correct key word search to find examples of this functionality. If anyone can help me lead to examples to mimic this design it would be helpful!
I am not sure what exactly you want to do but if you want to replace a listview with another listview on click of an item in listview, then you dont have to make it so complicated.
Have a listview in which you feed data from an array using an adapter. On list item click. Change the data array with new array in the adapter and notify the listview.
Something like this:
mListView = (ListView)findViewById(R.id.mylist);
mAdapter = new Adapter(this, mArray1);
mListView.setAdapter(mAdapter);
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
-----
mAdapter.setListData(mArray2);
mAdapter.notifyDataSetChanged();
This way it will work for you.
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.