专业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 { } }
给
HMStatusPictureView
的pictureURLs
属性赋值- 发现需要获取模型的图片路径不方便,最好是模型能提供图片对应的
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]? ... }
在
HMStatusViewModel
的init(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) } } }
在
HMStatusCell
的statusVM: HMStatusViewModel?
的didSet
属性监视器里面将原创微博配图赋值给HMStatusPictureView
的pictureURLs
属性/// 微博ViewModel var statusVM: HMStatusViewModel? { didSet { guard let status = statusVM?.status else { print("statusVM中没有微博") return } // 头像,使用SDWebImage设置网络图片内容 ... // 用户名称 ... // 来源 ... // 时间 ... // 微博内容 ... // 会员等级 ... // 认证图标 ... // 设置原创微博配图的URL pictureView.pictureURLs = statusVM?.storePictureURLs } }
在
HMStatusPictureView
的pictureURLs: [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) } }
- 在
HMStatusPictureView
的pictureURLs
的属性监视器里面调用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
的宽高
在
HMStatusPictureView
的pictureURLs
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) }
- 运行: 效果如下