Reputation: 138
I'm trying to make a ListView with the first item displayed in a different layout, and others in a common layout. Both layouts have the same elements which in pairs have the same names. When I do like this:
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null) {
if(position == 0){
convertView = inflater.inflate(R.layout.article_list_top_item, parent, false);
Log.d("ALA", "pos = " + position + ", inflated top");
}
else {
convertView = inflater.inflate(R.layout.article_list_item, parent, false);
Log.d("ALA", "pos = " + position + ", inflated normal");
}
}
// setText, setBitmap etc here
return convertView;
}
it didn't work.
From the log I could say, inflater.inflate
was triggered 6 times, inflated top
1 time and inflated normal
5 times.
What displayed is, article[0] was in layout article_list_top_item
and article[1] ~ article[5] was in article_list_item
.
Up until here it's ok, but the pattern repeated, which means article[6], article[12], [18],... were all in the layout article_list_top_item
which is not what I want.
What can I do to make ONLY the first article to appear in article_list_top_item
??
P.S. I tried renaming elements in article_list_top_item.xml
and if-branched the setText
setImage
process, didn't help.
I tried adding else return convertView;
before //setText
lines, it became a mess.
I thought of making a dedicated layout element for the first item only, but that's not what I want because the whole list lays under a SwipeRefreshLayout
Please help.
Upvotes: 4
Views: 2135
Reputation: 1904
You should use different itew view type. Your adapter reuse the view already inflated, so if you want to different kind you should tell him :
Create a holder for each of your view type
private class FirstHolder {
//add a field for each subview in view type 1
}
private class SecondHolder {
//add a field for each subview in view type 2
}
Override the getViewTypeCount()
method
@Override
public int getViewTypeCount() {
return 2;
}
Override the getItemViewType(int position)
method. This method tells which type of view is used for each position.
@Override
public int getItemViewType(int position) {
if (position == 0) {
return 0;
} else {
return 1;
}
}
Build and setup the view :
public View getView(int position, View convertView, ViewGroup parent) {
if (position == 0) {
FirstHolder holder;
if (convertView == null) {
holder = new FirstHolder();
convertView = inflater.inflate(R.layout.whatever_firstlayout, parent, false);
//for each field of holder find the subview
convertView.setTag(holder);
} else {
holder = (FirstHolder) convertView.getTag();
}
//set the data in subview with holder fields
} else {
SecondHolder holder;
if (convertView == null) {
holder = new SecondHolder();
convertView = inflater.inflate(R.layout.whatever_secondlayout, parent, false);
//for each field of holder find the subview
convertView.setTag(holder);
} else {
holder = (SecondHolder) convertView.getTag();
}
//set the data in subview with holder fields
}
return convertView;
}
Upvotes: 6
Reputation: 138
I found the problem. Exactly like @sonic said, I want to use different kinds of views for the same ListView so I have to tell him so, by overriding getViewTypeCount()
and getItemViewType(int position)
. Working code:
@Override
public int getViewTypeCount(){
return 2;
}
@Override
public int getItemViewType(int pos){
return pos > 0 ? 1 : 0;
}
public View getView(int position, View listItem, ViewGroup parent) {
if(listItem == null)
listItem = inflater.inflate(getItemViewType(position) == 0 ?
R.layout.article_list_top_item : R.layout.article_list_item
, parent, false);
// setText setBitmap etc. here
}
Comments: It works even if I don't use getViewTypeCount()
and getItemViewType(int position)
anywhere, but overriding them matters. Doubting
getItemViewType(int position)
would do anything, I tried not overriding it - and the result is, I had to override both to make it work.
I wonder how. Maybe everytime the view is inflated with a layout that's never used before, then the system assign that layout with a number from 0 to getViewTypeCount() - 1
? Otherwise, where have it been used (in parent classes' code) to make it matter?
I'll leave this here to think later.
Upvotes: 0
Reputation: 378
You can use addHeaderView. For example;
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View head = inflater.inflate(R.layout.headerlayout, listview, false);
listview.addHeaderView(head);
Upvotes: 1