直播项目笔记(一)

颜色封装 + ClOPageView + 瀑布流

搭建主题框架

导航栏布局

  • 改变导航栏的颜色
// 在 AppDelegate 中
UINavigationBar.appearance().barTintColor = .black  // tintColor 是导航栏文字的颜色
  • 改变状态栏的颜色
// 苹果推荐方法 在需要设置页面 controller 中
override var preferredStatusBarStyle: UIStatusBarStyle {
        return .lightContent // 默认为白色
    }
// or
// 在 info.plist 中 设置
View controller-based status bar appearance 设置为 NO // 全局
// 在 AppDelegate 中
UIApplication.shared.statusBarStyle = .lightContent
// or

设置首页 NavigationBar 注意事项

  • 如果事件监听方法为私有时 要在方法前面加 @objc 公开则不需要
// 事件监听 --> 发送消息 --> 将方法包装SEL  --> 类方法列表 --> IMP

颜色封装 :UIColor + Extension

  • 拓展方法如果有参数 采用便利构造函数
// 自定义 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)
} 
// 返回一个十六进制颜色
convenience init?(hex : String, alpha : CGFloat = 1.0) {
        
        // 0xff0000
        // 1.判断字符串的长度是否符合
        guard hex.characters.count >= 6 else {
            return nil
        }
        
        // 2.将字符串转成大写
        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.将十六进制转成数字 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))
}
  • 没有参数的扩展方法 用类方法
/// 随机颜色
class func randomColor() -> UIColor {
        return UIColor(r: CGFloat(arc4random_uniform(256)), g: CGFloat(arc4random_uniform(256)), b: CGFloat(arc4random_uniform(256)))
}

封装 CLOPageView

  • 类似网易新闻 titleView(UIScrollView) + contentView(UICollectionView)

  • 结构视图


  • 如果类中的属性没有初始化,要在创建对象super.init()前赋值 否则会报错

// 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)
    }
  • 如果一个页面有多个控件继承自UIScrollView,需要设置这些控件的scrollsToTop属性,如果都为true, 则点击状态栏都不会移动
collectionView.scrollsToTop = false
scrollView.scrollsToTop = false
  • CLOTitleView中选择添加UILabel而不是UIButton的理由:UIButton中不好设置文字的属性, 直接给UILabel中添加相应的手势

  • 方法for (i, label) in titleLabels.enumerated()可以遍历数组取出数组中的元素及其下标

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

  • 设置委托协议时能不继承NSObjectProtocol就不继承,因为NSObjectProtocol里的方法一般用不到,又因为weak只能修饰类,所以委托协议只需继承自class即可

// MARK: - 设置委托协议
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)
}
  • 颜色渐变动画实现思路: 先判断当前是左移还是右移,用移动前scrollView的偏移量与移动后的偏移量比较,获得移动后下一个页面的下标,再获取当前页面移动的百分比,通过代理让titleView作出相应处理,让RGB颜色差值乘以百分比
  • 底部滚动条的动画类似,让不同滚动条宽度之间的差值乘以这个百分比

瀑布流布局

  • 瀑布流布局实现整体思路:采用UICollectionView自定义UICollectionViewFlowLayout 主要实现下面三个方法:
// MARK:- 准备布局
extension HYWaterfallLayout {
    // 告诉当前 layout 需要改变
    override func prepare() {
        super.prepare()
        ...
        // Cell --> UICollectionViewLayoutAttributes
        // 设置好每个 cell 的 frame        
        ...
        
}

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

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

  • 每个cellframe 计算
// 用一个属性保存每一行 cell 的高度
fileprivate lazy var totalHeights : [CGFloat] = Array(repeating: self.sectionInset.top, count: self.cols)
    
// 计算当前一排最小高度及其列数
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

// 更新当前的最小高度
totalHeights[minIndex] = minH + minimumLineSpacing + cellH

相当于将下一个 cell 加在当前一行中cellY值最小的 cell 的下面

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,193评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,306评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,130评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,110评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,118评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,085评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,007评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,844评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,283评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,508评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,395评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,985评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,630评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,797评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,653评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,553评论 2 352