我正在和RecyclerView一起工作。其中我必须在GridLayout管理器中显示两个项目,跨度计数为2才能以全宽显示原生广告。有人能帮我吗。


发布于 2019-06-10 23:16:20
我想我已经找到了一个可能对你有效的解决方案。我在这里使用的是Kotlin,但我相信在Java中也可以做到这一点。
假设
GridLayoutManager
多么?
别再用“跨度”这个词了..。
假设您有一个List<Thing>作为数据源。你有0..n个东西。所述Thing具有通过类型来标识的手段。又名:aThing.type。假设你有两种类型:
正常和AD。
enum Type { Normal, AD }(例如)。
所以你可以这样做:
if (thing.type == Type.AD)现在,我假设您从存储库收到了一份Thing列表。
您有不同的选择(我将只探索一个,并将其他选项留给读者作为练习,主要是因为我没有那么多时间,但也因为每个最佳解决方案都将真正取决于上下文。我在这里没有太多的上下文)。我的要求很简单:让广告跨越所有网格。
一个简单的解决方案是修改Repository提供给您的结果列表(注意,我不会接触repo的数据,创建一个副本,将副本用于您的适配器)。
因此,当您获得列表时,请修改它,而不是直接将其发送到适配器:
(这是伪代码,假设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,它是关于何时显示广告和诸如此类的“智能”。
但后来我发现,GridLayoutManager智能地公开了一个值(并且它是有效的):
spanSizeLookup:设置来源以获取适配器中每个项目占用的跨度数。
这正是我们需要的,告诉网格:嘿,这一项占用N个跨度,而另一项占用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来实际展示这一点。它有一个bug,希望你能发现它(并修复它!) :)
请注意,我没有使用任何AD加载库,这取决于您。请记住,广告通常是作为WebViews实现的,因此往往是缓慢的,异步的,等等。准备好在广告尚未加载时显示占位符,等等。这将真的取决于你如何实现这一方面的事情,天空是限制。这只是我构建的一个简单的样本来验证我的理论。
我个人认为这会更难;我证明了自己是错的。
祝好运。
发布于 2021-04-25 13:56:07
在活动中:
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方式对serving TYPE_AD进行计算:
@Override
public int getItemViewType(int position) {
.........
if (position % 4 == 0){
return TYPE_AD;
}
.........
}https://stackoverflow.com/questions/56525682
复制相似问题