【问题标题】:Embedding ads within Recyclerview在 Recyclerview 中嵌入广告
【发布时间】:2015-01-15 17:28:21
【问题描述】:

我正在尝试将我的应用程序从 listview 升级到 recyclerview。当我使用列表视图时,我使用this tutorial 在列表视图中嵌入了广告。

我无法将其添加到 recyclerview 中。关于如何在 Recyclerview 中完成此操作的任何观点?

目前在我的列表视图中,用于加载广告的代码如下:

    if ((position % k) == 0) {
      if (convertView instanceof AdView) {
        return convertView;
      } else {
        // Create a new AdView
        AdView adView = new AdView(activity, AdSize.BANNER,
                                   ADMOB_ID);

        float density = activity.getResources().getDisplayMetrics().density;
        int height = Math.round(AdSize.BANNER.getHeight() * density);
        AbsListView.LayoutParams params = new AbsListView.LayoutParams(
            AbsListView.LayoutParams.FILL_PARENT,
            height);
        adView.setLayoutParams(params);

        adView.loadAd(new AdRequest());
        return adView;
      }
    } else {
      return delegate.getView(position - (int) Math.ceil(position / k) - 1,
          convertView, parent);
    }

应该是这样的:

更新:参考谷歌的this video,它给出了完整的解释

【问题讨论】:

  • 要显示什么代码?现在怎么样了?
  • 添加现有代码 sn-p..
  • 对于寻找此解决方案的人...现在有一个 Cigogne 答案的实现example...我认为非常有用...我将其粘贴在这里是因为它可能对人们在看这个问题
  • 视频未找到!请修复它

标签: android listview android-recyclerview admob android-appcompat


【解决方案1】:

在你的适配器中,首先需要重写getItemViewType,例如:

@Override
public int getItemViewType(int position) 
{
    if (position % 5 == 0)
        return AD_TYPE; 
    return CONTENT_TYPE;
}

然后在onCreateViewHolder中,根据类型膨胀不同的视图。像这样的:

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) 
{
    View v = null;

    if (viewType == AD_TYPE)
    {
        v = new AdView(activity, AdSize.BANNER, ADMOB_ID);
        float density = activity.getResources().getDisplayMetrics().density;
        int height = Math.round(AdSize.BANNER.getHeight() * density);
        AbsListView.LayoutParams params = new AbsListView.LayoutParams(AbsListView.LayoutParams.FILL_PARENT,height);
        v.setLayoutParams(params);

     AdRequest adRequest = new AdRequest.Builder().build();
        if (adRequest != null && v != null){
            v.loadAd(adRequest);
         }
    }
    else 
        v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_item_layout, viewGroup, false);

    RecyclerView.ViewHolder viewHolder = new RecyclerView.ViewHolder(v);
    return viewHolder;
}

【讨论】:

  • ( position % 5 == 0 ) 更改视图类型将跳过该位置的实际项目对吗?
  • 不要忘记相应地更改 getItemCount():'return items_count + (items_count % 5)'
  • @nbtk 它应该是 item_count / 5 而不是 "%"
  • 我心中只有一个问题,可以在回收站视图中显示 admob 广告吗?我的意思是,在每 5 或 10 个项目间隔之后。它是否违反任何 admob 政策?
  • 这实际上会跳过项目。我测试了它,它确实如此。另外,您可以在 getItemViewType() 处获得 IndexOutOfBoundsException
【解决方案2】:

如何添加广告列表项不跳过内容项不向内容列表插入空项?? p>

private static final int LIST_AD_DELTA = 3;
private static final int CONTENT = 0;
private static final int AD = 1;

@Override
public int getItemViewType(int position) {
    if (position > 0 && position % LIST_AD_DELTA == 0) {
        return AD;
    }
    return CONTENT;
}

@Override
public BaseRecyclerHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    if (viewType == CONTENT) {
        return new ContentRecyclerHolder(parent, layoutId) {
            @Override
            protected void onCardClick(CardView card) {
                fragmentManager.showPagerFragmentWithTransition(card.getContext(), getRealPosition(getAdapterPosition()));
            }
        };
    } else {
        return new AdRecyclerHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_ad, parent, false));
    }
}

@Override
public int getItemCount() {
    int additionalContent = 0;
    if (data.size() > 0 && LIST_AD_DELTA > 0 && data.size() > LIST_AD_DELTA) {
        additionalContent = data.size() / LIST_AD_DELTA;
    }
    return data.size() + additionalContent;
}

@Override
public void onBindViewHolder(BaseRecyclerHolder baseHolder, int position) {
    if (getItemViewType(position) == CONTENT) {
        ContentRecyclerHolder holder = (ContentRecyclerHolder) baseHolder;
        Content content = data.get(getRealPosition(position));
    } else {
        AdRecyclerHolder holder = (AdRecyclerHolder) baseHolder;
            AdRequest adRequest = new AdRequest.Builder().build();
            if (adRequest != null && holder.adView != null){
                holder.adView.loadAd(adRequest);
             }
    }
}

private int getRealPosition(int position) {
    if (LIST_AD_DELTA == 0) {
        return position;
    } else {
        return position - position / LIST_AD_DELTA;
    }
}

【讨论】:

  • 效果很好,对于未来的读者,我建议将 BaseRecyclerHolder 替换为 RecyclerView.ViewHolder
  • @MartinDeSimone BaseRecyclerHolder 实际上是在我的项目中扩展了 RecyclerView.ViewHolder
  • 这会跳过一些内容。例如,如果 LIST_AD_DELTA = 3 并且您希望显示 8 个内容项,那么您的最后一行将是一个广告,因为(位置:9 % 3 = 0)。所以,只需将getItemCount()中获取additionalContent的公式改成:additionalContent = (data.size() + (data.size() / LIST_AD_DELTA)) / LIST_AD_DELTA;
  • getItemViewType 中获取 IndexOutOfBounds 异常
  • @RichardMcFriendOluwamuyiwa 确保您使用的是我的示例中的getItemViewType(没有此类异常的逻辑)或列表项计数> 0
【解决方案3】:

在您的 ArrayList 中,将空值添加到您要展示广告的位置

    for(int i=0;i<arr.size();i++){
       if(i%5==0)
       {
         alist.add(null);
       }
       alist.add(arr.get(i));
    }

然后在getItemViewType()中,

  @Override
public int getItemViewType(int position) {
   if(qlist.get(position)==null)
       return AD_TYPE;
   return CONTENT_TYPE;
}

那么,

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View v = null;
    ViewHolder vh=null;
    if (viewType == AD_TYPE)
    {
        v=inflater.inflate(R.layout.adview_item, parent, false);
        vh=new AdviewHolder(v);

    }
    else {
        v = inflater.inflate(R.layout.cardview_items, parent, false);
        vh = new ContentViewHolder(v);
    }
    return vh;
}

这不会跳过任何项目,但会在所需位置插入广告。

【讨论】:

  • 如果你使用gson来解析json呢
  • 在每个答案中,我的项目位置都错误。这个帮助我+1。 @kinsleykajiva 从服务器获取 json 后,您可以创建新的类实例并在其中添加此过滤器值
  • @kinsleykajiva 我已经在上面添加了关于改造 gson 的答案。
【解决方案4】:

我正在使用带有 gson 转换器的改造,并且需要在每 5 个项目之后显示广告。通过使用最重要的答案,我得到了错误的 item 位置。所以我在 json 响应中的每 5 个元素中插入自定义值。就像这样

call.enqueue(new Callback<List<DataModel>>() {
            @Override
            public void onResponse(Call<List<DataModel>> call, Response<List<DataModel>> response) {

                if (response.body() != null) {

                    List<DataModel> list_Data = response.body();
                    List<DataModel> list_ad_Data = new ArrayList<>();

                        for (int i = 0; i < list_Data.size(); i++) {
                            if (i %5 == 0 ){
                                list_ad_Data.add(null);
                            }
                                list_ad_Data.add(list_Data.get(i));
                        }

                        adapter = new HomeAdapter(getActivity(), list_ad_Data);

在我的适配器中。我已经根据

更改了视图类型
@Override
    public int getItemViewType(int position) {
        if (list_data.get(position) == null) {
            return AD;
        }
        return CONTENT;

    }

上面的答案中已经提到了更改视图类型。希望对以后的读者有所帮助。

【讨论】:

    【解决方案5】:

    像这样通过数据绑定加载广告更容易:

    @BindingAdapter({"bind:loadAds"})
    public static void loadAds(AdView adView, boolean load) {
        AdRequest adRequest = new AdRequest.Builder().build();
        adView.loadAd(adRequest);
    }
    

    然后在 xml 中添加这个 like 到 adView

            app:loadAds='@{true}'
    

    像这样:

      <com.google.android.gms.ads.AdView
            android:id="@+id/adView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            ads:adSize="BANNER"
            ads:adUnitId="ca-app-pub-3940256099942544/6300978111"
            app:loadAds='@{true}'
            />
    

    【讨论】:

    • 这将在用户每次尝试加载添加时创建一个新的添加请求(构建器)。
    • @AqsaShahid 我认为加载更多广告更好,因为用户更有可能点击并赚取更多钱。
    猜你喜欢
    • 2020-12-22
    • 1970-01-01
    • 2014-01-31
    • 1970-01-01
    • 1970-01-01
    • 2021-06-09
    • 1970-01-01
    • 2012-12-08
    相关资源
    最近更新 更多