iOS 浮層廣告拖動(dòng)問題

筆者性懶,腹中無墨
關(guān)于簡單的可拖動(dòng)的頁面浮層廣告,可以用addSubview實(shí)現(xiàn).遵循MVC設(shè)計(jì)模式,subview分離出來.筆者的思路是在自定義的view上放一個(gè)UIImageView,沒有直接加UIImageView.由于浮層廣告可以是動(dòng)圖,所以需要支持動(dòng)圖的一個(gè)三方的庫FLAnimatedImage.GitHub源碼:https://github.com/Flipboard/FLAnimatedImage.當(dāng)然,SDWebImage在4.0版本之后,加入了依賴FLAnimatedImage,支持動(dòng)圖.共同點(diǎn)都是原來的UIImageView都需要換成FLAnimatedImageView.

SDWebImage新增動(dòng)圖支持.png
測試截圖.png

簡要概括為以下幾個(gè)步驟
1.廣告的拖動(dòng)手勢
給UIView上的FLAnimatedImageView添加輕觸Tap和拖動(dòng)Pan手勢,點(diǎn)擊跳轉(zhuǎn)廣告的URL鏈接,拖動(dòng)改變廣告在俯視圖中的位置,一般浮層廣告frame較小.根據(jù)需求可能會(huì)有拖動(dòng)范圍的限制,例如導(dǎo)航欄以下,tabbar之上.iPhone X就需要考慮尺寸問題,所以需要考慮距頂部距底部的高度.

    /* 廣告拖動(dòng)手勢 */
@objc fileprivate func panAdvertise(ges: UIPanGestureRecognizer) {
    var startPoint: CGPoint = CGPoint.zero
    switch ges.state {
        
    case .began:
        startPoint = ges.location(in: superView)
        UIView.animate(withDuration: 0.2, animations: {
            self.transform = CGAffineTransform(scaleX: 1.1, y: 1.1)
            self.alpha = 0.7
        })
        
    case .changed:
        let newPoint: CGPoint = ges.location(in: superView)

        //由于測試圖片是方形,所以圖片在邊界時(shí)的中心點(diǎn)距離邊界圖片尺寸的1/2
        let imageHeight = advertiseImage.frame.size.height*0.5

        //為了方便,將浮層的superview是作為參數(shù)傳入
        let superFrameW = superView.frame.size.width
        let superFrameH = superView.frame.size.height

        var deltaX: CGFloat = 0
        var deltaY: CGFloat = 0
        deltaX = newPoint.x - startPoint.x
        deltaY = newPoint.y - startPoint.y
        
        //左邊界
        if newPoint.x < superView.frame.origin.x + imageHeight {
            deltaX = imageHeight
        }
        //右邊界
        if newPoint.x > superFrameW - imageHeight {
            deltaX = superFrameW - imageHeight
        }
        //上邊界
        if newPoint.y < topHeight + imageHeight  {
            deltaY = imageHeight + topHeight
        }
        //下邊界
        if newPoint.y > superFrameH - topHeight {
            deltaY = superFrameH - bottomHeight - imageHeight
        }
        
        self.center = CGPoint(x: deltaX, y: deltaY)
        
    case .ended, .cancelled, .failed:
        
        UIView.animate(withDuration: 0.2, animations: {
            self.transform = CGAffineTransform.identity
            self.alpha = 1.0
        })
        
    case .possible:
        break
    }
}

2.獲取廣告數(shù)據(jù)并展示廣告

/*
 獲取廣告基本數(shù)據(jù)
 這里的廣告數(shù)據(jù) advertises 并沒有區(qū)分動(dòng)圖或者圖片,只是獲得了廣告展示位的基本信息,類似title,url等
 var advertises = [Advertise]()  這里的結(jié)構(gòu)體類型Advertise根據(jù)需求定義
 */
fileprivate func getAdvertises() {
    ADSuspendService.shared.getSuspendAdvertise({ (advertises) in

        //advertises是廣告結(jié)構(gòu)體類型的數(shù)組
        self.advertises = advertises

        if advertises.count > 0 {
           //根據(jù)廣告的基本信息,獲取圖片或者動(dòng)圖
           self.getSuspendImage()
            self.addSubview(self.advertiseImage)
            self.advertiseImage.snp.makeConstraints { (make) in
                make.left.right.top.bottom.equalTo(self)
            }
        }
    })
}

// 根據(jù)廣告類型 展示廣告
fileprivate func getSuspendImage() {
    /*currentIndex表示當(dāng)前展示的第幾個(gè)浮層廣告,由于需求是一定的時(shí)間間隔切換浮層廣告,所以需要記錄每次展示的廣告,無需求可忽略*/
    if let url = advertises[currentIndex].url {
        self.getFLAnimatedImage(from: url, callback: { (img) in
            DispatchQueue.main.async {
                if ((img as? UIImage) != nil) {
                    self.advertiseImage.image = img as? UIImage
                    self.advertiseImage.animatedImage = nil
                }else if (img as? FLAnimatedImage) != nil {
                    self.advertiseImage.animatedImage = img as? FLAnimatedImage
                }
                /* 統(tǒng)計(jì)浮層廣告曝光,根據(jù)需求是否統(tǒng)計(jì)*/
                var event:NativeClickEvent 
                event = event_ad_show
                event.areaLabelName = self.advertises[self.currentIndex].spot
                event.desc = self.advertises[self.currentIndex].adId
                EventTracker.trackNativeClickEvent(event: event)
            }
        })
    }
}

//獲取廣告類型
fileprivate func getFLAnimatedImage(from url: String, callback: @escaping (Any?) -> Void) {
    
    guard let urlObj = URL(string: url) else {
        callback(nil)
        return
    }
    //CachedResourceManager是自己的緩存管理器,根據(jù)url有緩存則不在請求,類似的可以使用邊便捷的SDWebImage的方法,關(guān)于CachedResourceManager這里就不在贅述.
    let cacheManager = CachedResourceManager()
    cacheManager.downloadResource(urlObj, forceCaching: true) { (data) in
        
        if let data = data, let image = FLAnimatedImage(gifData: data) { // Gif
            callback(image)
        }else if let data = data, let image = UIImage(data: data, scale: UIScreen.main.scale) { // jpg/png
            callback(image)
        }else {
            callback(nil)
        }
    }
}

3.關(guān)于計(jì)時(shí)器

//TODO: - 測試間隔10秒鐘
func startTimer() {
    //這個(gè)時(shí)間可以是離開浮層廣告頁面的時(shí)間.或者根據(jù)需求,記錄就可以
    if let last = ADSuspendService.shared.lastedADShownDate {
        let minute = Date().timeIntervalSince(last) 
        if minute >= 10 && advertises.count > 1 {
            if currentIndex < advertises.count - 1 {
                currentIndex += 1
            } else {
                currentIndex = 0
            }
            self.getSuspendImage()
        }
    } else {
        // 若未超過10分鐘,則會(huì)從零計(jì)時(shí),啟動(dòng)計(jì)時(shí)器,到10分鐘才換廣告
    }
    
    if advertises.count > 1 {
        timer = Timer.scheduledTimer(timeInterval: 10, target: self, selector: #selector(changeImage), userInfo: nil, repeats: true)
    }
}
func changeImage() {
    if currentIndex < advertises.count - 1 {
        currentIndex += 1
    } else {
        currentIndex = 0
    }
    getSuspendImage()
}

4.初始化view

init(frame: CGRect, top: CGFloat, bottom: CGFloat) {
    super.init(frame: frame)
    topHeight = top
    bottomHeight = bottom

    DispatchQueue.global().async {
        self.getAdvertises()
        self.startTimer()
    }
}

5.廣告的點(diǎn)擊跳轉(zhuǎn)及統(tǒng)計(jì)就不再贅述,離開浮層頁需要移除定時(shí)器,回到該頁面需要再次開啟定時(shí)器.

func removeTimer() {
    timer?.invalidate()
    timer = nil
}

deinit {
    timer?.invalidate()
    timer = nil
}

6.Controller里

fileprivate func suspendAdvertiseShow() {
    adView = AdvertiseSuspendView(frame: CGRect.zero, top: (navigationController?.navigationBar.frame.size.height)! + UIApplication.shared.statusBarFrame.size.height, bottom: (tabBarController?.tabBar.frame.size.height)!)
    adView.superView = view
    scrollContentView.addSubview(adView)
    adView.snp.makeConstraints { (make) in
        make.trailing.equalTo(networkPanel).offset(-15)
        make.bottom.equalTo(networkPanel).offset(-15)
        make.size.equalTo(kScreenWidth*0.16)
    }
    
    adView.advertiseTapHandler = { url in
        self.clickAdvertiseHandler(url: url)
    }
}

最后,浮層廣告的曝光量和點(diǎn)擊量應(yīng)該是運(yùn)營考慮的重點(diǎn),埋點(diǎn)統(tǒng)計(jì)工作要做到.end.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市淑玫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌敞映,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,294評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件次兆,死亡現(xiàn)場離奇詭異蔑鹦,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)蔬胯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,493評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來位他,“玉大人氛濒,你說我怎么就攤上這事《焖瑁” “怎么了舞竿?”我有些...
    開封第一講書人閱讀 157,790評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長窿冯。 經(jīng)常有香客問我骗奖,道長,這世上最難降的妖魔是什么醒串? 我笑而不...
    開封第一講書人閱讀 56,595評論 1 284
  • 正文 為了忘掉前任重归,我火速辦了婚禮,結(jié)果婚禮上厦凤,老公的妹妹穿的比我還像新娘。我一直安慰自己育苟,他們只是感情好较鼓,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,718評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著违柏,像睡著了一般博烂。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上漱竖,一...
    開封第一講書人閱讀 49,906評論 1 290
  • 那天禽篱,我揣著相機(jī)與錄音,去河邊找鬼馍惹。 笑死躺率,一個(gè)胖子當(dāng)著我的面吹牛玛界,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播悼吱,決...
    沈念sama閱讀 39,053評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼慎框,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了后添?” 一聲冷哼從身側(cè)響起笨枯,我...
    開封第一講書人閱讀 37,797評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎遇西,沒想到半個(gè)月后馅精,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,250評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡粱檀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,570評論 2 327
  • 正文 我和宋清朗相戀三年洲敢,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片梧税。...
    茶點(diǎn)故事閱讀 38,711評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡沦疾,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出第队,到底是詐尸還是另有隱情哮塞,我是刑警寧澤,帶...
    沈念sama閱讀 34,388評論 4 332
  • 正文 年R本政府宣布凳谦,位于F島的核電站忆畅,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏尸执。R本人自食惡果不足惜家凯,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,018評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望如失。 院中可真熱鬧绊诲,春花似錦、人聲如沸褪贵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,796評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽脆丁。三九已至世舰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間槽卫,已是汗流浹背跟压。 一陣腳步聲響...
    開封第一講書人閱讀 32,023評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留歼培,地道東北人震蒋。 一個(gè)月前我還...
    沈念sama閱讀 46,461評論 2 360
  • 正文 我出身青樓茸塞,卻偏偏與公主長得像,于是被迫代替她去往敵國和親喷好。 傳聞我的和親對象是個(gè)殘疾皇子翔横,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,595評論 2 350

推薦閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件梗搅、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,066評論 4 62
  • Swift版本點(diǎn)擊這里歡迎加入QQ群交流: 594119878最新更新日期:18-09-17 About A cu...
    ylgwhyh閱讀 25,337評論 7 249
  • 隨著自己年齡的增長,我發(fā)現(xiàn)人的性格缺陷一旦形成哆键,要做改變是超級難的一件事情掘托。 而更讓人感到悲劇的是這種缺陷往往是向...
    野望者閱讀 148評論 0 1
  • 我想和你一起生活 在海邊的某座小城 共享無盡的黃昏 和綿綿不絕的濤聲 我們可以漫步在小城的碼頭 看歸航的漁船 挑撿...
    足下阿蒙閱讀 194評論 0 1