【问题标题】:Showing Native Ads in RecyclerView在 RecyclerView 中显示原生广告
【发布时间】:2019-06-10 11:40:35
【问题描述】:

我正在使用 RecyclerView。其中我必须在 GridLayout Manager 中显示两个项目,并且跨度计数为 2 以显示全宽的原生广告。谁能帮帮我。

【问题讨论】:

  • 你好Sumit,你看过Adapter支持的RecyclerView Item Type了吗? developer.android.com/reference/android/support/v7/widget/… 您的适配器将为每 4 项广告提供一个容器。对于所有其他情况,它将返回正常视图。等等。
  • 我试图编辑评论,但过了一会儿就不行了;我忘了提到当前没有布局管理器会为您执行此操作,您必须扩展 GridLayoutManager 或......创建自己的。这不是“容易”的任务,所以要准备好承受很多痛苦(但这是可行的)。

标签: android android-layout ads native-ads


【解决方案1】:

我想我找到了可能对您有用的解决方案。我在这里使用 Kotlin,但我确信在 Java 中也可以实现。

假设

  • 您正在使用GridLayoutManager
  • 您希望每 N 个项目插入一个“广告”。
  • 您已经实现或有方法来确定您要显示的数据类型(又名:您根据 itemType 膨胀不同的“ViewHolders”。
  • 在不可变数据列表中插入占位符没有问题,因此您的 RecyclerView 适配器不会充满疯狂的逻辑,而且您的 GridLayout 也不必是自定义的。

如何?

  • 一个网格布局管理器,根据“跨度”的数量计算布局/度量(我在心理上将其称为列,即使这并不是真正的意思)。
  • 当您创建 GridLayoutManager 时,您会这样做,通过提供表示布局将 span 的跨度数(哈哈?)
  • 可以更改视图在网格中布局时的跨度数(?)跨度。默认情况下,视图将跨越一个跨度(span thingy 已经足够了)。

“跨度”这个词就够了……

假设您有一个List<Thing> 作为您的数据源。 你有 0..n 东西。 说Thing有通过Type来识别的意思。又名:aThing.type。 假设你有两种类型:

正常和 AD。

enum Type { Normal, AD }

(例如)。

所以你可以这样做:

if (thing.type == Type.AD)

现在我假设您从您的存储库中收到了Thing 的列表。

你有不同的选择(我只探索一个,其他的留给读者作为练习,主要是因为我没有那么多时间,而且每个最佳解决方案都会真的取决于上下文。我这里没有太多上下文)。我的要求很简单:让广告跨越所有网格。

一个简单的解决方案涉及改变存储库为您提供的结果列表(请注意,我不会接触存储库的数据,制作副本,将副本用于适配器)。

所以当你得到你的列表时,不要将它直接发送到适配器,而是修改它:

(这是伪代码,假设listOfData是你要显示的数据,当然已经填充了)

var newList = ArrayList<Thing>()

for ((index, thing) in listOfData.withIndex()) {
    // if it's an Ad, insert one, and continue adding items
    if (index % 4 == 0) {
        newList.add(AdPlaceholder())
    } else {
        newList.add(thing)
    }
}

return newList

所以我们根据原始列表返回一个 newList(这只是一种实现方式,不是唯一的,当然也不是所有情况下最好的,可能远不止眼前所见)。

AdPlaceholder() 是什么?

这只是一个专门的“东西”:)(见下文)。

现在在您的活动/片段中的某个地方,您可能会像这样设置您的回收站视图:(再次,伪代码,但有效的 Kotlin)

 override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        layoutManager = GridLayoutManager(this, 2)
        mainRecyclerView.layoutManager = layoutManager
        mainRecyclerView.adapter = YourAdapter()

        // and somewhere you'll send data to this adapter...
        adapter.submitList(repository.getMyListOfThings())
  }

这看起来像您的初始网格。

现在,起初,我想,如果我们创建一个自定义 LayoutManager,它可以“智能”了解何时显示广告等等。

但后来我发现有一个 value 被 GridLayoutManager 智能公开(并且它有效):

spanSizeLookup:设置源获取适配器中每个项目占用的span数。

这正是我们需要的,告诉 Grid:嘿,这个 item 占据了 N spans,但是这个 item 占据了 Y。

所以,我添加了这个:

layoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
    override fun getSpanSize(position: Int): Int {
        return when (adapter.getItemViewType(position)) {
            adapter.normalViewType -> 1
            adapter.adViewType -> 2
            else -> 1 //default
        }
    }
}

瞧!

由于要处理的内容很多,我创建了a sample project 来展示这一点。它有一个错误,希望你能发现它(并修复它!):)

注意我没有使用任何广告加载库,这取决于你。请记住,广告通常以 WebView 的形式实现,因此往往很慢、异步等。准备好在广告尚未加载时显示占位符等。 这真的取决于你如何实现这方面的事情,天空才是极限。这只是我为测试我的理论而构建的一个简单示例。

我个人认为这会更难;我证明自己错了。

祝你好运。

【讨论】:

    【解决方案2】:

    在活动中:

    StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
    recyclerView.setLayoutManager(layoutManager);
    recyclerView.setHasFixedSize(true);
    recyclerView.setAdapter(mAdapter);
    

    在您的回收站 OnCreateViewHolder 中:

    switch (viewType) {
    
           ...........      
    
           case TYPE_AD: {
                View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.AD_ITEM_LAYOUT, parent, false);
                final ViewGroup.LayoutParams lp = v.getLayoutParams();
                    if (lp instanceof StaggeredGridLayoutManager.LayoutParams){
                        StaggeredGridLayoutManager.LayoutParams sglp = (StaggeredGridLayoutManager.LayoutParams)lp;
                        sglp.setFullSpan(true);
                    }
                    return new AdViewHolder(v);
                }
    
           ...........
    
    }
    

    并在getItemViewType 方法中计算为 TYPE_AD 提供服务:

    @Override
        public int getItemViewType(int position) {
    
           .........
    
           if (position % 4 == 0){
              return TYPE_AD;
           }
    
           .........
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-09
      • 2021-10-02
      • 1970-01-01
      • 2021-10-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多