Inside my getView method I want to get a specific child view. I know that my adapter holds several items, by doing calling getCount:
getCount();
According to the JavaDoc:
public abstract int getCount ()
Added in API level 1
How many items are in the data set represented by this Adapter.
Now in my getView method:
public View getView(final int position, View convertView, ViewGroup parent) {
View lastAddedItem = parent.getChildAt(getCount()-1);
if(lastAddedItem == null) {
Log.w("ListAdapter", "View is null");
}
}
This message always appears in the LogCat, which means that the View I try to grab is Null.
I've also tried this:
View lastAddedItem = parent.getChildAt(parent.getChildCount()-1);
So how can I grab a specific view from my ViewGroup object?
I know that my adapter holds several items, by doing calling
getCount:
Yes it does, but the getCount()(returning the items in the Adapter) method of an adapter has nothing to do with getting the children of a ListView with getChildAt()(where you should use getChildCount() as this will return the Views present in the ViewGroup).
lastAddedItem = parent.getChildAt(parent.getChildCount()-1);
This should return a non-null view, the last view returned by the getView() method.
I just want to animate a specific View in my ViewGroup
If you are going to animate a list row(or part of that row) when it becomes visible than register a scroll listener for the ListView and start the animation from there when the target view is appearing on the screen.
I don't how are you implemented the rest of the adapter, but if you are doing it in the right way, and I am right, the parent only contains the Views being displayed on the device's screen, and each time you pull down or pull up the list, it modifies the content of those views, that is why you get Null.
What you want to achieve (animate a view), should be done in runtime, checking if the view currently being displayed in the screen should be animated or not.
Hope it helps.
Related
I have an expandable list view with checkboxes. When i click a child, an alertdialog and i choose the quantity and then the textView of a child changes. BUT when i scroll down the list and this child disappers from view , the list forget changed textview and set the old one. What's the reason?
ListView (and its descendent ExpandableListView) does NOT create and store the views forever; instead it creates them on-the-fly as needed.
Imagine a scenario where you have a ListView with a list containing 1000 items; but the views for only any 5 items can be visible on the screen at a given time. Do you think that ListView would create and maintain 1000 different views on the screen? That would be a waste of memory, and might cause the UI to lag.
Instead, ListView internally calls getView() function to obtain the view for each item and shows it on the screen. It does this every time the item is brought into the screen display, and only for those many number of items which can fit into the screen at a given time (ListView handles these things internally so you do not have to worry about this)
All you need to do is set the text in the corresponding list item, and use this text to populate the textview in getView(). Maintain a text String and create some form of getText() and setText(String) methods in whatever Object type you are using as an Item.
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
......//initialize text view for this position
Item item = getItem(position);
textView.setText(item.getText());
.......
}
Once you set the text in the list item via alertDialog, Call notifyDataSetChanged() on the adapter to indicate that getView needs to be called again for all the views currently in display.
In your Listener, pass a reference to the adapter of the ListView. When you set the quantity in the alertDialog, just use
{
......
adapter.getItem(position).setText(quantityText);
adapter.notifyDataSetChanged();
......
}
The first line sets the text in the item; the second line tells the adapter that the information in the items have changed and it needs to create the views again.
i use ListView to display a list of 30 products.
protected class ListProductAdapter extends ArrayAdapter<Product>
implements View.OnClickListener {
...
#Override
public View getView(int position, View convertView, ViewGroup parent) {
I noticed that when I display the activity, it first calls getView 6 times, then if I scroll down, getView will be called to display other products, but if then I scroll up, getView is called again on product for which getView had already been called. Isn't it possible to get it in memory to not have to recalculate everything I scroll down and up ?
The ListView recycles its Views precisely so you do not have to have a View for every item in memory all the time, but it passes an old View as convertView so it can be reused and doesn't have to be re-inflated every time. See here.
That's how ListView works. It manages a number of views and calls getView(int, View, ViewGroup) whenever it needs one view to be set up. It doesn't hold to many views though. You might be able to hold all in memory, but that's not its intent.
If convertView is null the list needs you to create the views (your first 6 calls to getView). When you start scrolling, the list will provide you with an (already initialized) convertView which you only need to refill with the data you want to display.
See the documentation of getView for an elaborate explanation.
I am using horizontal list view and adding dynamic data into this, but I want to add an item when the scroll reached to the right most item in the listview.
How can I get that scroll reached to the right most position?
Implement an onScrollListener to your listview, and fetch data through onScroll() method.
There are many libraries for doing this easily. The following is a vertical listview example, but you can always change it to Horizontal and modify the code according to your needs.
https://github.com/shontauro/android-pulltorefresh-and-loadmore
In order to do that, you have to mock the size of the list ruled by your adapter. For example, if the list is called myList, its size is myList.size(), you will have to do something like: myList.add(mockelemnt).
Now that you have mocked the last element, what you may do is to handle it on your adapter method getView():
#Override
public View getView(int position, View convertView, ViewGroup parent){
if (oistion < myList.size(){
//work with conventional view
}else if (postion == myList.size()){
//work with addMore view
}
}
Hope it helps
public class CustomAdapter extends BaseAdapter
I found a code that extends BaseAdapter
public View getView(int index, View view, final ViewGroup parent) {
if (view == null) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
view = inflater.inflate(R.layout.single_list_item, parent, false);
}
}
TextView textView = (TextView) view.findViewById(R.id.tv_string_data);
textView.setText(dataModel.getName());
my question is when view == null ?
why we need the code if (view == null) {}
thanks
A ListView typically contain more data then the number of displayed rows. If the user scrolls the list then rows and their associated Views will be scrolled out of the visible area. The Java objects which represents the rows can be reused for newly visible rows.
If Android determines that a View which represents a row is not visible anymore it allows the getView() method to reuse it via the convertView parameter.
A performance optimized adapter assigns the new data to the convertView. This avoids inflating an XML file and creating new Java objects.
In case no View is available for reuse, Android will pass null to the convertView parameter. Therefore the adapter implementation need to check for this.
For the first item in the listView the View will be null. It needs to be inflated for the first item.
Please be free to ask any further doubts.
Android re-cycles View objects to minimize object creation and memory usage. The View that is passed to you will either be null, in which case you are expected to create it, or the view will be non-null which means it has been re-cycled. Re-cycled views are ones that you may have created earlier, but can now be used for a different purpose.
A good example of this is a listview. A list may have many elements, say 100. The screen however may only display 10 items of the list. Thus when you scroll the screen, views that were for items no longer on the screen may be passed to you for re-use. This is re-cycling.
For list view we have to provide view for each and every item, and also we have to fill contents also. In most cases the same view will be repeated in every item with different content. So at the first time in getView method we will check, if view is null then we should inflate a view and fill the contents and return. At second time the view will not be null. So you can reuse or provide different view.
I want to change the background color of one of my views in my listview
myListView.getView(int position, View convertView, ViewGroup parent).setBackgroundColor(0x00FFE303);
I know what position is - this will be my index of the arrayadapter, but I don't know what view and viewgroup are. I have declared them above this line, but I don't know what to initialize them to
help?
I'm not sure you want to be calling getView() manually like that. getView is called automatically by Android when a item in a listview is drawn to the screen. What would be most common to do, would be to extend an Adapter class (like ArrayAdapter) and #Override the getView() method.