Reputation: 1678
I want to display an ad every n items on my RecyclerAdapter.
I'm expecting this
|----- Item 0 -----|
|------- AD -------|
|----- Item 1 -----|
|----- Item 2 -----|
|----- Item 3 -----|
|----- Item 4 -----|
|----- Item 5 -----|
|------ ... -------|
|----- Item 15 ----|
|------- AD -------|
|----- Item 16 ----|
|------ ... -------|
But with a fast scroll I can have something like that
|----- Item 0 -----|
|------- AD -------|
|----- Item 1 -----|
|----- Item 2 -----|
|----- Item 3 -----|
|------ ... -------|
|---- Item 241 ----|
|------- AD -------|
|------ ... -------|
If I'm scrolling slowly ads are displayed after every 15 items. But if I'm scrolling fastly ads are displayed not correctly. For example an ad is displayed after item n°241, and 241 % 15 is not equal to 0.
Is it probably a problem due to view reuse, I am probably doing it wrong but I don't know how I can do it otherwise.
Here is my adapter code.
public class MyCursorRecyclerAdapter extends CursorRecyclerAdapter<RecyclerView.ViewHolder> {
private static final int AD_POS = 15;
private Context mContext;
private LayoutInflater mInflater;
class ViewHolderItem extends RecyclerView.ViewHolder {
public TextView mTextView;
public LinearLayout mLayout;
public ViewHolderItem(View layout) {
super(layout);
mTextView = (TextView) layout.findViewById(R.id.text);
mLayout = (LinearLayout) layout.findViewById(R.id.main_linear_layout);
}
}
public MyCursorRecyclerAdapter(Context context, Cursor c) {
super(c);
mContext = context;
mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.listview_item_layout, parent, false);
return new ViewHolderItem(v);
}
@Override
public void onBindViewHolderCursor(RecyclerView.ViewHolder holderDefault, Cursor cursor) {
int cursorPosition = cursor.getPosition();
final ViewHolderItem holder = (ViewHolderItem) holderDefault;
final String text = cursorPosition + " : "+ cursor.getString(cursor.getColumnIndex(MyTable.MY_COLUMN));
holder.mTextView.setText(text);
final ViewGroup layout = ((ViewHolderItem) holderDefault).mLayout;
if (cursorPosition % AD_POS == 0) {
NativeAd ad = new NativeAd(mContext, "ID");
ad.setAdListener(new AdListener() {
@Override
public void onError(Ad ad, AdError error) {}
@Override
public void onAdLoaded(Ad ad) {
mInflater.inflate(R.layout.native_ad_layout, layout);
AdManager.inflateAd((NativeAd) ad, layout, mContext);
}
@Override
public void onAdClicked(Ad ad) {}
});
ad.loadAd();
} else {
int childCount = layout.getChildCount();
if (layout.getChildAt(childCount-1).getId() == R.id.adUnit) {
layout.removeViewAt(childCount-1);
}
}
}
}
Upvotes: 2
Views: 2216
Reputation: 12365
The better way is use getItemViewType(int position)
method.
@Override
public int getItemViewType(int position) {
if(cursorPosition % AD_POS == 0){
return 0;
}
return 1;
}
And after that you have to use viewType param in onCreateViewHolder
method, to recognise which view you have to inflate as is shown in code below:
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if(viewType ==0){
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.listview_item_layout, parent, false);
} else if(viewType ==1){
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.different_layout, parent, false);
}
return new ViewHolderItem(v);
}
And additionally you have to support second layout in ViewHolderItem
or create SecondViewHolderItem
and return proper ViewHolder in method above and cast to proper ViewHolder
in onBindViewHolderCursor
method depend on the position of.
And you have to take into account these items in getItemCount()
method.
Upvotes: 6