I'm trying to add some banner ads randomly inside my collectionView.
Each collectionView cell would be a basic image (black square here to make things easier) populated dynamically from an array (let's say it's a really long array and call it "longDataArray") that I would get from the web.
I could manage to add some banner ads to my collectionView but the problem is that it's breaking the order of my longDataArray. For example, just for testing when I'm adding an ad banner at indexPath 6, then the ad banner correctly shows up at indexPath 6, and I'm able to manage the width change for the cell, but the image corresponding at the indexPath 6 for my longDataArray would obviously never appears.
I also could do it spliting my longDataArray in two, and then playing with the sections : section 0 = firstPartOfArray, section 1 = ad banner, and section 2 = secondPartOfArray. But this takes a lot of effort creating differents arrays and sections, just to add only one ad banner, and it's obviously not what I'm looking for.
So my question is, how would you add banner ad within your collectionView (only one section), but keeping the indexPath logic ?
I googled a lot about that, and was surprised that I could not come up with any solution for this problem.
Do you guys have any idea ?
Thanks!
Hi I have created a collectionView inside the table cell with same requirement, You can check my code.
//
// 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])
}
}
}
So my question is, how would you add banner ad within your collectionView (only one section), but keeping the indexPath logic ?
You just need to adjust the index path to account for the ads. For example, let's say that you want every 15th cell to contain an ad. Let's use 1-based arithmetic here to make the math intuitive. Cells 1-14 will just get their regular content, cell 15 will have an ad, cells 16-29 will get the content for items 15-28, cell 30 will get another ad, and so on. So, your -collectionView:cellForItemAtIndexPath:
method would need to figure out whether the index path refers to an ad cell (in which case the 1-based item number is evenly divisible by 15) or a content cell (every other cell). In the latter case, it'd also need to adjust the item number to get the right content.
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`
}
You'd also have to do corresponding calculations in other methods that deal with cells, such as -collectionView:numberOfItemsInSection:
. For that reason, it'd probably be a good idea to write some utility methods that would make the adjustments.
For UICollectionView
you have to two custom UICollectionView
- Cell1 is for the
Imageview
. - Cell2 is for the the banner ad.
In cellForItem
if (indexPath.item == 6){
// dequeue your cell2 here
return cell2
}
else{
// dequeue your cell1 here
return cell1
}
Implement UICollectionViewDelegateFlowLayout and use like this
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)
}
}
To display ad in your app, you AdMob
We succeeded that developed an example for with Ersin for this issue.
You can check it out here.
来源:https://stackoverflow.com/questions/43062278/how-to-display-ads-within-a-collection-view