Reputation: 4323
In Recyclerview with multiple layouts I override the getItemViewType() method by which I decide which layout to display. Strange issue occurred when on scrolling duplicate items appeared and change their position too.
When I hardcode the things on the basis of the position then no duplicate's like below code sample.
@Override
public int getItemViewType (int position)
{
switch (position)
{
case 0:
return TYPE_HEADER;
case 8:
return TYPE_HEADER;
default:
return TYPE_ITEMS;
}
}
But duplicate's start when I change it like below code and make it dynamic instead of static positions.
String tempDate = "";
List<String> items = new ArrayList<>();
items.add("2017-01-01");
items.add("2017-01-01");
items.add("2017-01-02");
items.add("2017-01-02");
items.add("2017-01-02");
items.add("2017-01-03");
items.add("2017-01-03");
items.add("2017-01-03");
items.add("2017-01-04");
@Override
public int getItemViewType (int position)
{
if(!tempDate.equalsIgnoreCase(items.get(position)){
tempDate = items.get(position);
return TYPE_HEADER;
} else{
tempDate = items.get(position);
return TYPE_ITEMS;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int i) {
switch (viewHolder.getItemViewType()) {
case TYPE_HEADER:
//Make your header view visible
initialize the view resources of HeaderLayout xml
break;
case TYPE_ITEM:
//Make your second header view visible
initialize the view resources of ItemLayout xml
break;
}
}
The other methods onBindViewHolder(), onCreateViewHolder() are fine as per my knowledge. Any help is appreciated.
Upvotes: 1
Views: 1340
Reputation: 796
You can use this code
@Override
public int getItemViewType(int position) {
String tem = "";
for (int i = 0; i < items.size(); i++) {
if (!tem.equals(items.get(i))) {
tem=items.get(i);
if (i == position) {
return TYPE_HEADER;
}
} else {
if (i == position) {
return TYPE_items;
}
}
}
return -1;
}
Upvotes: 0
Reputation: 5470
I think simple is better here:
private List<String> items = new ArrayList<>();
@Override
public int getItemViewType (int position) {
if (position == 0) {
return TYPE_HEADER;
}
String textForPosition = items.get(position);
String textForPrevPosition = items.get(position - 1);
if (textForPosition.equalsIgnoreCase(textForPrevPosition)) {
return TYPE_HEADER;
}
return TYPE_ITEM;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int i) {
// Use dateText instead of tempDate
String dateText = items.get(i);
switch (viewHolder.getItemViewType()) {
case TYPE_HEADER:
//Make your header view visible initialize the view resources of HeaderLayout xml
break;
case TYPE_ITEM:
//Make your second header view visible initialize the view resources of ItemLayout xml
break;
}
}
Upvotes: 1
Reputation: 1615
I think the problem is in that code section:
if(!tempDate.equalsIgnoreCase(items.get(position)){
tempDate = items.get(position);
return TYPE_HEADER;
}
else{
tempDate = items.get(position);
return TYPE_ITEMS;
}
I'd recomment to create another list in your adapter which called headers. I already implemented a class which extends a baseadapter which i am using for a navigation list with headers and items. Maybe you can take some ideas for your problem:
/**
* Adapter class for the navigation list. It handles items and section header items.
*/
public class CDMNavListAdapter extends BaseAdapter {
/**
* Constructor
*
* @param p_Context the context
*/
public CDMNavListAdapter(Context p_Context) {
m_Inflater = (LayoutInflater) p_Context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
/**
* Adds an item to the list
*
* @param p_Item the item to add
*/
public void addItem(CDMNavigationItem p_Item) {
m_Data.add(p_Item);
notifyDataSetChanged();
}
/**
* Adds a section header item to the list
*
* @param p_Item the section head item
*/
public void addSectionHeaderItem(String p_Item) {
// CDMNavigationItem is just a wrapper: CDMNavigationItem(int p_iType , String p_Title, int p_iResIcon, String p_Count)
m_Data.add(new CDMNavigationItem(ADMNavigationTypes.iSECTION_HEADER, p_Item, -1, "0"));
m_SectionHeader.add(m_Data.size() - 1);
notifyDataSetChanged();
}
@Override
public int getItemViewType(int p_iPosition) {
return m_SectionHeader.contains(p_iPosition) ? iTYPE_SEPARATOR : iTYPE_ITEM;
}
@Override
public int getViewTypeCount() {
return 2;
}
@Override
public int getCount() {
return m_Data.size();
}
@Override
public CDMNavigationItem getItem(int p_iPosition) {
return m_Data.get(p_iPosition);
}
@Override
public long getItemId(int p_iPosition) {
return p_iPosition;
}
@Override
public View getView(int p_iPosition, View p_ConvertView, ViewGroup p_Parent) {
int l_iRowType = getItemViewType(p_iPosition);
// sets the text to the item / section head item
CDMNavigationItem l_NavItem = m_Data.get(p_iPosition);
switch(l_iRowType) {
// item
case iTYPE_ITEM:
// item layout code
break;
// section header
case iTYPE_SEPARATOR:
// section header layout code
break;
}
return p_ConvertView;
}
/**
* Returns true if the item on the position is a section header item
*
* @param p_iPosition the position
* @return true if the item on the position is a section header item
*/
public boolean isSectionHeader(int p_iPosition) {
return getItemViewType(p_iPosition) == iTYPE_SEPARATOR;
}
/**
* Gets the position without header sections
* @param p_iPosition the position
* @return int the position without header sections
*/
public int getPositionWithoutHeaderSections(int p_iPosition) {
int l_iPositionWithoutHeaderSections = -1;
for(int i = 0; i <= p_iPosition; i++) {
if(!isSectionHeader(i))
l_iPositionWithoutHeaderSections++;
}
return l_iPositionWithoutHeaderSections;
}
/**
* Clears the data
*/
public void clear() {
m_Data.clear();
m_SectionHeader.clear();
notifyDataSetChanged();
}
private static final int iTYPE_ITEM = 0;
private static final int iTYPE_SEPARATOR = 1;
private List<CDMNavigationItem> m_Data = new ArrayList<>();
private Set<Integer> m_SectionHeader = new TreeSet<>();
private LayoutInflater m_Inflater;
}
Upvotes: 0