Access Child View from List Adapter - android

I am trying to highlight an item in a ListView (touchable interface). The aim is that the user will touch an image and it will select the item in the ListView moving it to be visible (it does not all show on the screen at the same time) and then highlight the item in the ListView related to the position on the image by changing the background color of the item view. I have a custom ListAdapter with a view for each item.
From the image I can get the postion of the item in the ListView. From this I can call listView.setSelection(selectedPos). This positions the item at the top of the list. However I now want to get the view for this item; I have tried getFirstVisiblePosition() however it seems that this is not available until the list has been layed out (I am responding to a click on the image) so I cannot use this.
Nothing else I try works - all I want to do is to do something like listView.getViewAt(index) but I simply cannot find a way of doing it. I cannot use 'selected' as I am in touchable mode.
For what seems a very simple thing - I've wasted a day; any help would be greatly appreciated!
Cheers,
Neil

Shouldn't listView.getChildAt(position) do what you want?

Try creating your own custom adapter for the list view. For example:
private class CustomAdapter extends ArrayAdapter<RowData> {
public CustomAdapter(Context context, int resource, List<RowData> objects) {
super(context, resource, objects);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
//convertView holds the view for each item.
TextView txt = (TextView)convertView.findViewById(R.id.button);
//do some other stuff with the views
return convertView;
}
}

I got round this by doing the following:
I marked the item I wished to select in the adapter first by adding in my own method
Then when the view is requested I can check to see if the view is for a position at which I requested
I get then modify the presented view that is returned by GetView
This seems the simplest option.

Related

Android listview getting all items

In android, is it possible to get all items inside the list view. Lets say the list view has multiple rows and only 2 rows are visible on the screen while the rest are accessible using the scroll bar. Each row has a radio button and a text view. Is there a way to get all textview of the rows whose radio button is selected and not just the ones visible on the screen.
Your answer may be:
for(int item = 0; item < m_listitem.count(); item ++){
if(m_listitem[item].isSelected){
View view = ListView.getChildAt(i);
TextView textview = view.findViewById(your textView id);
// do some thing
}
}
You can use custom list view to show your list items with checkbox & textview.
I happened to have a similar requirement where I had multiple EditText inside a ListView and only few of them were visible on the screen. I needed to get the values of all EditText and not just the ones visible on the screen.
Well if you are using a default Adapter, then the way it will work is it will recycle the old views to create new ones. So there is no way to preserve values of those Views which are not visible.
So the only workaround is to create your own Adapter, maybe something like the following, which will not recycle any views, but every time inflate new ones.
public class ListViewAdapter extends ArrayAdapter {
public ListViewAdapter(Context context, ArrayList<Object> items) {
super(context, 0, items);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
return LayoutInflater.from(getContext()).inflate(R.layout.your_layout_for_list_view_item, parent, false);
}
}
After that, as in above answer Lãng Tử Bị Điên has mentioned, you can check in your java code, if your radio buttons are checked or not, and according to that, selected desired TextViews
for(int item = 0; item < m_listitem.count(); item ++){
if(m_listitem[item].isSelected){
View view = ListView.getChildAt(i);
TextView textview = view.findViewById(your textView id);
// do some thing
}
}
Hopefully this should do it.. It sure worked in my case!

Get access to particular item's layout in list view

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;
}

How to set background color for all elements of ListView on OnItemClick event?

I have a ListView and posibility to select one element (single choice).
How can I set background color for all elements of ListView (maybe which are visible at least) when some item was selected?
adapter = new ArrayAdapter<Orderline>(activity, simple_list_item_single_choice, orderlines) {
#Override
public View getView(final int position, View convertView, final ViewGroup parent) {
...
convertView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
convertView.setBackgroundColor(BLACK);
// so here currently selected element is set to BLACK, but also other elements have to be set to WHITE
}
});
return convertView;
}
}
I don't have much code for you because I'm not at my workstation right now, but I'm thinking you can just set the background of the selected item to black by via your onItemClick as you've already suggested. Cool.
To change the color of the other(unselected) views when a particular view is selected, I'm guessing you can call your Adapter's getCount() and loop through that list, make a call to getChildAt(i) of your ListView. This returns a View which you can call setBackgroundColor(Color) on. Hope this helps
You can do
parent.setBackgroundColor(BLACK);
this.notifyDataSetChanged();
to set your list view background.
I would use a Drawable selector.
Check this link for a pretty good example:
http://www.charlesharley.com/2012/programming/custom-drawable-states-in-android/
Basically you create the XML drawable which contains a mapping (which the system uses automatically) to what you would like displayed when certain click events occur.
You can assign the background drawable to any view, so you could do it in your XML for your adapter, or in Java code. Which in your case might be something like this:
convertView.setBackgroundDrawable(R.drawable.MySelector);
parent.setBackgroundColor(while_color);
v.setBackgroundColor(black_color)

Dynamically increase the size of the cell in a list view in Android based on Content size?

I am doing a project where i am a using a custom list view, which contains a textview. Data is coming from the server. I want to change the height of the cell, based on the data size. If the content is more than two lines, i have to trim it to two lines and show a see more button. On clicking the see more button expand the cell to show full details.I googled about it. But i cannot find any useful resource.Could any one help me to solve this, any useful links or suggestions?`
One way to do this is to first invalidate the listView forcing it to redraw the visible elements and then handle the layout change in the getView method of your adapter.
Try this:
Add a showTrimmed(int position, boolean value) method to your adapter. This will update a structure inside your adapter that keeps track of the list items that you want to trim or not trim. Then in the getView method, when creating the item view, you test if the current element should be trimmed or not and based on the result you create the proper view.
I did something similar to achieve a different but similar result and it works.
Remember to call invalidate after calling showTrimmed to force the listView to redraw the displayed items.
Edit: I post my code which is different from what you want to do but it's quite similar in the idea:
public class HeroListViewAdapter extends ArrayAdapter<Hero> {
public static int NO_POS = -1;
private List<Hero> heroes;
private int selected_pos = NO_POS;
public HeroListViewAdapter(Context context, List<Hero> heroes){
super(context, R.layout.hero_list_item_view, heroes);
this.heroes = heroes;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View rowView = GuiBuilder.createHeroListItemView(heroes.get(position),getContext(),parent,false);
if(position == selected_pos){
rowView.setBackgroundColor((rowView.getResources().getColor(R.color.list_item_selected_color)));
}
return rowView;
}
public void setSelectedPosition(int selected_pos){
this.selected_pos = selected_pos;
}
public int getSelectedPosition(){
return selected_pos;
}
public Hero getSelectedHero(){
if(selected_pos>=0 && selected_pos<heroes.size())
return this.getItem(selected_pos);
else
return null;
}
}
instead of setSelectedPosition you should have the showTrimmed method which updates an inner member as setSelectedPos does, in order to keep track of the trimmed state of every list item. Then in the getView method you do the test (like I do in if(position == selected_pos)) and then you build your custom trimmed or not trimmed list item based on the result of the test. My listener which uses these functions is:
listView.setOnItemClickListener(new AdapterView.OnItemClickListener(){
public void onItemClick(AdapterView<?> parent, View view, int position, long id){
list_adapter.setSelectedPosition(position);
listView.invalidate();
}
}
);
you can try to update this idea to your needs. In particular in my case I do this to highlight the clicked listview item by programmatically changing its background.

Android Listview: getView being called multiple times on unobservable views

(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
}

Categories

Resources