专业java、php、iOS、C++、网页设计、平面设计、网络营销、游戏开发、前端与移动开发培训机构

配图视图布局和计算尺寸

  • 添加9张图片

    /// 微博配图视图,显示9张图片
    class HMStatusPictureView: UIView {
    
      /// 配图自身的宽度约束
      @IBOutlet weak var widthCons: NSLayoutConstraint!
    
      /// 配图自身的高度约束
      @IBOutlet weak var heightCons: NSLayoutConstraint!
    
      // MARK: - 属性
      // 存放9个imageView
      private var imageViews = [UIImageView]()
    
      required init?(coder aDecoder: NSCoder) {
          super.init(coder: aDecoder)
    
          setupUI()
      }
    
      /// 配图视图添加9张图片
      private func setupUI() {
          // 添加9个imageView
          for _ in 0..<9 {
              // 创建imageView
              let imageView = UIImageView()
              imageView.backgroundColor = UIColor.random
    
              self.addSubview(imageView)
              // 添加到imageViews的数组里面,方便后续操作
              imageViews.append(imageView)
          }
    
          // 添加测试的label
          addSubview(debugLabel)
      }
    
      //MARK: - 懒加载
      private lazy var debugLabel: UILabel = {
          let label = UILabel()
    
          label.font = UIFont.systemFont(ofSize: 20)
          label.textColor = UIColor.black
          label.text = "我还没有图片"
          label.frame = CGRect(x: 20, y: 20, width: 200, height: 100)
    
          return label
      }()
    }
    
  • 实现随机颜色的扩展

    import UIKit
    extension UIColor {
    
      /// 返回随机颜色
      class var random: UIColor {
          get {
              let r = CGFloat(arc4random_uniform(256)) / 255.0
              let g = CGFloat(arc4random_uniform(256)) / 255.0
              let b = CGFloat(arc4random_uniform(256)) / 255.0
    
              return UIColor(red: r, green: g, blue: b, alpha: 1)
          }
      }
    }
    

  • 微博配图视图 HMStatusPictureView 定义 pictureURLs 属性
  • 根据 微博配图 计算 配图视图宽高

    • HMStatusPictureView 定义 pictureURLs 属性

      /// 微博配图
      var pictureURLs: [NSURL]? {
        didSet {
      
        }
      }
      
  • HMStatusPictureViewpictureURLs 属性赋值

    • 发现需要获取模型的图片路径不方便,最好是模型能提供图片对应的 URL,其他地方只需要直接拿来使用
    • HMStatusViewModel 添加 storePictureURLs 存储 HMStatus 里面的 pic_urls 对应的 URL

      /// 一个HMStatusViewModel包含一个微博模型
      class HMStatusViewModel: NSObject {
        // MARK: - 属性
        /// 微博模型
        var status: HMStatus
      
        /// 视图模型提供 认证类型的图片
        var verifiedImage: UIImage?
      
        /// 视图模型提供 会员等级的图片
        var mbrankImage: UIImage?
      
        /// 原创微博配图的URL数组
        var storePictureURLs: [NSURL]?
        ...   
      }
      
    • HMStatusViewModelinit(status: HMStatus) 里面设置 storePictureURLs 属性

      // MARK: - 构造函数
      init(status: HMStatus) {
        self.status = status
      
        // 认证类型
        ...
        // 会员等级
        ...
      
        // 原创微博配图URL数组
        let count = status.pic_urls?.count ?? 0
        if count > 0 {
            // 原创微博有图片,创建数组保存转好的URL
            storePictureURLs = [NSURL]()
      
            // 遍历所有字典
            for dict in status.pic_urls! {
                // 取出字典的value,转成NSURL,
                let urlString = dict["thumbnail_pic"]
      
                // 转成NSURL
                let url = NSURL(string: urlString!)!
      
                // 添加到storePictureURLs数组
                storePictureURLs?.append(url)
            }
        }
      }
      
    • HMStatusCellstatusVM: HMStatusViewModel?didSet 属性监视器里面将原创微博配图赋值给 HMStatusPictureViewpictureURLs 属性

      /// 微博ViewModel
      var statusVM: HMStatusViewModel? {
        didSet {
            guard let status = statusVM?.status else {
                print("statusVM中没有微博")
                return
            }
      
            // 头像,使用SDWebImage设置网络图片内容
            ...
      
            // 用户名称
            ...
      
            // 来源
            ...
      
            // 时间
            ...
      
            // 微博内容
            ...
      
            // 会员等级
            ...
      
            // 认证图标
            ...
      
            // 设置原创微博配图的URL
            pictureView.pictureURLs = statusVM?.storePictureURLs
        }
      }
      
    • HMStatusPictureViewpictureURLs: [NSURL] 属性可以获得传入的图片

      /// 微博配图
      var pictureURLs: [NSURL]? {
        didSet {
      
        }
      }
      

布局9张imageView

  • HMStatusPictureView 定义计算配图尺寸的相关常量
    /// cell 的间距
    private let HMStatusPictureViewItemMargin: CGFloat = 4
    /// 最大列数
    private let maxColumn = 3
    /// cell 的宽高 = (屏幕的宽度 - 左边的间距 - 右边的间距 - 2 * item之间的间距) / 列数
    private let HMStatusPictureViewItemWH: CGFloat = (UIScreen.width - 2 * CZStatusCellMargin - (2 * CZStatusPictureViewItemMargin)) / 3
    
  • 定义 UIScreen 扩展,快速返回 宽高

    extension UIScreen {
      /// 返回宽度
      class var width: CGFloat {
          return UIScreen.main.bounds.width
      }
    
      /// 返回高度
      class var height: CGFloat {
          return UIScreen.main.bounds.height
      }
    }
    
  • HMStatusPictureView 里面添加 layoutImageViews 布局图片的位置
  • 实现 layoutImageViews: 方法

    /// 布局9个图片的位置
    ///
    /// - parameter count: 要显示图片的数量
    private func layoutImageViews(count: Int) {
      // 遍历每一个imageView,设置frame
      for (index, imageView) in imageViews.enumerated() {
          // 计算每个imageView在哪列
          let column = index % maxColumn
    
          // 计算每个imageView在哪行
          let row = index / maxColumn
    
          // 计算x
          let x = CGFloat(column) * (HMStatusPictureViewItemWH + HMStatusPictureViewItemMargin)
    
          // 计算y
          let y = CGFloat(row) * (HMStatusPictureViewItemWH + HMStatusPictureViewItemMargin)
    
          // 设置imageView的fame
          imageView.frame = CGRect(x: x, y: y, width: HMStatusPictureViewItemWH, height: HMStatusPictureViewItemWH)
      }
    }
    
  • HMStatusPictureViewpictureURLs 的属性监视器里面调用 layoutImageViews,并且设置调试label,显示图片数量
    /// 微博配图
    var pictureURLs: [NSURL]? {
      didSet {
          debugLabel.text = "图片数量 = \(pictureURLs?.count ?? 0)"
          layoutImageViews(pictureURLs: pictureURLs.count)
      }
    }
    
  • 运行

隐藏不需要显示图片的imageView

  • /// 布局9个图片的位置
    ///
    /// - parameter count: 要显示图片的数量
    private func layoutImageViews(count: Int) {
    
      /// 默认3列
      var numberOfColumn = 3
      if count == 1 {
          // 只有一个图片,显示1列
          numberOfColumn = 1
      } else if count == 2 || count == 4 {
          // 2个或4个图片显示2列
          numberOfColumn = 2
      }
    
      // 遍历每一个imageView,设置frame
      for (index, imageView) in imageViews.enumerated() {
          if index >= count {
              // 隐藏起来
              imageView.isHidden = true
          } else {
              // 显示出来
              imageView.isHidden = false
    
              // 计算每个imageView在哪列
              let column = index % numberOfColumn
    
              // 计算每个imageView在哪行
              let row = index / numberOfColumn
    
              // 计算x
              let x = CGFloat(column) * (HMStatusPictureViewItemWH + HMStatusPictureViewItemMargin)
    
              // 计算y
              let y = CGFloat(row) * (HMStatusPictureViewItemWH + HMStatusPictureViewItemMargin)
    
              // 设置imageView的fame
              imageView.frame = CGRect(x: x, y: y, width: HMStatusPictureViewItemWH, height: HMStatusPictureViewItemWH)
          }
      }
    }
    
  • 运行: 效果如下

计算宽高

  • /// 计算配图的总宽和高
    ///
    /// - parameter count: 图片的数量
    ///
    /// - returns: 配图的总宽和高
    private func calcPictureViewSize(count: Int) -> CGSize {
      // 根据 图片数量 计算配图的总大小
      if count == 0 {
          return CGSize.zero
      }
    
      /// 默认3列
      var numberOfColumn = 3
      if count == 1 {
          // 只有一个图片,显示1列
          numberOfColumn = 1
      } else if count == 2 || count == 4 {
          // 2个或4个图片显示2列
          numberOfColumn = 2
      }
    
      // 计算宽度 = 总列数 * 图片的宽度 + (总列数 - 1) * 图片间距
      let width = CGFloat(numberOfColumn) * HMStatusPictureViewItemWH + (CGFloat(numberOfColumn) - 1) * HMStatusPictureViewItemMargin
    
      // 2 = (6 + 3 - 1) / 3
      // 3 = (9 + 3 - 1) / 3
      // 1 = (3 + 3 - 1) / 3
      // 总行数 = (总数 + 总列数 - 1) / 总列数, 前提保证都是整数
      let numberOfRow = (count + numberOfColumn - 1) / numberOfColumn
    
      // 计算高度 = 顶部间距 + 总行数 * 图片高度 + (总行数 - 1) * 图片的间距
      let height = HMStatusPictureViewItemMargin + CGFloat(numberOfRow) * HMStatusPictureViewItemWH + (CGFloat(numberOfRow) - 1) * HMStatusPictureViewItemMargin
    
      return CGSize(width: width, height: height)
    }
    

设置 HMStatusPictureView 的宽高

  • HMStatusPictureViewpictureURLs didSet 属性监视器里面调用 calcPictureViewSize 计算 配图的宽高, 并更新约束

    /// 微博配图
    var pictureURLs: [NSURL]? {
      didSet {
          debugLabel.text = "图片数量 = \(pictureURLs?.count ?? 0)"
    
          // 要显示图片的数量
          let count = pictureURLs?.count ?? 0
          layoutImageViews(count: count)
    
          let size = calcPictureViewSize(count: count)
          widthCons.constant = size.width
          heightCons.constant = size.height
      }
    }
    

设置内容

/// 布局9个图片的位置
///
/// - parameter count: 要显示图片的数量
private func layoutImageViews(count: Int) {

    /// 默认3列
    var numberOfColumn = 3
    if count == 1 {
        // 只有一个图片,显示1列
        numberOfColumn = 1
    } else if count == 2 || count == 4 {
        // 2个或4个图片显示2列
        numberOfColumn = 2
    }

    // 遍历每一个imageView,设置frame
    for (index, imageView) in imageViews.enumerated() {
        if index >= count {
            // 隐藏起来
            imageView.isHidden = true
        } else {
            // 显示出来
            imageView.isHidden = false

            // 计算每个imageView在哪列
            let column = index % numberOfColumn

            // 计算每个imageView在哪行
            let row = index / numberOfColumn

            // 计算x
            let x = CGFloat(column) * (HMStatusPictureViewItemWH + HMStatusPictureViewItemMargin)

            // 计算y
            let y = HMStatusCellMargin + CGFloat(row) * (HMStatusPictureViewItemWH + HMStatusPictureViewItemMargin)

            // 设置imageView的fame
            imageView.frame = CGRect(x: x, y: y, width: HMStatusPictureViewItemWH, height: HMStatusPictureViewItemWH)

            let url = pictureURLs![index]
            imageView.sd_setImage(with: url)
        }
    }
}
  • 设置图片的填充模式和裁切

    /// 配图视图添加9张图片
    private func setupUI() {
      // 添加9个imageView
      for _ in 0..<9 {
          // 创建imageView
          let imageView = UIImageView()
          imageView.backgroundColor = UIColor.random
          imageView.contentMode = UIViewContentMode.scaleAspectFill
          imageView.clipsToBounds = true
    
          self.addSubview(imageView)
          // 添加到imageViews的数组里面,方便后续操作
          imageViews.append(imageView)
      }
    
      // 添加测试的label
      addSubview(debugLabel)
    }
    
  • 运行: 效果如下

results matching ""

    No results matching ""