直播項(xiàng)目筆記(一)

顏色封裝 + ClOPageView + 瀑布流

搭建主題框架

導(dǎo)航欄布局

  • 改變導(dǎo)航欄的顏色
// 在 AppDelegate 中
UINavigationBar.appearance().barTintColor = .black  // tintColor 是導(dǎo)航欄文字的顏色
  • 改變狀態(tài)欄的顏色
// 蘋果推薦方法 在需要設(shè)置頁面 controller 中
override var preferredStatusBarStyle: UIStatusBarStyle {
        return .lightContent // 默認(rèn)為白色
    }
// or
// 在 info.plist 中 設(shè)置
View controller-based status bar appearance 設(shè)置為 NO // 全局
// 在 AppDelegate 中
UIApplication.shared.statusBarStyle = .lightContent
// or

設(shè)置首頁 NavigationBar 注意事項(xiàng)

  • 如果事件監(jiān)聽方法為私有時(shí) 要在方法前面加 @objc 公開則不需要
// 事件監(jiān)聽 --> 發(fā)送消息 --> 將方法包裝SEL  --> 類方法列表 --> IMP

顏色封裝 :UIColor + Extension

  • 拓展方法如果有參數(shù) 采用便利構(gòu)造函數(shù)
// 自定義 RGB 顏色
convenience init(r : CGFloat, g : CGFloat, b : CGFloat, alpha : CGFloat = 1.0) {
        self.init(red: r / 255.0, green: g / 255.0, blue: b / 255.0, alpha: alpha)
} 
// 返回一個(gè)十六進(jìn)制顏色
convenience init?(hex : String, alpha : CGFloat = 1.0) {
        
        // 0xff0000
        // 1.判斷字符串的長度是否符合
        guard hex.characters.count >= 6 else {
            return nil
        }
        
        // 2.將字符串轉(zhuǎn)成大寫
        var tempHex = hex.uppercased()
        
        // 3.判斷開頭: 0x/#/##
        if tempHex.hasPrefix("0x") || tempHex.hasPrefix("##") {
            tempHex = (tempHex as NSString).substring(from: 2)
        }
        if tempHex.hasPrefix("#") {
            tempHex = (tempHex as NSString).substring(from: 1)
        }
        
        // 4.分別取出RGB
        // FF --> 255
        var range = NSRange(location: 0, length: 2)
        let rHex = (tempHex as NSString).substring(with: range)
        range.location = 2
        let gHex = (tempHex as NSString).substring(with: range)
        range.location = 4
        let bHex = (tempHex as NSString).substring(with: range)
        
        // 5.將十六進(jìn)制轉(zhuǎn)成數(shù)字 emoji表情
        var r : UInt32 = 0, g : UInt32 = 0, b : UInt32 = 0
        Scanner(string: rHex).scanHexInt32(&r)
        Scanner(string: gHex).scanHexInt32(&g)
        Scanner(string: bHex).scanHexInt32(&b)
        
        self.init(r : CGFloat(r), g : CGFloat(g), b : CGFloat(b))
}
  • 沒有參數(shù)的擴(kuò)展方法 用類方法
/// 隨機(jī)顏色
class func randomColor() -> UIColor {
        return UIColor(r: CGFloat(arc4random_uniform(256)), g: CGFloat(arc4random_uniform(256)), b: CGFloat(arc4random_uniform(256)))
}

封裝 CLOPageView

  • 類似網(wǎng)易新聞 titleView(UIScrollView) + contentView(UICollectionView)

  • 結(jié)構(gòu)視圖


  • 如果類中的屬性沒有初始化赃春,要在創(chuàng)建對象super.init()前賦值 否則會報(bào)錯

// MARK: - 定義屬性
    fileprivate var titles: [String]
    fileprivate var titleStyle: CLOPageStyle
    fileprivate var childVcs: [UIViewController]
    fileprivate var parentVc: UIViewController
    
    init(frame: CGRect, titles: [String], titleStyle: CLOPageStyle, childVcs: [UIViewController], parentVc: UIViewController) {
        self.titles = titles
        self.titleStyle = titleStyle
        self.childVcs = childVcs
        self.parentVc = parentVc
        
        super.init(frame: frame)
    }
  • 如果一個(gè)頁面有多個(gè)控件繼承自UIScrollView眉菱,需要設(shè)置這些控件的scrollsToTop屬性蚜印,如果都為true调炬, 則點(diǎn)擊狀態(tài)欄都不會移動
collectionView.scrollsToTop = false
scrollView.scrollsToTop = false
  • CLOTitleView中選擇添加UILabel而不是UIButton的理由:UIButton中不好設(shè)置文字的屬性, 直接給UILabel中添加相應(yīng)的手勢

  • 方法for (i, label) in titleLabels.enumerated()可以遍歷數(shù)組取出數(shù)組中的元素及其下標(biāo)

  • 方法w = (titles[i] as NSString).boundingRect(with: CGSize(width: CGFloat.greatestFiniteMagnitude, height: 0), options: .usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font: style.titleFont], context: nil).width可以算出給定文字的寬度

  • 設(shè)置委托協(xié)議時(shí)能不繼承NSObjectProtocol就不繼承姚建,因?yàn)?code>NSObjectProtocol里的方法一般用不到,又因?yàn)?code>weak只能修飾類漆羔,所以委托協(xié)議只需繼承自class即可

// MARK: - 設(shè)置委托協(xié)議
protocol CLOTitleViewDelegate: class {
    func titleView(_ titleView: CLOTitleView, didSelected currentIndex: Int)
}

weak var delegate: CLOTitleViewDelegate?
  • 獲取RGB顏色的差值方法: 分別獲取R婆芦、G、B值再相減
class func getRGBDelta(_ firstColor : UIColor, _ seccondColor : UIColor) -> (CGFloat, CGFloat,  CGFloat) {
        let firstRGB = firstColor.getRGB()
        let secondRGB = seccondColor.getRGB()
        
        return (firstRGB.0 - secondRGB.0, firstRGB.1 - secondRGB.1, firstRGB.2 - secondRGB.2)
        
}
    
func getRGB() -> (CGFloat, CGFloat, CGFloat) {
        guard let cmps = cgColor.components else {
            fatalError("保證普通顏色是RGB方式傳入")
        }
        
        return (cmps[0] * 255, cmps[1] * 255, cmps[2] * 255)
}
  • 顏色漸變動畫實(shí)現(xiàn)思路: 先判斷當(dāng)前是左移還是右移穆刻,用移動前scrollView的偏移量與移動后的偏移量比較置尔,獲得移動后下一個(gè)頁面的下標(biāo),再獲取當(dāng)前頁面移動的百分比蛹批,通過代理讓titleView作出相應(yīng)處理撰洗,讓RGB顏色差值乘以百分比
  • 底部滾動條的動畫類似,讓不同滾動條寬度之間的差值乘以這個(gè)百分比

瀑布流布局

  • 瀑布流布局實(shí)現(xiàn)整體思路:采用UICollectionView自定義UICollectionViewFlowLayout 主要實(shí)現(xiàn)下面三個(gè)方法:
// MARK:- 準(zhǔn)備布局
extension HYWaterfallLayout {
    // 告訴當(dāng)前 layout 需要改變
    override func prepare() {
        super.prepare()
        ...
        // Cell --> UICollectionViewLayoutAttributes
        // 設(shè)置好每個(gè) cell 的 frame        
        ...
        
}

// MARK:- 返回準(zhǔn)備好所有布局
extension HYWaterfallLayout {
    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        return cellAttrs
    }
}

// MARK:- 設(shè)置contentSize
extension HYWaterfallLayout {
    override var collectionViewContentSize: CGSize {
        return CGSize(width: 0, height: totalHeights.max()! + sectionInset.bottom)
    }
}

  • 每個(gè)cellframe 計(jì)算
// 用一個(gè)屬性保存每一行 cell 的高度
fileprivate lazy var totalHeights : [CGFloat] = Array(repeating: self.sectionInset.top, count: self.cols)
    
// 計(jì)算當(dāng)前一排最小高度及其列數(shù)
let minH = totalHeights.min()!
let minIndex = totalHeights.index(of: minH)!

// x 和 y 值
let cellX : CGFloat = sectionInset.left + (minimumInteritemSpacing + cellW) * CGFloat(minIndex)
let cellY : CGFloat = minH + minimumLineSpacing

// 更新當(dāng)前的最小高度
totalHeights[minIndex] = minH + minimumLineSpacing + cellH

相當(dāng)于將下一個(gè) cell 加在當(dāng)前一行中cellY值最小的 cell 的下面

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末腐芍,一起剝皮案震驚了整個(gè)濱河市差导,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌猪勇,老刑警劉巖设褐,帶你破解...
    沈念sama閱讀 222,464評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異泣刹,居然都是意外死亡助析,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,033評論 3 399
  • 文/潘曉璐 我一進(jìn)店門椅您,熙熙樓的掌柜王于貴愁眉苦臉地迎上來外冀,“玉大人,你說我怎么就攤上這事掀泳⊙┧恚” “怎么了西轩?”我有些...
    開封第一講書人閱讀 169,078評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長脑沿。 經(jīng)常有香客問我藕畔,道長,這世上最難降的妖魔是什么庄拇? 我笑而不...
    開封第一講書人閱讀 59,979評論 1 299
  • 正文 為了忘掉前任注服,我火速辦了婚禮,結(jié)果婚禮上措近,老公的妹妹穿的比我還像新娘溶弟。我一直安慰自己,他們只是感情好瞭郑,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,001評論 6 398
  • 文/花漫 我一把揭開白布可很。 她就那樣靜靜地躺著,像睡著了一般凰浮。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上苇本,一...
    開封第一講書人閱讀 52,584評論 1 312
  • 那天袜茧,我揣著相機(jī)與錄音,去河邊找鬼瓣窄。 笑死笛厦,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的俺夕。 我是一名探鬼主播裳凸,決...
    沈念sama閱讀 41,085評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼劝贸!你這毒婦竟也來了姨谷?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,023評論 0 277
  • 序言:老撾萬榮一對情侶失蹤映九,失蹤者是張志新(化名)和其女友劉穎梦湘,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體件甥,經(jīng)...
    沈念sama閱讀 46,555評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡捌议,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,626評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了引有。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瓣颅。...
    茶點(diǎn)故事閱讀 40,769評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖譬正,靈堂內(nèi)的尸體忽然破棺而出宫补,到底是詐尸還是另有隱情檬姥,我是刑警寧澤,帶...
    沈念sama閱讀 36,439評論 5 351
  • 正文 年R本政府宣布守谓,位于F島的核電站穿铆,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏斋荞。R本人自食惡果不足惜荞雏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,115評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望平酿。 院中可真熱鬧凤优,春花似錦、人聲如沸蜈彼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,601評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽幸逆。三九已至棍辕,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間还绘,已是汗流浹背楚昭。 一陣腳步聲響...
    開封第一講書人閱讀 33,702評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拍顷,地道東北人抚太。 一個(gè)月前我還...
    沈念sama閱讀 49,191評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像昔案,于是被迫代替她去往敵國和親尿贫。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,781評論 2 361