iOS直播:評(píng)論框與粒子系統(tǒng)點(diǎn)贊動(dòng)畫(huà)

本文始發(fā)于我的博文iOS直播:評(píng)論框與粒子系統(tǒng)點(diǎn)贊動(dòng)畫(huà)雳刺,現(xiàn)轉(zhuǎn)發(fā)至此掖桦。

目錄

  • 前言
  • 效果預(yù)覽
  • 評(píng)論框
    • 列表
    • 添加評(píng)論
    • 從下往上顯示
    • 支持昵稱(chēng)顏色
    • 給出NSAttributedString
  • 點(diǎn)贊動(dòng)畫(huà)

前言

最近做了直播功能枪汪,其實(shí)難度不是說(shuō)很大,主要是方案和SDK的選擇宿稀、整個(gè)直播流程的異常處理和優(yōu)化祝沸,還有第三方SDK的填坑越庇。不過(guò)本文只是記錄下評(píng)論框和點(diǎn)贊效果的實(shí)現(xiàn)卤唉,其他的是用第三方SDK,覺(jué)得沒(méi)什么好分享的竭恬,只是了解了直播流程和開(kāi)發(fā)中會(huì)遇到的問(wèn)題萍聊。
但看到效果還是蠻激動(dòng)和蠻有成就感的寿桨,這個(gè)主要是技術(shù)本身帶來(lái)的。

效果預(yù)覽

2016-07-31-ios-live-comment-praise-1.gif

評(píng)論框

細(xì)化需求:

  1. 顯示評(píng)論內(nèi)容
  2. 從下往上顯示
  3. 最大支持1000條
  4. 不同人昵稱(chēng)顯示顏色隨機(jī)分配,同一個(gè)人顏色保持不變墨微。
  5. 評(píng)論插入有動(dòng)畫(huà)

列表

  • 新的類(lèi)MessageChatView扁掸,對(duì)外接口add谴分。
func add(message: String) {}
  • 存放評(píng)論數(shù)組
private let maxMessageCount: Int = 1000
private var messages: [String] = []
  • UITableViewDelegate & UITableViewDataSource
extension MessageChatView: UITableViewDataSource {
    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return messages.count
    }
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1
    }
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {   
        ...
        return cell
    }
}
extension MessageChatView: UITableViewDelegate {
    func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        return ...
    }
    func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
        return 5.0
    }
}

此時(shí)顯示了數(shù)組里面的評(píng)論牺蹄,最多1000條沙兰。

添加評(píng)論

func add(message: String) {
    messages.insert(message, atIndex: 0)
    tableView.insertSections(NSIndexSet(index: 0), withRowAnimation: .Top)
    if messages.count > maxMessageCount {
        messages.removeLast()
        tableView.deleteSections(NSIndexSet(index: messages.count), withRowAnimation: .None)
    }
}

使用UITableView自帶的方法可以有動(dòng)畫(huà)效果鼎天。插入動(dòng)畫(huà)使用.Top斋射。

從下往上顯示

  • iOS在tableView和tableViewCell里調(diào)用下面語(yǔ)句:
tableView.transform = CGAffineTransformMakeScale (1,-1);
label.transform = CGAffineTransformMakeScale (1,-1);

兩條語(yǔ)句就可以實(shí)現(xiàn)了绩鸣。

  • Android可以調(diào)用ListView自帶的屬性stackFromBottom
android:stackFromBottom="true"

網(wǎng)上有文章將數(shù)據(jù) append到數(shù)據(jù)源纱兑,在獲取數(shù)據(jù)源時(shí)從后往前讀的方式(即messages.count-1-indexPath.section)潜慎,顯然插入在0位置比那樣更方便:insert(message, atIndex: 0)

支持昵稱(chēng)顏色

  • 使用NSAttributedString铐炫,且由外界設(shè)置。messages類(lèi)型改為NSAttributedString數(shù)組科贬。
private var messages: [NSAttributedString] = []
  • add改為NSAttributedString榜掌。
func add(message: NSAttributedString) {}
  • 設(shè)置Label的時(shí)候設(shè)置label.attributedText憎账。

給出NSAttributedString

  • 一個(gè)新的類(lèi)ChatColorText胞皱,對(duì)外接口colorText,參數(shù)nickName雾鬼、text于颖。
func colorText(nickName: String?, text: String?) -> NSAttributedString?{}
  • 隨機(jī)顏色數(shù)組森渐。
private var colors = [
    UIColor(hex: .RGB00AEFF)!,
    UIColor(hex: .RGB00A61C)!,
    UIColor(hex: .RGB5400E6)!,
    UIColor(hex: .RGBFF3377)!,
    UIColor(hex: .RGBFF8800)!,
    UIColor(hex: .RGBFF5E00)!,
    UIColor(hex: .RGBCA2EE6)!,
]
  • 記錄當(dāng)前取顏色的Index同衣,使得不同人給不同顏色。
private var colorIndex: Int = 0
  • 記錄昵稱(chēng)對(duì)應(yīng)的顏色值浪秘,保證同一個(gè)昵稱(chēng)同一種顏色耸携。
private var dicOfNameAndColor = [String: UIColor]()
  • 對(duì)外接口colorText實(shí)現(xiàn)夺衍。
func colorText(nickName: String?, text: String?) -> NSAttributedString? {
    guard let nickName = nickName, text = text else {return nil}
    let nickNameColor: UIColor = {
        if let color = dicOfNameAndColor[nickName] {
            return color
        }else {
            let color = colors[colorIndex]
            dicOfNameAndColor[nickName] = color
            colorIndex = (colorIndex + 1) % colors.count
            return color
        }
    }()
    let attributedString = NSAttributedString.attributedStringWithTextsAndColors([nickName, text], colors: [nickNameColor, UIColor(hex: .RGB333333)!])
    return attributedString
}

NSAttributedString.attributedStringWithTextsAndColors是自己擴(kuò)展的一個(gè)方法沟沙,傳入多串文字和對(duì)應(yīng)的字符返回匹配的NSAttributedString壁榕。

主要邏輯是:先判斷是否已經(jīng)有保存過(guò)昵稱(chēng)對(duì)應(yīng)的顏色值矛紫,有則直接返回;沒(méi)有則根據(jù)index獲取顏色值牌里,然后保存起來(lái)颊咬,并改變index

點(diǎn)贊動(dòng)畫(huà)

iOS自帶了粒子引擎的類(lèi)CAEmitterLayer,是一個(gè)粒子發(fā)射器系統(tǒng)喳篇,每個(gè)粒子都是CAEmitterCell的實(shí)例缓呛。可以查看它們分別有什么屬性杭隙。

有兩個(gè)小點(diǎn)哟绊,一個(gè)是CAEmitterLayer一些屬性對(duì)CAEmitterCell有成倍作用痰憎,如birthRate票髓;另一個(gè)是沒(méi)有明確的停止動(dòng)畫(huà)的方法,包括它的父類(lèi)也沒(méi)提供铣耘∏⒐担可以想到的方法,除了把layer抹除掉之外蜗细,還可以將CAEmitterLayerbirthRate設(shè)置為0裆操,這樣每個(gè)CAEmitterCell的誕生速率都為0,就不會(huì)有動(dòng)畫(huà)了炉媒。

class PraiseEmitterView: UIView {

    private var timer: NSTimer?
    private let emitter: CAEmitterLayer! = {
        let emitter = CAEmitterLayer()
        return emitter
    }()
    override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
    }
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()
    }
    private func setup() {
        emitter.frame = bounds
        emitter.birthRate = 0
        emitter.emitterShape = kCAEmitterLayerLine
        emitter.emitterPosition = CGPointMake(0,CGRectGetHeight(bounds))
        emitter.emitterSize = bounds.size
        emitter.emitterCells = [getEmitterCell(UIImage(named: "comment")!.CGImage!), getEmitterCell(UIImage(named: "flower_15")!.CGImage!)]
        self.layer.addSublayer(emitter)
    }
    func timeoutSelector() {
        emitter.birthRate = 0
    }
    func emit() {
        emitter.birthRate = 2
        timer?.invalidate()
        timer = NSTimer.scheduledTimerWithTimeInterval(2, target: self, selector: #selector(timeoutSelector), userInfo: nil, repeats: false)
    }
    private func getEmitterCell(contentImage: CGImage) -> CAEmitterCell {

        let emitterCell = CAEmitterCell()
        emitterCell.contents = contentImage
        emitterCell.lifetime = 2
        emitterCell.birthRate = 2

        emitterCell.yAcceleration = -70.0
        emitterCell.xAcceleration = 0
        
        emitterCell.velocity = 20.0
        emitterCell.velocityRange = 200.0
        
        emitterCell.emissionLongitude = CGFloat(0)
        emitterCell.emissionRange = CGFloat(M_PI_4)
        
        emitterCell.scale = 0.8
        emitterCell.scaleRange = 0.8
        emitterCell.scaleSpeed = -0.15
        
        emitterCell.alphaRange = 0.75
        emitterCell.alphaSpeed = -0.15

        return emitterCell
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末踪区,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子吊骤,更是在濱河造成了極大的恐慌缎岗,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件白粉,死亡現(xiàn)場(chǎng)離奇詭異传泊,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)鸭巴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)眷细,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人鹃祖,你說(shuō)我怎么就攤上這事溪椎。” “怎么了惯豆?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵池磁,是天一觀的道長(zhǎng)奔害。 經(jīng)常有香客問(wèn)我楷兽,道長(zhǎng),這世上最難降的妖魔是什么华临? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任芯杀,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘揭厚。我一直安慰自己却特,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布筛圆。 她就那樣靜靜地躺著裂明,像睡著了一般。 火紅的嫁衣襯著肌膚如雪太援。 梳的紋絲不亂的頭發(fā)上闽晦,一...
    開(kāi)封第一講書(shū)人閱讀 51,370評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音提岔,去河邊找鬼仙蛉。 笑死,一個(gè)胖子當(dāng)著我的面吹牛碱蒙,可吹牛的內(nèi)容都是我干的荠瘪。 我是一名探鬼主播,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼赛惩,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼哀墓!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起喷兼,我...
    開(kāi)封第一講書(shū)人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤麸祷,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后褒搔,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體阶牍,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年星瘾,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了走孽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡琳状,死狀恐怖磕瓷,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情念逞,我是刑警寧澤困食,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站翎承,受9級(jí)特大地震影響硕盹,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜叨咖,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一瘩例、第九天 我趴在偏房一處隱蔽的房頂上張望啊胶。 院中可真熱鬧,春花似錦垛贤、人聲如沸焰坪。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)某饰。三九已至,卻和暖如春善绎,著一層夾襖步出監(jiān)牢的瞬間露乏,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工涂邀, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留瘟仿,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓比勉,卻偏偏與公主長(zhǎng)得像劳较,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子浩聋,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

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