簡體   English   中英

在自定義UITableViewCell中保持UIImageView的長寬比

[英]Keep aspect ratio of an UIImageView in a custom UITableViewCell

所以我想做的是讓我的自定義UITableViewCell包含一個UIImageView其中包含一個圖像,並讓此ImageView始終與其中的圖像保持相同的寬高比,同時具有與單元格相同的寬度。 然后,單元格的高度應與ImageView的高度相同。

這是我正在使用的代碼:

我的自定義UITableViewCell類:

import UIKit

class ImageTableViewCell: UITableViewCell {

    var imageURL: NSURL? {
        didSet {
            fetchImage()
        }
    }

    @IBOutlet weak var activityIndicator: UIActivityIndicatorView!

    @IBOutlet weak var myImageView: UIImageView!

    func fetchImage() {
        myImageView?.image = nil

        guard let imageURL = self.imageURL else {
            return
        }
        activityIndicator?.startAnimating()
        let queue = dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)
        dispatch_async(queue) {
            guard let imageData = NSData(contentsOfURL: imageURL) else { return }
            dispatch_async(dispatch_get_main_queue()) {
                guard imageURL == self.imageURL else { return }
                if let image = UIImage(data: imageData) {
                    self.tweetImage?.image = image
                    self.tweetImage?.sizeToFit()
                } else { self.tweetImage?.image = nil }
                self.spinner?.stopAnimating()
            }
        }
    }

    func addRatioConstraint(ratio: CGFloat) {
        let ratioConstraint = NSLayoutConstraint(item: myImageView, attribute: .Width, relatedBy: .Equal, toItem: myImageView, attribute: .Height, multiplier: ratio, constant: 0)
        ratioConstraint.priority = UILayoutPriorityDefaultHigh //important piece of code
        myImageView?.addConstraint(ratioConstraint)
    }
}

這是UITableViewController的相關代碼:

override func viewDidLoad() {
    super.viewDidLoad()
    tableView.rowHeight = UITableViewAutomaticDimension
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let mention = mentionSections[indexPath.section].mentions[indexPath.row]
    switch mention {
    case .Image(let url, let ratio):
        guard let imageCell = tableView.dequeueReusableCellWithIdentifier(.Image, forIndexPath: indexPath) as? ImageTableViewCell else { fallthrough }
        imageCell.imageURL = url
        imageCell.addRatioConstraint(CGFloat(ratio))
        return imageCell
    //left out code for additional irrelevant cells
    }
}

override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    let mention = mentionSections[indexPath.section].mentions[indexPath.row]
    switch mention {
    case .Image(_, _): return 200
    default: return 41
    }
}

並了解我在使用dequeueReusableCellWithIdentifier函數的操作(只是為我簡化事情的一個擴展):

private extension UITableView {

    enum CellIdentifier: String {
        case Image = "Image"
        case Keyword = "Keyword"
    }

    func dequeueReusableCellWithIdentifier(cellIdentifier: CellIdentifier, forIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        return self.dequeueReusableCellWithIdentifier(cellIdentifier.rawValue, forIndexPath: indexPath)
    }
} 

很抱歉有這么多代碼,但是我覺得我必須包括所有這些內容。

現在問題了! 我遇到的問題是,當視圖第一次加載時,所有內容看起來都很不錯,但是當我將設備轉為橫向,然后再轉回縱向時,我失去了長寬比,圖像被壓縮了。 像這樣:

http://i.imgur.com/tcnBfyH.jpg

但是,如果我刪除以下代碼行(在addRatioConstraint(ratio: CGFloat) -方法中):

ratioConstraint.priority = UILayoutPriorityDefaultHigh

(這意味着優先級現在是1000,而不是750),一切正常,只是我現在在控制台中打印出一個錯誤:

Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSLayoutConstraint:0x7fcfd4d3e690 UIImageView:0x7fcfd4e29a70.trailing == UITableViewCellContentView:0x7fcfd4e29900.trailingMargin>",
    "<NSLayoutConstraint:0x7fcfd4d3f5c0 UIImageView:0x7fcfd4e29a70.bottom == UITableViewCellContentView:0x7fcfd4e29900.bottomMargin>",
    "<NSLayoutConstraint:0x7fcfd4d3f610 UIImageView:0x7fcfd4e29a70.top == UITableViewCellContentView:0x7fcfd4e29900.topMargin>",
    "<NSLayoutConstraint:0x7fcfd4d3f660 UIImageView:0x7fcfd4e29a70.leading == UITableViewCellContentView:0x7fcfd4e29900.leadingMargin>",
    "<NSLayoutConstraint:0x7fcfd4d52010 UIImageView:0x7fcfd4e29a70.width == 1.34387*UIImageView:0x7fcfd4e29a70.height>",
    "<NSLayoutConstraint:0x7fcfd4e1f200 'UIView-Encapsulated-Layout-Width' H:[UITableViewCellContentView:0x7fcfd4e29900(341)]>",
    "<NSLayoutConstraint:0x7fcfd4e1f250 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7fcfd4e29900(199.5)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x7fcfd4d52010 UIImageView:0x7fcfd4e29a70.width == 1.34387*UIImageView:0x7fcfd4e29a70.height>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

因此,基本上Xcode所做的是它打破了我的方面約束,試圖解決一些沖突。 而且有效。 在我的腦海中,這應該意味着降低約束的優先級也可以解決問題?

任何幫助將不勝感激,我已經為此努力了幾天。

就像在此答案中一樣 ,您正在設置可變寬度約束以及尾隨和前導約束。 這將導致沖突。

用centerX約束替換尾隨/前導約束。

我建議為此使用

首先,請確保imageView.contentMode = .scaleAspectFill imageView.translatesAutoreisizingMaskIntoConstraints = falseimageView.contentMode = .scaleAspectFill

然后,根據需要在每一側設置錨點。

imageView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
imageView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
imageView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
imageView.bottomAnchor.constraint(self.bottomAnchor).isActive = true

您還可以在約束參數中添加..,constant: Float) ,以設置父錨點和imageView之間的特定距離。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM