如何在集合视图中显示广告
Posted
技术标签:
【中文标题】如何在集合视图中显示广告【英文标题】:How to display ads within a collection view 【发布时间】:2017-03-28 06:37:48 【问题描述】:我正在尝试在我的 collectionView 中随机添加一些横幅广告。
每个 collectionView 单元格都将是一个基本图像(这里是黑色方块以使事情更容易)从我从网络上获取的数组(假设它是一个非常长的数组并称之为“longDataArray”)动态填充。
我可以设法向我的 collectionView 添加一些横幅广告,但问题是它破坏了我的 longDataArray 的顺序。 例如,仅用于测试当我在 indexPath 6 处添加广告横幅时,广告横幅在 indexPath 6 处正确显示,并且我能够管理单元格的宽度更改,但是 我的 longDataArray 在 indexPath 6 处对应的图像显然永远不会出现。
我也可以将我的 longDataArray 分成两部分,然后使用这些部分:部分 0 = firstPartOfArray,部分 1 = 广告横幅,部分 2 = secondPartOfArray。但这需要花费大量精力来创建不同的数组和部分,只添加一个广告横幅,这显然不是我想要的。
所以我的问题是,如何在 collectionView 中添加横幅广告(只有一个部分),但保留 indexPath 逻辑?
我在谷歌上搜索了很多关于这个问题的信息,但很惊讶我无法为这个问题想出任何解决方案。
你们有什么想法吗?
谢谢!
【问题讨论】:
您使用的是表格视图还是集合视图?您的标题与内容不符。 对不起,我打错了,我的意思是collectionView,但无论您使用collectionView还是tableView,概念基本相同,我希望广告横幅出现在collectionView(或tableView)中随机(不仅是banner的位置,还有banner的数量)而不破坏indexPath的逻辑 我不会为广告创建另一个部分,而是将其插入到数组中的实际数据之间并添加某种标志来识别它(例如,theActualDataForACell[@"is_ad"] = @YES;
然后if ( [dataForCell[@"is_ad"] boolValue] ) /* this is an ad */
,您可以在 UICollectionViewDelegateFlowLayout
协议的 collectionView:layout:sizeForItemAtIndexPath:
方法中定义特定单元格的大小...或者您可以创建另一个单元格原型并在适当时将广告出列。
这里也一样,你找到优雅的解决方案了吗?
@armnotstrong 我认为 AlejandroIván 解决方案很简单,也是最好用的解决方案。您只需在随机位置添加一个特殊对象(由于显示的布局,可能需要至少是 3 的倍数,但这应该很容易。
【参考方案1】:
对于UICollectionView
,您必须自定义两个UICollectionView
-
Cell1 用于
Imageview
。
Cell2 用于横幅广告。
在cellForItem
if (indexPath.item == 6)
// dequeue your cell2 here
return cell2
else
// dequeue your cell1 here
return cell1
实现UICollectionViewDelegateFlowLayout并像这样使用
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize
if (indexPath.item == 6)
return CGSizeMake(60,60)
else
return CGSizeMake([[UIScreen mainScreen] bounds].size.width, 60.0)
要在您的应用中展示广告,请AdMob
【讨论】:
感谢您的回复@agent_stack,但是,如果我这样构建它,问题是我将不得不拆分我的数据,这不是我想要的(我的数据将动态增长并且将很大) 如果您有任何想法,我正在寻找一种不会改变我的数据和 indexPath 逻辑的解决方案? @jellyfish6 您的用户界面实际上是如何显示的,您可以告诉我,以便我可以相应地提出建议。请描述您拥有的数据类型以及您在集合视图中显示的内容 再次感谢您的快速回复!在这个屏幕上,用户将能够看到他们朋友分享的所有照片。所以基本上我的 dataArray 将包含在一个结构数组中,我的 dataArray = [PhotoStruct] 并且每个 PhotoStruct 都由一个 photoImageURL、一个 photoAuthor 和一个 photoTime 组成,我将抓取并使用它们来填充 collectionView。 每个集合单元格将包含照片图像(完整单元格大小),底部的作者标签和顶部的时间标签。【参考方案2】:您好,我在表格单元格中创建了一个具有相同要求的 collectionView,您可以查看我的代码。
//
// ViewController.swift
// DemoApp
//
// Created by Mahesh Kumar on 09/01/18.
// Copyright © 2018 Mahesh Kumar. All rights reserved.
import UIKit
class TableCell : UITableViewCell
@IBOutlet weak var collVw: UICollectionView!
@IBOutlet weak var categoryName: UILabel!
class ViewController: UIViewController, UICollectionViewDelegate,UICollectionViewDataSource , UICollectionViewDelegateFlowLayout , UITableViewDelegate,UITableViewDataSource
var categories_array = ["Home","Helth","New","Home1","Home2","Home3","Home4","Home5","Home6","Home7","Home8","Home9","Home11","Home12","Home13","Home14","Home15"]
//Mark
var sectionArray = NSMutableArray()
@IBOutlet weak var tableVw: UITableView!
override func viewDidLoad()
super.viewDidLoad()
//Mark
var sectionCount = 0
var mainIndex = 0
let section = categories_array.count % 4
if(section == 0)
sectionCount = categories_array.count/4
else
sectionCount = categories_array.count/4 + 1
//Mark
for _ in 0...sectionCount
let rowsData = NSMutableArray()
var j = 0
while j<4
if(mainIndex == categories_array.count)
break
rowsData.add(categories_array[mainIndex])
j = j + 1
mainIndex = mainIndex + 1
sectionArray.add(rowsData)
tableVw.reloadData()
// Do any additional setup after loading the view, typically from a nib.
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return 3
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = tableVw.dequeueReusableCell(withIdentifier: "cell1", for: indexPath) as? TableCell
if(indexPath.row == 1)
cell?.categoryName.text = "Top Redeemed"
else if(indexPath.row == 2)
cell?.categoryName.text = "Categories"
cell?.collVw.tag = indexPath.row
cell?.collVw.delegate = self
cell?.collVw.dataSource = self
cell?.collVw.reloadData()
return cell!
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
return 400
func numberOfSections(in collectionView: UICollectionView) -> Int
if(collectionView.tag == 0)
return 1
else if(collectionView.tag == 1)
if(categories_array.count > 4)
if(categories_array.count % 4 == 0)
return categories_array.count/4
else
return (categories_array.count/4) + 1
else
return 1
else
return 10
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
cell.backgroundColor = UIColor.green
if let lbl = cell.viewWithTag(1) as? UILabel
lbl.text = "\(indexPath.row)"
return cell
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
if(collectionView.tag == 0)
return CGSize.init(width: collectionView.frame.width - 10, height: collectionView.frame.height)
else if(collectionView.tag == 1)
return CGSize.init(width: (collectionView.frame.width)/2 - 5.5, height: collectionView.frame.height/2 - 0.5)
else
return CGSize.init(width: collectionView.frame.width/3 - 4, height: collectionView.frame.height/2 - 0.5)
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat
if(collectionView.tag == 0)
return 10
else
return 1
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets
return UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
if(collectionView.tag == 0)
return 10
else if(collectionView.tag == 1)
return ((sectionArray[section] as? NSMutableArray)?.count)!
else
return 6
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath)
print("coll vw",indexPath.row)
print(indexPath.section)
//Mark
if(collectionView.tag == 1)
print(collectionView.tag)
let array = sectionArray[indexPath.section] as? NSMutableArray
print(array![indexPath.row])
【讨论】:
请添加此代码,它会创建一个三部分,一是广告横幅,二和三是类别,用户可以水平和垂直滚动。如果有效,请接受我的回答。【参考方案3】:所以我的问题是,你将如何在你的 collectionView 中添加横幅广告(只有一个部分),但保留 indexPath 逻辑?
您只需调整索引路径以考虑广告。例如,假设您希望每 15 个单元格包含一个广告。让我们在这里使用基于 1 的算术来使数学更直观。单元格 1-14 将获得它们的常规内容,单元格 15 将有一个广告,单元格 16-29 将获得项目 15-28 的内容,单元格 30 将获得另一个广告,依此类推。因此,您的 -collectionView:cellForItemAtIndexPath:
方法需要确定索引路径是指广告单元格(在这种情况下,从 1 开始的项目编号可以被 15 整除)还是内容单元格(每隔一个单元格)。在后一种情况下,它还需要调整项目编号以获得正确的内容。
NSInteger item = indexPath.item + 1; // switch to 1-based numbering
if (item % 15 == 0)
// we have an ad cell, so return a cell configured with an ad
else
item = item - (item / 15); // subtract the ad cells
item -= 1; // switch back to 0-based indexes
// return a cell configured with the data at index `item`
您还必须在其他处理单元格的方法中进行相应的计算,例如-collectionView:numberOfItemsInSection:
。因此,编写一些可以进行调整的实用方法可能是一个好主意。
【讨论】:
嗨@Caleb,感谢您的详细回答!我没有想到这一点,但是,这很有意义!使用它,我可以跟踪我的原始 indexPath 并相应地获取数据。但是,在我在问题中提出的随机广告展示位置(并非总是每 15 个单元格)的情况下,您将如何使其工作?您将如何跟踪这种随机性?你能解释一下吗 如果您随机放置广告,则无法使用公式计算索引。我认为在这种情况下,我会保留一个广告位置列表,然后使用该列表来计算差异。例如,如果您有一个像[13, 27, 43, 58, 71]
这样的广告位置列表,那么每次填充一个单元格时,您都需要查看该列表并确定该单元格之前有多少广告。如果您正在填充单元格 #30,则查看列表并看到有两个广告
另一种方法:在您的数据中插入广告占位符。只需将一种新的项目添加到您正在管理的项目列表中,并让您的代码在大多数情况下忽略这些项目。这样可以避免进行数学运算来调整项目索引,但可能会使代码的其他部分复杂化。【参考方案4】:
我们成功地为这个问题与 Ersin 开发了一个示例。
你可以在这里查看。
https://github.com/Cemoo/WaterFlowLayout
【讨论】:
以上是关于如何在集合视图中显示广告的主要内容,如果未能解决你的问题,请参考以下文章
如果集合视图嵌入到 ios 的表视图中,如何始终显示集合视图的第一项
如何在集合视图中从数组显示项目到特定的 indexPath [关闭]