I want to be able to access my ArrayAdapter's view:
public View getView(int position, View convertView, ViewGroup parent)
I'm not sure how I can access this:
View myView = myArrayAdapter.getView(myPosition, myView, ?);
I am not sure how I can get a ViewGroup parent?
Well as far as I understand you don't suppose to Adapter in general serves as a source to instance of AdapterView so getView contract is follows :
in params : inPosition,convertView,viewParent
result : View witch will be shown at position inPosition , you can use convertView to bind data to if it's not null, returned view will be attached to viewParent.
So if you want to acquire view that will be shown by adapter view at specific position, why don't just call
AdapterView<?> adapterView = getAdapterView();
View myView = adapterView.getChildAt(position);
If you want to change way of showing view at specific position you should use
Adapter myAdapter = getAdapter();
//change data inside adapter
myAdapter.notifyDataSetChanged();
Update:
Try adding a field to the data in the data set that holds the background resource/color to be used when returning the view, and in the getView do
holder.background = dataSet.get(position).getBackground()
If you don't know what I'm talking about with this holder thing, check How to load the Listview "smoothly" in android
Old:
I'd say the ListView containing the adapter is the parent ViewGroup.
Anyway, why don't you use the ListView containing the ArrayAdapter? The ListView is the container of the Views, rather than the adapter, that only holds the data collection and creates and returns Views on demand when the ListView asks for them (f.e, when scrolling). Even if you were able to fetch a view for the position X, I'd say that won't work, as the convertView you pass as a parameter is not the one the ListView is holding and showing.
Take into account that in a ListView there are at most 7-8 Views inflated at any given moment (I don't know the exact number), and what the ListView does is fill them in by calling the adapter's getview.
This said, to update a single row (a single view) you'll need to update the adapter's data collection. Then, speculating, try to get that View from the ListView and invalidate it, but I doubt this'll work.
I think these concepts are right, if they are wrong I'd be grateful if anyone corrects me.
Why do you want to update only one view at a time?
Related
I have a scrollview in an activity that I want to populate. Each item I want to add to the list is made up of several views (text view, image view, etc). Instead of programmatically creating each view, and adding it to a linear layout, and then adding that to the containing layout, is it possible to instead create a predefined layout resource with these items and instead add it to the view and programmatically change the item contents?
Essentially, is it possible to do something like:
container.addView(R.layout.listItem);
And if so, how could I access views within the list item to change them?
It's just what inflate(int, ViewGroup, boolean) does with the third parameter attachToRoot set to true
getLayoutInflater().inflate(R.layout.listItem, container, true);
After that everything is straightforward
container.findViewById(R.id.text_view)
You have to "inflate" your view by LayoutInflater. For example like this:
View view = LayoutInflater.from(context).inflate(R.layout.listItem, container, true);
or
View view = LayoutInflater.from(context).inflate(R.layout.listItem, container, false);
container.addView(view);
Hello i have a fully working code for my list adapter:
public View getView(int position, View convertView, ViewGroup parent) {
View vi=convertView;
if(convertView==null)
vi = inflater.inflate(R.layout.overview_item, null);
//getting id's
TextView name =(TextView)vi.findViewById(R.id.userUsername);
TextView date =(TextView)vi.findViewById(R.id.imageDate);
ImageView image=(ImageView)vi.findViewById(R.id.userImage);
ImageView avatar=(ImageView)vi.findViewById(R.id.userAvatar);
//setting text
name.setText(dataNames.get(position));
date.setText(dataDates.get(position));
//set image
Log.d("test: ", "Adapter wants to get picture");
imageLoader.DisplayImage(dataImage.get(position), image);
imageLoader.DisplayImage(dataAvatars.get(position), avatar);
return vi;
}
This code works perfect but the problem is this function runs everytime when you scroll throught the listview so whenever the lis item is getting in sight. And that's not what i want. i want it to do this function just once for every list item. This is because when your scrolling fast trought the list it has to load all images again so the loading image is showing and it keeps jumping because the loading image is another size then the image wich is getting loaded. I hope thay tou understand my question and can help me. Already thanks and if i'm not clear please ask my anything in the comments.
So short:
How do i run this code just once for every list-item and not everytime when it's getting in sight?
Your code might call findViewById() frequently during the scrolling of ListView, which can slow down performance. Even when the Adapter returns an inflated view for recycling, you still need to look up the elements and update them. A way around repeated use of findViewById() is to use the "view holder" design pattern.
Check this links:
1 - http://www.javacodegeeks.com/2013/09/android-viewholder-pattern-example.html
No, you should not. This is the way ListView works. Beside, you should use ViewHolder pattern for better performance.
If you still want to do this, you could remove check NULL with convertView. It will solve your problem, but lead to performance, I think.
I have to show some HTML with images from the internet in a ListView. The images are handled in a custom Html.ImageGetter. The problem is, I need the TextView available to download the images to inside. This leads to having to incorporate the HTML parsing inside the ArrayAdapter's getView method. But that method gets called very often by the Android system as it recycles and redraws elements.
How can I stop this recycling from happening? I assume I have to use a different flow. This is my current getView() method:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView view = new TextView(context);
CharSequence element = getItem(position);
CharSequence html = Html.fromHtml(element.toString(), new MessageImageGetter(context, view), null);
view.setText(html);
view.setPadding(12, 4, 12, 4);
return view;
}
Maybe a list-like behavior is possible without the use of ListView and ArrayAdapter, that doesn't recycle and redraw often.
How can I stop this recycling from happening?
You don't. You create a richer model object. Rather than having what appears to be a ListAdapter<String>, have a ListAdapter<Thing>, where:
Thing holds your existing string value (element)
Thing caches the Html.fromHtml() result
Your getView() gets the html CharSequence from the Thing and therefore can take advantage of caching
Feel free to substitute a more applicable noun than Thing, of course... :-)
I'am trying to use a custom listView in my application and i have some questions about its working principles.When i implemented a custom adapter,how its methods(especially the getView method)work without calling them from any other class ?
When you set the adapter to a view (e.g. ListView or GridView), that view at some point wants to have some items to show. So it calls getView in the adapter:
getView(int position, View convertView, ViewGroup parent).
The position is the position of the item in the list/grid/etc. The convertView is a recycled view that can be already inflated by a previous getView() call, or null when it's not inflated yet (see this answer about convertView and view recycling.
The parent is used to inflated the view, so the correct layout parameters can be computed in relation to the parent view.
Note that inflation is slow. That is why the convertView mechanism exists, to recycle views so the number of inflations is minimized. Next to that, finding views (findViewById()) is also relatively slow. To improve on that, check out the ViewHolder pattern, which keeps references to views in memory so they don't have to be searched for each time.
I think this link can help you. getview is a callback function which will be called automatically when you will display your listview on Activity. When you display your listview then you overrides getview and inflates your row from XML or dynamically creates your row. That row you return as a view which displays in your listview.
How does the getView() method work when creating your own custom adapter?
For each row getview will be called once. You create your layouts and return them as view. Those respective views displays in your lisview rows.
You are calling the custom adapter class from you activity class.Your customised adapter class extends a BaseAdapter which is an abstract class.The methods of an abstract will be used by the extended class(the methods like getView(), getItemId(), getItem(), and getCount()).These methods should not need a seperate call from your Class since you are calling the customised adapter classs .
I'm trying to implement a custom ArrayAdapter for a ListView.
The ArrayList I want to adapt have some positions I want to ignore. (for example when myobject.getValue()>20) how can I indicate that object shouldn't appear in the ListView?
Returning null in the method getView result in a nullPointerException
public View getView(int position, View convertView, ViewGroup parent)
Thanks in advance
Filter out your list before you create the adapter. Go through the original list, checking values, and only add the ones you need to a second list. Then use the second list for your adapter.