I have a ListView with custom adaptor that I molded off the example shown here.
I want to take the user's selection and inflate a different layout for that selection. So that I can expand the view to display more information when an item is selected. Can I simply inflate a new layout onclick using something like this?
protected void onListItemClick(ListView list, View v, int position, long id){
super.onListItemClick(list, v, position, id);
LayoutInflater inflate = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.new_layout, null);
After this section of code I would populate the individual TextView and ImageView objects, just as I did in the initial list only this time I would include more fields. Is this right or is there a better approach?
this won't work since you haven't done anything to the view that you got . you only replaced its reference (and didn't do anything with the newly inflated view) and not really modified anything in the "views tree" .
what you can do is to empty the view from its content and add new content into it .
don't forget that in the getView you will have to do the same thing and return a view with this content.
Related
I'm trying to implement a custom listview. Everything works fine until I use a if () statement inside the getView() method
Without the if() condition a single item gets selected when I select an item but when I add the if() condition, the views are displayed properly but two items (non-adjacent) get selected (1st and last 1st or and second-last, any such combination).
View getView(...){
....
if (!item.getPriceTo().equals(""))
priceToTV.setText(item.getPriceTo());
else
priceToTV.setText(item.getPriceFrom());
return view;
}
Also I'm using saving the previous view to show the selection so the current selection has a red_border and when it is selected a black_border is set to it.:
subItemsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Log.d("New Order", "........");
if (previousViewOfSubItems != null && previousViewOfSubItems != view) {
previousViewOfSubItems.setBackgroundResource(R.drawable.black_border);
if (quantity.getText().toString().equals("xx") || quantity.getText().toString().equals("0")) {
viewForVisibility.setVisibility(View.GONE);
layoutForQuantity.setVisibility(View.GONE);
}
}
if (previousViewOfSubItems == view)
return;
previousViewOfSubItems = view;
previousViewOfSubItems.setBackgroundResource(R.drawable.red_border);
viewForVisibility = previousViewOfSubItems.findViewById(R.id.viewForVisibility);
viewForVisibility.setVisibility(View.VISIBLE);
layoutForQuantity = (LinearLayout) previousViewOfSubItems.findViewById(R.id.layoutForQuantity);
layoutForQuantity.setVisibility(View.VISIBLE);
quantity = (TextView) previousViewOfSubItems.findViewById(R.id.subTypeQuantity);
}
});
previousViewOfSubItems = view; seems to be causing the problem,
In Listviews with adapter you should avoid saving view instances, because views are reused by adapters so view can be same for two rows so rather than saving view instance's reference use ViewHolder Design pattern and use view tagging
You need to use ViewHolder Pattern and view tagging to properly identify every view in different position. ListView always recycle the view instead of re-inflating the view again and again.
You can refer to Android Training documentation on how to implement ViewHolder pattern.
ListViews recycle the views in the list. so as you scroll, top views are reused and content replaced using the methods.
Where you set background to Red etc, use Else statements to set it back to your default black.
its beacause it listview reuses view to display items, once the first view is scrolled out the the same view is reused to display the view at bottom of the listview. instead of comparing the view try compairing the position of the view clicked
I have explained about this abnormal behavior in my blog on recyclerview you refer that to solve this problem.
use pojo class to get the status and update the view accordingly
In my android app my Main Activity extends List Activity. I store there elements called Items, their layout is defined by itemLayout xml file and I use custom adapter (called ItemAdapter) to transfer data to List View in Main Activity. In itemLayout there's an ImageView and my aim is to change its image when user clicks on the particular item in list view. In my opinion the easiest way to achieve that is to get access to particular item's (the one that was clicked) layout, there find the ImageView and call method setImageBitmap. How can I "find" this layout of clicked item? I tried many things in method:
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
}
but nothing worked. Do I have to add anything to my ItemAdapter? Or is it possible to do in onListItemClick(…) but I can't find out how?
You're thinking about it in slightly the wrong way. Adapter's are a way to map data to views. So if you want to change how a particular view looks for a given position, you need to change it's correlating data so that the rendered View then changes. Attempting to modify a view directly kinda goes against how adapters are meant to be used.
So in your case, when a user clicks on an item. Find that item in your adapter via the position number. Then update the item and ensure notifydataset is called. Meanwhile, your adapter's getView() will then handle displaying the appropriate image.
As I understood you need to modify clicked item layout, right? Use argument from onListItemClicked:
v.findViewById(<your_img_view_id>)
For better performance use view holder.
onListItemClick is fired when you press on an element of the ListView. If you want to retrieve the element in the dataset, you can simply invoke
l.getItemAtPosition(position)
the returned value has to be casted to the specific object
Yes It is possible in your custom adapter class in the getView() mtheod u can change imageview bitmap by clicking on it
see this code
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View rowView = convertView;
rowView = inflater.inflate(R.layout.playlist_item, null);
final ImageView im = (ImageView) rowView.findViewById(R.id.favorite);
im.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// Do your stuff here
}
});
return rowView;
}
I have a multiple choice list view and for its adapter I have designed a layout file. I have an image view in the layout and when it's clicked, I want to know what child of the list it is. I mean the child id for the its parent which is the list to further use the method list.getChildAt(???). can anyone tell me how to get that?
The image is independent of the list view and for its onClick attribute I've written a different method that changes image view resource... How can I know which child that a particular imageView is when I click on it?
In the XML layout I have this:
<ImageView
android:id="#+id/choice_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="deleteSelected" />
And here is a part of deleteSelected method:
public void deleteSelected(View view) {
icon = (ImageView)view.findViewById(R.id.choice_image);
list.getChildAt(???); \\ To know which child the view is
}
I have set the adapter as follows:
list.setAdapter(new ArrayAdapter<String>(this, R.layout.list_choice_multiple,
R.id.choice_text, terms) {
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = super.getView(position, convertView, parent);
icon = (ImageView)v.findViewById(R.id.choice_image);
icon.setImageResource(R.drawable.delete_off);
icon.setTag(R.drawable.delete_off);
return v;
}
});
How can I set the id for each image view so I can access it by getID() method within deleteSelected()?
ListView has a getFirstVisiblePosition method, using that you can calculate the child position based on its position in the list view (which is a parameter passed in to the onItemClicked method of the listener).
int childIndex = listView.getFirstVisiblePosition() - position;
If you're clicking on a child of the row view (View used in the ListView, created by the adapter), then you need to know which position the row belongs too - simplest way is to store the position in the tag of the child when you set the onClickListener
Simple answer: You are writing that the click happens on the ImageView. The ImageView is not associated with the ListView.
So there is no relationship between your click or any element in the ListView.
When clicking on the ImageView, though, the onClick receives a reference to the ListView itself. So what you are trying to achieve? Please be more precise.
Basically first you will have to set an onClickListener for your list-item's ImageView in getView() of the Adaptor.
Now with onClickListener you get the view that is clicked as function parameter to onClick(). Set a different background for this view (ImageView) object.
Hope this is clear. Let me know.
I have already fill adapter into Listview and it works fine.
My problem is how to change Text and Background color in specific row Item (using TextView) when selected.
#Override
public void onItemClick(AdapterView<?> a, View v, int position, long id) {
int visiblePosition = listView1.getFirstVisiblePosition();
View view = (View)listView1.getChildAt(position);
.....
});
But it doesn't work as well.
By the way, please show me how to prevent loading data when scrolling in Listview (using custom adapter) or how to fill adapter into all row when first run.
it doesn't work because the children of a listview are being re-used each time you scroll.
you should either update the data and call notifyDataSetChanged , or update the data and use something like:
int visiblePosition = mListView.getFirstVisiblePosition();
View view = mListView.getChildAt(position - visiblePosition);
if(view!=null)
{
// update the view to have a different background and other stuff...
}
notes about the second way:
on some adapterViews the second way might not work as expected.
i'm not sure what will happen when changing the size of the view .
(I have already seen this similar question)
I have a ListView for which I've written a custom adapter, and an onitemclicklistener. I'm having an issue where, when any element of the list is selected, getView is called (twice) for each of the top 4 elements of the ListView, even if those elements are not visible. This happens even if I don't call notifyDataSetChanged on the adapter - those first 4 views are fetched twice regardless. Is this normal behavior? My issue is not as much that it's being called twice for them, but that it is being called at all when updating them is not needed.
By the way, I am not using wrap_content for the height or width of the listview - the height is match_parent and the width is a fixed number of dp.
The onItemClick() method of the OnItemClickListener is here:
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
mPicture = pictures[position];
mPicturesAdapter.setCurrentPicture(mPicture);
mPicturesAdapter.notifyDataSetChanged();
}
getView() from my custom Adapter (which extends BaseAdapter) is here:
public View getView(int position, View convertView, ViewGroup parent) {
Log.v("tag", "Getting view for position "+position);
LayoutInflater inflater = LayoutInflater.from(mContext);
LinearLayout layout = (LinearLayout)
inflater.inflate(R.layout.picture_thumbnail, parent, false);
// set up the linearlayout here ...
return layout;
}
On any item click, getView() is called for positions 0 - 3 twice regardless of which item was clicked.
Just by modifying the adapter via
mPicturesAdapter.setCurrentPicture(mPicture);
the ListView already tries to update itself. I'm guessing the onClick method will still do it's job without you calling notifyDataSetChanged
Actually whatever List/Group you are using to populate the ListView, you need to first empty it and then recall it. For example, if you use ListA to populate the ListView, in the second or any consecutive update you need to empty the ListA first and then add items and then populate using it.
if (convertView != null){
Then populate list
}