i'm trying to load admob native ads inside a recyclerview. I've used the native ads templates. I've initialized the ads in the main activity(onCreate).
MobileAds.initialize(this, "ca-app-pub-3940256099942544~3347511713");
this is my items_ads.xml
<com.google.android.ads.nativetemplates.TemplateView android:id="#+id/my_template"
app:gnt_template_type="#layout/gnt_small_template_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" />
and this is my adapter class
public class WallpaperzAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final int CONTENT_TYPE=1;
private final int AD_TYPE=2;
private Activity _activity;
private List<Photo> wallpapersList = new ArrayList<Photo>();
Context context;
public WallpaperzAdapter(Activity activity, List<Photo> wallpapersList) {
this._activity = activity;
this.wallpapersList = wallpapersList;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == AD_TYPE) {
adViewHolder madViewHolder = new adViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_ads, null, false));
return madViewHolder;
} else{
WallpaperViewHolder mYourViewHolder = new WallpaperViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_wallpaperz, null, false));
return mYourViewHolder;
}
}
#Override
public void onBindViewHolder(#NonNull final RecyclerView.ViewHolder holder, final int position) {
if (getItemViewType(position) == CONTENT_TYPE) {
final Photo p = wallpapersList.get(position);
((WallpaperViewHolder) holder).thumbNail.setVisibility(View.VISIBLE);
Glide.with(_activity)
.load(p.getSrc().getPortrait())
.thumbnail(0.5f)
.into(((WallpaperViewHolder) holder).thumbNail);
((WallpaperViewHolder) holder).thumbNail.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.v("","");
}
});
} else if (getItemViewType(position) == AD_TYPE){
final AdLoader adLoader = new AdLoader.Builder(context, "ca-app-pub-3940256099942544/2247696110")
.forUnifiedNativeAd(new UnifiedNativeAd.OnUnifiedNativeAdLoadedListener() {
#Override
public void onUnifiedNativeAdLoaded(UnifiedNativeAd unifiedNativeAd) {
// Show the ad.
NativeTemplateStyle styles = new
NativeTemplateStyle.Builder().build();
TemplateView template = ((adViewHolder) holder).Adtemplate;
template.setStyles(styles);
template.setNativeAd(unifiedNativeAd);
}
})
.withAdListener(new AdListener() {
#Override
public void onAdFailedToLoad(int errorCode) {
// Handle the failure by logging, altering the UI, and so on.
}
})
.withNativeAdOptions(new NativeAdOptions.Builder()
// Methods in the NativeAdOptions.Builder class can be
// used here to specify individual options settings.
.build())
.build();
adLoader.loadAd(new AdRequest.Builder().build());
}}
#Override
public int getItemCount() {
return wallpapersList.size();
}
public class WallpaperViewHolder extends RecyclerView.ViewHolder {
public ImageView thumbNail;
final ProgressBar imageloader;
public WallpaperViewHolder(View itemView) {
super(itemView);
// Grid thumbnail image view
imageloader = itemView.findViewById(R.id.imgLoader);
thumbNail = itemView
.findViewById(R.id.home_image_item_view);
}
}
class adViewHolder extends RecyclerView.ViewHolder {
TemplateView Adtemplate;
public adViewHolder(#NonNull View itemView) {
super(itemView);
Adtemplate = itemView.findViewById(R.id.my_template);
}
}
#Override
public int getItemViewType(int position) {
if ((position+1) % 5 == 0 && (position+1) != 1) {
return AD_TYPE;
}
return CONTENT_TYPE;
}
}
when i start the app, i get the following error which is the located in the onBindViewHolder where i tried to load the ad for the AD_TYPE
java.lang.NullPointerException: context cannot be null
at com.google.android.gms.common.internal.Preconditions.checkNotNull(Unknown Source:11)
at com.google.android.gms.ads.AdLoader$Builder.<init>(com.google.android.gms:play-services-ads-lite##19.3.0:2)
at com.amatyasajal.hdwallpaperz.adapter.WallpaperzAdapter.onBindViewHolder(WallpaperzAdapter.java:104)
at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:7065)
please help me, this is my first time working with admob and I'm very confused. Thanks in advance.
hey from your code the context is really null you have to initialize it first in constractor or just use _activity it will work and let me know
Related
I try to implement Native Ads inside RecyclerView. The ad should be placed every 3 items in recycler view. I use a native ads template. Ads are loaded but they have overlapped items in RecyclerView. I try couple of solution but they didn't work. Please help me, thank you in advance.
Below is the code for Adapter class:
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
Context c;
ArrayList<Model> models;
private static final int CONTENT_TYPE = 1;
private static final int AD_TYPE = 0;
public MyAdapter(Context c, ArrayList<Model> models) {
this.c = c;
this.models = models;
}
#Override
public int getItemViewType(int position) {
if (position % 3 == 0) {
return AD_TYPE;
} else {
return CONTENT_TYPE;
}
}
class adViewHolder extends RecyclerView.ViewHolder {
TemplateView adTemplate;
public adViewHolder(#NonNull View itemView) {
super(itemView);
adTemplate = itemView.findViewById(R.id.native_ad);
}
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
if (viewType == AD_TYPE) {
adViewHolder myadViewHolder = new adViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_ads, null, false));
return myadViewHolder;
} else {
MyHolder myHolder = new MyHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.single_list_item, null, false));
return myHolder;
}
}
#Override
public void onBindViewHolder(#NonNull final RecyclerView.ViewHolder holder, int position) {
if (getItemViewType(position) == CONTENT_TYPE) {
((MyHolder) holder).mTitle.setText(models.get(position).getTitle());
((MyHolder) holder).mDescription.setText(models.get(position).getDesc());
((MyHolder) holder).mImageView.setImageResource(models.get(position).getImage());
} else if (getItemViewType(position) == AD_TYPE) {
final AdLoader adLoader = new AdLoader.Builder(c, "ca-app-pub-3940256099942544/2247696110")
.forUnifiedNativeAd(new UnifiedNativeAd.OnUnifiedNativeAdLoadedListener() {
#Override
public void onUnifiedNativeAdLoaded(UnifiedNativeAd unifiedNativeAd) {
NativeTemplateStyle styles = new NativeTemplateStyle.Builder().build();
TemplateView template = ((adViewHolder) holder).adTemplate;
template.setStyles(styles);
template.setNativeAd(unifiedNativeAd);
}
})
.withAdListener(new AdListener() {
#Override
public void onAdFailedToLoad(int errorCode) {
}
})
.withNativeAdOptions(new NativeAdOptions.Builder()
.build())
.build();
adLoader.loadAd(new AdRequest.Builder().build());
}
}
#Override
public int getItemCount() {
return models.size();
}
I want place the admob native advanced ads in every 3 position of my recycler view in android app.
I would like to template provided by Admob.
https://github.com/googleads/googleads-mobile-android-native-templates
Here is xml code implementation of native ads
<com.google.android.ads.nativetemplates.TemplateView
android:id="#+id/my_template"
<!-- this attribute determines which template is used. The other option is
#layout/gnt_medium_template_view -->
app:gnt_template_type="#layout/gnt_small_template_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Here is Java code implementation of Admob
MobileAds.initialize(this, "[_app-id_]");
AdLoader adLoader = new AdLoader.Builder(this, "[_ad-unit-id_]")
.forUnifiedNativeAd(new UnifiedNativeAd.OnUnifiedNativeAdLoadedListener() {
#Override
public void onUnifiedNativeAdLoaded(UnifiedNativeAd unifiedNativeAd) {
NativeTemplateStyle styles = new
NativeTemplateStyle.Builder().withMainBackgroundColor(background).build();
TemplateView template = findViewById(R.id.my_template);
template.setStyles(styles);
template.setNativeAd(unifiedNativeAd);
}
})
.build();
adLoader.loadAd(new AdRequest.Builder().build());
}
RecyclerView Adapter Class:
public class ArticleAdapter extends RecyclerView.Adapter<ArticleAdapter.MyViewHolder>{
private Context mContext;
private List<ArticleJson> articleList;
String titleoflist;
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView txtTitle,txtDesc,txtStatus,txtColor,txtAuthor;
LinearLayout linearLayout;
private ArticleJson m_articleJson;
public MyViewHolder(View view) {
super(view);
txtTitle = view.findViewById(R.id.texViewArticleTitle)
linearLayout = view.findViewById(R.id.article_linearlayout);
}
public void bindView(final ArticleJson articleJson){
m_articleJson = articleJson;
txtTitle.setText(articleJson.getmTitle());
txtAuthor.setText(titleoflist);
}
}
public ArticleAdapter(Context mContext, List<ArticleJson> articleList,String titleoflist) {
this.mContext = mContext;
this.articleList = articleList;
this.titleoflist = titleoflist;
}
#NonNull
#Override
public ArticleAdapter.MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item_article, parent, false);
return new ArticleAdapter.MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(#NonNull ArticleAdapter.MyViewHolder holder, int position) {
final ArticleJson articleJson = articleList.get(position);
holder.bindView(articleJson);
holder.linearLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//Toast
}
});
}
#Override
public int getItemCount() {
return articleList.size();
}
}
First, you need to create the Ads container item_ads.xml folder
<com.google.android.ads.nativetemplates.TemplateView
android:id="#+id/my_template"
<!-- this attribute determines which template is used. The other option is
#layout/gnt_medium_template_view -->
app:gnt_template_type="#layout/gnt_small_template_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Second, your recyclerview adapter must extends the following
extends RecyclerView.Adapter<RecyclerView.ViewHolder>
Now you need to override 4 methods
public RecyclerView.ViewHolder onCreateViewHolder()
public void onBindViewHolder()
public int getItemCount()
public int getItemViewType()
In the getItemViwType() method, We will define two possibilities
#Override
public int getItemViewType(int position) {
if (AD_LOGIC_CONDITION)) {
return AD_TYPE;
} else{
return CONTENT_TYPE; ///do not forget to initialize any of AD_TYPE and CONTENT_TYPE
}
}
then we will create two view holders, one for your content and second for your Ads
I assume that you know how to create your view holder so I will just explain the AD View holder
class adViewHolder extends RecyclerView.ViewHolder {
TemplateView Adtemplate;
public adViewHolder(#NonNull View itemView) {
super(itemView);
Adtemplate = itemView.findViewById(R.id.my_template);
}
Now we return to the onCreateViewHolder() method
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
if (viewType == AD_TYPE) {
adViewHolder madViewHolder = new adViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_ads, null, false));
return madViewHolder;
} else{
YourViewHolder mYourViewHolder = new YourViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_item, null, false));
return mYourViewHolder;
}
}
now we go to the onBindViewHolder() method
#Override
public void onBindViewHolder(#NonNull final RecyclerView.ViewHolder holder, int position) {
if (getItemViewType(position) == TYPE_CONTENT) {
///your data
// AN EXAMPLE
((YourViewHolder) holder).textview.setText(data.getmtext());
((YourViewHolder) holder).Img.setImageResource(data.getmImg());
((YourViewHolder) holder).title.setText(data.getmName());
} else if (getItemViewType(position) == TYPE_AD){
final AdLoader adLoader = new AdLoader.Builder(context, "ca-app-pub-3940256099942544/2247696110")
.forUnifiedNativeAd(new UnifiedNativeAd.OnUnifiedNativeAdLoadedListener() {
#Override
public void onUnifiedNativeAdLoaded(UnifiedNativeAd unifiedNativeAd) {
// Show the ad.
NativeTemplateStyle styles = new
NativeTemplateStyle.Builder().build();
TemplateView template = ((adViewHolder) holder).Adtemplate;
template.setStyles(styles);
template.setNativeAd(unifiedNativeAd);
}
})
.withAdListener(new AdListener() {
#Override
public void onAdFailedToLoad(int errorCode) {
// Handle the failure by logging, altering the UI, and so on.
}
})
.withNativeAdOptions(new NativeAdOptions.Builder()
// Methods in the NativeAdOptions.Builder class can be
// used here to specify individual options settings.
.build())
.build();
adLoader.loadAd(new AdRequest.Builder().build());
}
in Your article list, fill every third entry with "null" values (or "Ad" String value if You want).
in Your Adapter set for list entries with "null" values content_type = "AD_TYPE":
#Override
public int getItemViewType(int position) {
if (yourList.get(position).getArticle().equals("null")) {
ADPosition = position;
return AD_TYPE;
}
return CONTENT_TYPE;
}
and in Your ViewHolderClass set AD_Layout for AD_TYPE Entries and normal layout for CONTENT_TYPE entries.
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == CONTENT_TYPE) {
itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.normalLayoutRecyclerView,prent,false);
return new MyViewHolder(itemView)
}
if (viewType == AD_TYPE) {
itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.ad_layout, parent, false);
}
return new MyViewHolder(itemView)
}
Hope that helps.
GGK
What i am doing is, that i have a recyclerView which has it's adapter and from within adapter i am loading the nativeAds. But due to loading the ads within the recyclerView instead of preloading the ads my recyclerView is not scrolling smoothly.
And also i tried to load the native ad on different thread but that also was't helpful.
Any ideas how to load the native ad without sacrificing the performance??
public class GetInspiredAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public static int VIEW_TYPE_ADS = 0;
public static int VIEW_TYPE_NOTADS = 1;
// this shows that the ad is to be added after this many items.
public static int ADS_AFTER_HOW_MANY_ITEMS = 3;
private boolean isNetworkAvailable = false;
private Context context;
private ArrayList<Object> list;
private GetInspiredListener listener;
public GetInspiredAdapter(Context context, ArrayList<Object> list, GetInspiredListener listener) {
this.context = context;
this.list = list;
this.listener = listener;
}
private void addNativeToList() {
int i = ADS_AFTER_HOW_MANY_ITEMS;
while (i < list.size()) {
list.add(i, new UnifiedNativeAdView(context));
i += ADS_AFTER_HOW_MANY_ITEMS + 1;
}
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int viewType) {
if (viewType == VIEW_TYPE_ADS) {
View unifiedNativeLayoutView = LayoutInflater.from(context).inflate(R.layout.ad_unified, viewGroup, false);
unifiedNativeLayoutView.setTag(new Integer(GetInspiredAdapter.VIEW_TYPE_ADS));
return new UnifiedNativeAdViewHolder(unifiedNativeLayoutView);
} else {
View itemView = LayoutInflater.from(context).inflate(R.layout.image_item, viewGroup, false);
itemView.setTag(new Integer(GetInspiredAdapter.VIEW_TYPE_NOTADS));
return new GetInspiredViewHolder(itemView);
}
}
#Override
public void onBindViewHolder(#NonNull final RecyclerView.ViewHolder holder, int position) {
int viewType = getItemViewType(position);
if (viewType == VIEW_TYPE_ADS) {
if (!isNetworkAvailable) {
list.remove(position);
notifyDataSetChanged();
return;
}
AdLoader.Builder builder = new AdLoader.Builder(context, Constants.INSPIRED_MOB)
.forUnifiedNativeAd(new UnifiedNativeAd.OnUnifiedNativeAdLoadedListener() {
#Override
public void onUnifiedNativeAdLoaded(UnifiedNativeAd unifiedNativeAd) {
populateNativeAdView(unifiedNativeAd, (UnifiedNativeAdViewHolder) holder);
}
}).withAdListener(new AdListener() {
#Override
public void onAdFailedToLoad(int i) {
super.onAdFailedToLoad(i);
}
});
builder.build().loadAd(new AdRequest.Builder().build());
} else if (viewType == VIEW_TYPE_NOTADS) {
LoadImage((InspiredObject) list.get(getItemIndex(position)), (GetInspiredViewHolder) holder);
}
}
private void LoadImage(InspiredObject obj, GetInspiredViewHolder viewHolder) {
//Url link to images
String url = "http://aim-itech.com/mandala/image/";
String string = url + obj.low;
Glide.with(context).load(string).override(Constants.SAMPLE_SIZE_MEDIUM).into(viewHolder.imageView);
Log.e("TAG", string);
}
private void populateNativeAdView(UnifiedNativeAd nativeAd, UnifiedNativeAdViewHolder holder) {
if (nativeAd == null) {
holder.getAdView().setVisibility(View.INVISIBLE);
holder.textLoading.setVisibility(View.VISIBLE);
return;
}
holder.textLoading.setVisibility(View.GONE);
UnifiedNativeAdView adView = holder.getAdView();
adView.setVisibility(View.VISIBLE);
((TextView) adView.getHeadlineView()).setText(nativeAd.getHeadline());
((TextView) adView.getBodyView()).setText(nativeAd.getBody());
((Button) adView.getCallToActionView()).setText(nativeAd.getCallToAction());
NativeAd.Image icon = nativeAd.getIcon();
if (icon == null) {
adView.getIconView().setVisibility(View.INVISIBLE);
} else {
((ImageView) adView.getIconView()).setImageDrawable(icon.getDrawable());
adView.getIconView().setVisibility(View.VISIBLE);
}
if (nativeAd.getPrice() == null) {
adView.getPriceView().setVisibility(View.INVISIBLE);
} else {
adView.getPriceView().setVisibility(View.VISIBLE);
((TextView) adView.getPriceView()).setText(nativeAd.getPrice());
}
if (nativeAd.getStore() == null) {
adView.getStoreView().setVisibility(View.INVISIBLE);
} else {
adView.getStoreView().setVisibility(View.VISIBLE);
((TextView) adView.getStoreView()).setText(nativeAd.getStore());
}
if (nativeAd.getStarRating() == null) {
adView.getStarRatingView().setVisibility(View.INVISIBLE);
} else {
((RatingBar) adView.getStarRatingView())
.setRating(nativeAd.getStarRating().floatValue());
adView.getStarRatingView().setVisibility(View.VISIBLE);
}
if (nativeAd.getAdvertiser() == null) {
adView.getAdvertiserView().setVisibility(View.INVISIBLE);
} else {
((TextView) adView.getAdvertiserView()).setText(nativeAd.getAdvertiser());
adView.getAdvertiserView().setVisibility(View.VISIBLE);
}
// Assign native ad object to the native view.
adView.setNativeAd(nativeAd);
}
public int getItemIndex(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
Object recyclerViewItem = list.get(getItemIndex(position));
if (recyclerViewItem instanceof UnifiedNativeAd) {
return VIEW_TYPE_ADS;
} else if (recyclerViewItem instanceof UnifiedNativeAdView) {
return VIEW_TYPE_ADS;
}
return VIEW_TYPE_NOTADS;
}
public boolean isNetworkAvailable() {
return isNetworkAvailable;
}
public void setNetworkAvailable(boolean networkAvailable) {
isNetworkAvailable = networkAvailable;
if (isNetworkAvailable) {
addNativeToList();
}
}
#Override
public int getItemCount() {
return list.size();
}
public class GetInspiredViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
public GetInspiredViewHolder(#NonNull View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.imageProf);
imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
InspiredObject inspiredObject = (InspiredObject) list.get(getAdapterPosition());
Intent i = new Intent(context, InspiredActivity.class);
i.putExtra("image", inspiredObject.high);
listener.onClick(i);
}
});
}
}
public class UnifiedNativeAdViewHolder extends RecyclerView.ViewHolder {
private UnifiedNativeAdView adView;
private TextView textLoading;
private CardView adContainer;
public UnifiedNativeAdView getAdView() {
return adView;
}
UnifiedNativeAdViewHolder(View view) {
super(view);
textLoading = view.findViewById(R.id.native_loading_text);
adView = view.findViewById(R.id.native_ad_view);
adContainer = view.findViewById(R.id.ad_unified_conatiner);
// The MediaView will display a video asset if one is present in the ad, and the
// first image asset otherwise.
adView.setMediaView((MediaView) adView.findViewById(R.id.ad_media));
// Register the view used for each individual asset.
adView.setHeadlineView(adView.findViewById(R.id.ad_headline));
adView.setBodyView(adView.findViewById(R.id.ad_body));
adView.setCallToActionView(adView.findViewById(R.id.ad_call_to_action));
adView.setIconView(adView.findViewById(R.id.ad_icon));
adView.setPriceView(adView.findViewById(R.id.ad_price));
adView.setStarRatingView(adView.findViewById(R.id.ad_stars));
adView.setStoreView(adView.findViewById(R.id.ad_store));
adView.setAdvertiserView(adView.findViewById(R.id.ad_advertiser));
}
}
}
surprised there is no answer here.
The approach I would use outside of the recyclerview adapter:
adLoader.loadAds(new AdRequest.Builder().build(), NUMBER_OF_ADS_TO_LOAD(Max 5 according to docs);
instead usual adLoader.loadAd
and then
builder.forUnifiedNativeAd(new UnifiedNativeAd.OnUnifiedNativeAdLoadedListener() {
// OnUnifiedNativeAdLoadedListener implementation.
#Override
public void onUnifiedNativeAdLoaded(UnifiedNativeAd unifiedNativeAd) {
nativeAds.add(unifiedNativeAd);
}
});
where
private List<UnifiedNativeAd> nativeAds = new ArrayList<>();
which you pass to your recyclerview adapter and mix in your other items.
This will need some memory handling with destroy called before you request another list etc. but the idea is to preload a list of ads instead of loading them while scrolling
I am working with RecyclerView which support pagination with Firestore database.I want to showing into 10 items recylcerview an Ads,i try serveral times without succes,help me please to find the right code.
Here is my code of pagination.
//Initialize FirebasePagingOptions
DatabasePagingOptions<Pubs> options = new DatabasePagingOptions.Builder<Pubs>()
.setLifecycleOwner(this)
.setQuery(mDatabase, config, Pubs.class)
.build();
//Initialize Adapter
mAdapter = new FirebaseRecyclerPagingAdapter<Pubs, PubsViewHolder>(options) {
#Override
public int getItemViewType(int position)
{
if (position % 5 == 0)
return AD_TYPE;
return CONTENT_TYPE;
}
#NonNull
#Override
public PubsViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new PubsViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_pub, parent, false));
}
#Override
protected void onBindViewHolder(#NonNull PubsViewHolder holder,
int position,
#NonNull Pubs model) {
holder.setItem(model);
}
this is a full example to how to use multi type recyclerview with custom adapter with Model and Ads Type
and for paging issue you have to handle it outside adapter class it can be more easier.
public class SiteAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<SiteModel> dataList;
private Context context;
private static final int AD_TYPE = 1;
private static final int CONTENT_TYPE = 2;
public SiteAdapter(Context context) {
this.context = context;
dataList = new ArrayList<>();
}
#Override
public int getItemViewType(int position) {
if (dataList.get(position) == null)
return AD_TYPE;
return CONTENT_TYPE;
}
public List<SiteModel> getDataList() {
return dataList;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = null;
RecyclerView.ViewHolder vh = null;
if (viewType == AD_TYPE) {
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.ad_view_item, parent, false);
vh = new AdViewHolder(v);
} else {
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.site_list_item, parent, false);
vh = new SitesViewHolder(v);
}
return vh;
}
#Override
public void onBindViewHolder(#NonNull final RecyclerView.ViewHolder holder, int position) {
holder.setIsRecyclable(false);
if (getItemViewType(position) == CONTENT_TYPE) {
} else {
AdViewHolder adViewHolder = (AdViewHolder) holder;
AdRequest request = new AdRequest.Builder().build();
adViewHolder.adView.loadAd(request);
}
}
#Override
public int getItemCount() {
return dataList.size();
}
public void add(SiteModel siteModel, int i) {
dataList.add(siteModel);
notifyItemInserted(i);
}
public void add(List<SiteModel> moreData) {
dataList.addAll(moreData);
notifyDataSetChanged();
}
public void updateItem(String desc, boolean isFavourites, int adapterPosition) {
dataList.get(adapterPosition).setDesc(desc);
notifyItemChanged(adapterPosition);
}
public class SitesViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public SitesViewHolder(View itemView) {
super(itemView);
}
#Override
public void onClick(View v) {
if (clickListener != null) {
switch (v.getId()) {
}
}
}
private class AdViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
AdView adView;
public AdViewHolder(View itemView) {
super(itemView);
adView = itemView.findViewById(R.id.adView);
}
#Override
public void onClick(View v) {
}
}
}
Friends, help me please. I'm making a RecyclerView with ads. The list is not displayed correctly. When embedded advertising, break sequence list. In the screenshot I give an example.
The list is not currently displayed correctly. Item 10 is not displayed:
I need Item 10 to be visible as in this screenshot:
My adapter code:
public class ScheduleAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<Card> scheduleList;
private static final int CONTENT = 0;
private static final int AD = 1;
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView textDate;
public TextView textSubject;
public Button share;
public MyViewHolder(View view) {
super(view);
textDate = view.findViewById(R.id.textDate);
textSubject = view.findViewById(R.id.textSubject);
share = view.findViewById(R.id.shareBtn);
Typeface custom_font = Typeface.createFromAsset(view.getContext().getAssets(), "Exo2Light.ttf");
textDate.setTypeface(custom_font);
textSubject.setTypeface(custom_font);
}
}
public static class ViewHolderAdMob extends RecyclerView.ViewHolder {
public AdView mAdView;
public ViewHolderAdMob(View view) {
super(view);
mAdView = view.findViewById(R.id.adView);
}
}
public ScheduleAdapter(List<Card> scheduleList) {
this.scheduleList = scheduleList;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
RecyclerView.ViewHolder viewHolder = null;
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
if (viewType == CONTENT) {
View v = inflater.inflate(R.layout.recycler_item, parent, false);
viewHolder = new MyViewHolder(v);
} else {
View v = inflater.inflate(R.layout.recycler_item_admob, parent, false);
viewHolder = new ViewHolderAdMob(v);
}
return viewHolder;
}
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
if (getItemViewType(position) == CONTENT) {
MyViewHolder viewHolder = (MyViewHolder) holder;
Card card = scheduleList.get(position);
viewHolder.textDate.setText(card.getDateline());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
viewHolder.textSubject.setText(Html.fromHtml(card.getContentline(), Html.FROM_HTML_MODE_COMPACT));
else
viewHolder.textSubject.setText(Html.fromHtml(card.getContentline()));
((MyViewHolder) holder).share.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// handle your click here.
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
sharingIntent.putExtra(Intent.EXTRA_TEXT, "\uD83D\uDCC5 " + ((MyViewHolder) holder).textDate.getText().toString()+"\r\n"+((MyViewHolder) holder).textSubject.getText().toString());
v.getContext().startActivity(Intent.createChooser(sharingIntent,"Поділитися..."));
} });
} else {
AdRequest adRequest = new AdRequest.Builder()
//.addTestDevice("B86C95B89D21A5F8E2C22F0D94470A13")
.build();
((ViewHolderAdMob) holder).mAdView.setAdListener(new AdListener() {
#Override
public void onAdLoaded() {
super.onAdLoaded();
((ViewHolderAdMob) holder).mAdView.setVisibility(View.VISIBLE);
}
#Override
public void onAdFailedToLoad(int errorCode) {
super.onAdFailedToLoad(errorCode);
((ViewHolderAdMob) holder).mAdView.setVisibility(View.GONE);
}
});
((ViewHolderAdMob) holder).mAdView.loadAd(adRequest);
}
}
#Override
public int getItemViewType(int position) {
if (position == 10) {
return AD;
}
return CONTENT;
}
#Override
public int getItemCount() {
return scheduleList.size();
}
}
Replace your code with
#Override
public int getItemCount() {
return scheduleList.size() + 1;
}
and use this function get Card object in onBindViewHolder
public Card getItem(int position) {
if(position > 10){
return scheduleList.get(position - 1)
}else{
return scheduleList.get(position)
}
}
By adding 1 to getItemCount() function, we are making adapter to draw one more line which represents ad.
And being sure we dont have IndexOutOfBoundsException for 13th row by decreasing position by minus one for the values which bigger than 10 in getItem(int position) function.