I\'m reading this tutorial http://android.amberfog.com/?p=296 . I\'d like to create a Listview weith different types of rows. I understand how to create the adapter, but wha
This might be a wrong method to do it. If you have only one component in the ListView then use simple adapter else use custom adapter with separate XML for the list row.
Sample code:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.listhistory);
initcomponents();
ArrayList<HashMap<String, String>> alist = new ArrayList<HashMap<String, String>>();
for (int i = 1; i < 20; i++) {
HashMap<String, String> hmap = new HashMap<String, String>();
hmap.put("date", "" + i + "/13");
hmap.put("restaurant", "Restaurant" + i);
hmap.put("distance", "" + (i * 100) + "kms");
alist.add(hmap);
}
final CustomListAdapter adapter = new CustomListAdapter(this,
R.layout.listitemhistory, alist);
list.setAdapter(adapter);
}
private void initcomponents() {
list = (ListView) findViewById(R.id.history_lst_list);
}
public void backButtonClick(View v) {
finish();
}
class CustomListAdapter extends ArrayAdapter<HashMap<String, String>> {
Context context;
int textViewResourceId;
ArrayList<HashMap<String, String>> alist;
public CustomListAdapter(Context context, int textViewResourceId,
ArrayList<HashMap<String, String>> alist) {
super(context, textViewResourceId);
this.context = context;
this.alist = alist;
this.textViewResourceId = textViewResourceId;
}
public int getCount() {
return alist.size();
}
public View getView(int pos, View convertView, ViewGroup parent) {
Holder holder = null;
LayoutInflater inflater = ((Activity) context)
.getLayoutInflater();
convertView = inflater.inflate(R.layout.listitemhistory,
parent, false);
holder = new Holder();
holder.date = (TextView) convertView
.findViewById(R.id.listitemhistory_txt_date);
holder.restaurant = (TextView) convertView
.findViewById(R.id.listitemhistory_txt_restaurant);
holder.distance = (TextView) convertView
.findViewById(R.id.listitemhistory_txt_distance);
holder.lin_background = (LinearLayout) convertView
.findViewById(R.id.history_lin_background);
convertView.setTag(holder);
holder = (Holder) convertView.getTag();
holder.date.setText(alist.get(pos).get("date"));
holder.restaurant.setText(alist.get(pos).get("restaurant"));
holder.distance.setText(alist.get(pos).get("distance"));
return convertView;
}
class Holder {
TextView date, restaurant, distance;
LinearLayout lin_background;
}
}
It wont be a problem. But I think you got the tutorial wrong.
Your need to define a layout for a row.
If you want your row to be able to contain a Text or an Image, you need to add both Views to the Layout.
Now in you adapter, where you fill your List you decide which item to set.
So lets say you have 2 Strings and an image.
So you set the text for the first two rows and add an image to the third. You dont have to predefine every row for itself, as i guess thats what you are trying to do.
@Override
public int getItemViewType(int position) {
if (position % 4 == 0) {
return 0;
} else if (position % 4 == 1) {
return 1;
} else if (position % 4 == 2) {
return 2;
}
return 3;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
int type = getItemViewType(position);
if (convertView == null) {
switch (type) {
case 0: {
convertView = mInflater.inflate(R.layout.element1, null);
break;
}
case 1: {
convertView = mInflater.inflate(R.layout.element2, null);
break;
}
case 2: {
convertView = mInflater.inflate(R.layout.element3, null);
break;
}
case 3: {
convertView = mInflater.inflate(R.layout.element4, null);
break;
}
}
holder = new ViewHolder();
holder.txt1 = (TextView) convertView.findViewById(R.id.text1);
holder.txt2 = (TextView) convertView.findViewById(R.id.text2);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
String rowItem = null;
rowItem = rowItems[position];
holder.txt1.setText(rowItem);
rowItem = rowItems[position+1];
holder.txt1.setText(rowItem);
return convertView;
}
private class ViewHolder {
TextView txt1, txt2;
}
You need to override getViewItemType
and getViewTypeCount
. You will also need to have custom layouts.
getItemViewType(int position)
- returns information which layout type you should use based on position.
You should have a look at the video in the link.
http://www.youtube.com/watch?v=wDBM6wVEO70
private static final int TYPE_ITEM1 = 0;
private static final int TYPE_ITEM2 = 1;
private static final int TYPE_ITEM3 = 2;
Then
int type;
@Override
public int getItemViewType(int position) {
if (position== 0){
type = TYPE_ITEM1;
} else if (position == 1){
type = TYPE_ITEM2;
}
else
{
type= TYPE_ITEM3 ;
}
return type;
}
@Override
public int getViewTypeCount() {
return 3;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
LayoutInflater inflater = null;
int type = getItemViewType(position);
// instead of if else you can use a case
if (row == null) {
if (type == FIRST_TYPE) {
//infalte layout of type1
}
if (type == SECOND_TYPE) {
//infalte layout of type2
} else {
//infalte layout of normaltype
}
}