I am facing some problem for rendering ListView from a dynamic layout. I don't know why the getView
is called only with position 0 and several times!
I searched over internet and stackoverflow but cannot find a suitable answer.
I am actually trying to do a demo of this: http://www.framentos.com/en/android-tutorial/2012/07/16/listview-in-android-using-custom-listadapter-and-viewcache/
Notably, my main layout file is surrounded by scrollbar.
main activity layout file:
<ListView
android:id="@+id/city_list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="@+id/questionsList"
android:paddingTop="20sp" >
</ListView>
My layout file for list view:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="80dip" >
<ImageView
android:id="@+id/ImageCity"
android:layout_width="90sp"
android:layout_height="90sp" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_toRightOf="@id/ImageCity"
android:orientation="vertical"
android:paddingLeft="10sp">
<TextView
android:id="@+id/cityName"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="25sp" />
<TextView
android:id="@+id/cityLinkWiki"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:autoLink="web"
android:textSize="15sp" />
</LinearLayout>
</RelativeLayout>
Adapter class:
import com.incidentreport.app.classes.objects.City;
public class CityListAdapter extends ArrayAdapter{
private int resource;
private LayoutInflater inflater;
private Context context;
public CityListAdapter ( Context ctx, int resourceId, List objects) {
super( ctx, resourceId, objects );
resource = resourceId;
inflater = LayoutInflater.from( ctx );
context=ctx;
}
@Override
public View getView ( int position, View convertView, ViewGroup parent ) {
Log.v("adapter", "pos: " + position + "#" + resource);
/* create a new view of my layout and inflate it in the row */
convertView = ( RelativeLayout ) inflater.inflate( resource, null );
/* Extract the city's object to show */
City city = (City)getItem( position );
/* Take the TextView from layout and set the city's name */
TextView txtName = (TextView) convertView.findViewById(R.id.cityName);
txtName.setText(city.getName());
/* Take the TextView from layout and set the city's wiki link */
TextView txtWiki = (TextView) convertView.findViewById(R.id.cityLinkWiki);
txtWiki.setText(city.getUrlWiki());
/* Take the ImageView from layout and set the city's image */
ImageView imageCity = (ImageView) convertView.findViewById(R.id.ImageCity);
return convertView;
}
}
main activity code snipps:
List listCity= new ArrayList();
listCity.add(new City("London","http://en.wikipedia.org/wiki/London","london"));
listCity.add(new City("Rome","http://en.wikipedia.org/wiki/Rome","rome"));
listCity.add(new City("Paris","http://en.wikipedia.org/wiki/Paris","paris"));
ListView listViewCity = ( ListView ) findViewById( R.id.city_list);
listViewCity.setAdapter( new CityListAdapter(this, R.layout.layout_city, listCity ) );
In Android development, any time we want to show a vertical list of scrollable items we will use a ListView which has data populated using an Adapter . The simplest adapter to use is called an ArrayAdapter because the adapter converts an ArrayList of objects into View items loaded into the ListView container.
BaseAdapter, as it's name implies, is the base class for so many concrete adapter implementations on Android. It is abstract and therefore, cannot be directly instantiated. If your data source is an ArrayList or array, we can also use the ArrayAdapter construct as an alternative.
BaseAdapter is a common base class of a general implementation of an Adapter that can be used in ListView, GridView, Spinner etc. Whenever you need a customized list in a ListView or customized grids in a GridView you create your own adapter and extend base adapter in that.
In this case what you can do is, create a empty layout in your main activity xml. Set a ID for that. While inflating the listview, inflate it to that layout.
Okay, I figured out the issue by expanding ListView as much possible. Meaning to say, giving a dynamic full height so that all item becomes visible.
I followed the below solution:
Calculate the size of a list view or how to tell it to fully expand
Use a ViewHolder
pattern for better performance.
http://developer.android.com/training/improving-layouts/smooth-scrolling.html
static class ViewHolder
{
TextView txtName,txtWiki;
ImageView imageCity;
}
Change getView to
@Override
public View getView ( int position, View convertView, ViewGroup parent ) {
ViewHolder holder;
if(convertView == null)
{
convertView = ( RelativeLayout ) inflater.inflate( resource, parent, false );
holder = new ViewHolder();
holder.txtName = (TextView) convertView.findViewById(R.id.cityName);
holder.txtWiki = (TextView) convertView.findViewById(R.id.cityLinkWiki);
holder.imageCity = (ImageView) convertView.findViewById(R.id.ImageCity);
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
City city = (City)getItem( position );
holder.txtName.setText(city.getName());
holder.txtWiki.setText(city.getUrlWiki());
return convertView;
}
ListView recyclues view's. You may also want to read
How ListView's recycling mechanism works
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With