實現cell圖片自適應方案

UITableView 是 iOS 開發中最經常使用的控件之一,使用 UITaleView 時最頭疼的莫過於 cell 高度的計算,雖然說在 iOS8.0 之後引入了自適應方法,但在適配過程當中任然會遇到各類難題,尤爲是爲了知足產品需求進行復雜 cell 自定義時,高度計算可謂是難上加難.這裏主要對開發中遇到的自定義 cell 是加載網絡圖片適配問題進行總結.git

在開發中爲了用戶能有更好體驗,對網絡請求多采用異步請求的方式,更有甚者對請求數據作了本地緩存.圖片做爲 app 中最多見的展示形式無疑是最耗流量的,對圖片的處理直接影響到用戶的體驗,好在有大神爲咱們提供了好的框架(Kingfisher,SDWebImage),大大提升了咱們的開發效率.github

圖片的異步加載提升了用戶體驗,卻在開發中遇到了新的難題,由於圖片異步加載你沒法提早預知圖片的尺寸,在佈局時難以控制 UIImageView 的大小,若是將 UIImageView 固定大小勢必會形成圖片的壓縮或拉伸,如今主要針對於自定義 cell 時對圖片自適應佈局提一些建議.swift

固定 UIImageView 大小

在開發中咱們時常會將 UIImageView 固定大小或者固定寬高比例,經過設置 ImageView 的 contentMode 屬性設置圖片的顯示風格.
該方法簡單容易形成圖片壓縮拉伸或顯示不全問題.
contentMode 取值:緩存

public enum UIViewContentMode : Int {

    case scaleToFill //縮放內容到合適比例大小

    case scaleAspectFit //縮放內容到合適的大小,邊界多餘部分透明

    case scaleAspectFill  //縮放內容填充到指定大小,邊界多餘的部分省略

    case redraw //重繪視圖邊界

    case center //視圖保持等比縮放,居中

    case top //視圖頂部對齊

    case bottom //視圖底部對齊

    case left //視圖左側對齊

    case right //視圖右側對齊

    case topLeft //視圖左上角對齊

    case topRight //視圖右上角對齊

    case bottomLeft //視圖左下角對齊

    case bottomRight //視圖右下角對齊
}
複製代碼

經過獲取服務器存儲的圖片尺寸佈局

在上傳圖片時能夠將圖片的大小一塊兒上傳服務器保存,在用戶加載圖片時將圖片信息和圖片 URL 地址一塊兒返回,根據返回的圖片信息計算 UIImageView 的 size 進行佈局.
該方法比較簡單,但須要後臺配合使用.服務器

經過監聽圖片加載刷新 cell 實現(配合 cell 自適應)

不管 SDWebiamge 仍是 Kingfisher,做者都給咱們提供了圖片加載完回調方法,咱們能夠在圖片加載完後從新計算 cell 高度.
該方法大大加大了 cell 的刷新頻率.
具體步驟:網絡

  • 在自定義 cell 中定義閉包變量.
    var refreshCell: ((IndexPath) -> Void)?
  • 在圖片加載完成的回調中調用閉包,爲了減小 cell 的刷新,判斷是拉取網絡數據仍是加載的緩存數據,若是是網絡數據調整圖片大小並將調整後圖片覆蓋網絡加載圖片,若是是緩存圖片不處理.
iconImageView.kf.setImage(with: URL(string: iconImageURL), placeholder: UIImage(named: "tmp")) { [weak self](image, error, type, url) in
    if type == .none {
        self?.iconImageView.image =  self?.iconImageView.image?.ytt.resetImageSizeWithWidth(UIScreen.main.bounds.width)
        ImageCache.default.store((image?.ytt.resetImageSizeWithWidth(UIScreen.main.bounds.width))!, forKey: (url?.absoluteString)!)
        self?.refreshCell?(indexPath)
    }
}
複製代碼
  • 在 TableView 回調方法中實現閉包,僅當 cell 展示在屏幕時刷新
cell.refreshCell = {(index) in
    if (tableView.indexPathsForVisibleRows?.contains(index))! {
        tableView.reloadRows(at: [index], with: .automatic)
    }
}
複製代碼

經過 ImageIO 框架獲取圖片信息

在給 UIImageView 賦值時經過 ImageIO 獲取 image 的尺寸,修改 UIImageView 的大小.
該方法須要在網絡請求數據,加大了數據請求量.
實現代碼:閉包

let imageSource = CGImageSourceCreateWithURL(URL(string: iconImageURL)! as CFURL, nil)
if let result = CGImageSourceCopyPropertiesAtIndex(imageSource!, 0, nil) as? Dictionary<String, Any> {
    if let width = result["PixelWidth"] as? CGFloat, let height = result["PixelHeight"] as? CGFloat {
        let h =  (UIScreen.main.bounds.width - 20) / (width / height)
        iconImageView.snp.remakeConstraints { (make) in
            make.height.equalTo(h)
        }
    }
}
複製代碼
相關文章
相關標籤/搜索