Ios UITableView中的动态UIImageView大小

Ios UITableView中的动态UIImageView大小,ios,swift,uitableview,uiimageview,autolayout,Ios,Swift,Uitableview,Uiimageview,Autolayout,我想用显示图像的自定义TableViewCell实现TableView 为了简单起见,我使用autolayout(如下所示)将UIImageView放在tableviewcell中。 我想要的是在UIImageView中显示图像,但是这些图像的尺寸可以是任何东西,并且不一致(纵向、横向、方形) 因此,我希望显示具有固定宽度(设备宽度)和动态高度的图像,该高度与图像的比率有关。我想要这样的东西: 不幸的是,我没能达到那个结果 下面是我如何实现它的-(我使用Haneke从存储在AmazonS3中

我想用显示图像的自定义TableViewCell实现TableView

为了简单起见,我使用autolayout(如下所示)将UIImageView放在tableviewcell中。

我想要的是在UIImageView中显示图像,但是这些图像的尺寸可以是任何东西,并且不一致(纵向、横向、方形)

因此,我希望显示具有固定宽度(设备宽度)和动态高度的图像,该高度与图像的比率有关。我想要这样的东西:

不幸的是,我没能达到那个结果

下面是我如何实现它的-(我使用Haneke从存储在AmazonS3中的URL图像加载图像):

类TestCellVC:UITableViewCell{ @IBVAR selfieImageView:UIImageView! @IBOutlet弱var高度约束:NSLayoutConstraint! func loadItem(#selfie:selfie){ 让selfieImageURL:NSURL=NSURL(字符串:selfie.show_selfie_pic())! self.selfieImageView.hnk_setImageFromURL(selfieImageURL,占位符:nil,格式:HNKFormat(名称:“原始”),失败:{error->println中的Void(错误) },成功:{(图像)->Void in //屏幕宽度 var screen_width=UIScreen.mainScreen().bounds.width //宽高比 变量比率=image.size.height/image.size.width //图片的计算高度 设新高度=屏幕宽度*比率 //方法1 self.heightConstraint.constant=新高度 //方法2 //self.selfieImageView.bounds=CGRectMake(0,0,屏幕宽度,新高度) self.selfieImageView.image=图像 } ) } 重写func viewDidLoad(){ super.viewDidLoad() //为自定义TableViewCell注册xib var nib=UINib(nibName:“TestCell”,bundle:nil) self.tableView.registerNib(nib,强制重用标识符:“TestCell”) //动态设置单元格的高度 self.tableView.rowHeight=UITableViewAutomaticDimension self.tableView.estimateDroweight=500.0 //从UITableView中删除分隔线 self.tableView.separatorStyle=UITableViewCellSeparatorStyle.None loadData() } 重写func tableView(tableView:UITableView,cellForRowAtIndexPath:nsindepath)->UITableView单元格{ var cell=tableView.dequeueReusableCellWithIdentifier(“TestCell”)作为TestCellVC cell.loadItem(selfie:self.selfies\u数组[indexPath.row]) //拆下单元分离器的插图 cell.layoutMargins=UIEdgeInsetsZero cell.separatorInset=UIEdgeInsetsZero //更新单元约束 cell.setNeedsUpdateConstraints()单元格 cell.updateConstraintSifRequired() cell.sizeToFit() 返回单元 } } 我对动态高度的计算是正确的(我已经打印出来了)。我尝试了这两种方法(在代码中描述),但都不起作用:

  • 设置UIImageView的高度自动布局约束
  • 修改UIImageView的框架
  • 参见方法1和2的结果:
    从imageView中删除高度约束。选择以“方面”开头的图像视图的内容模式,例如:方面填充或方面匹配(根据您的要求进行匹配)

    注意:您还需要设置行的高度,以便imageView适合该行。使用

    heightForRowAtIndexPath
    

    设置自定义行高度。

    如果希望UIImageView告诉UITableView它需要多高,则需要配置表格视图以启用自动行计算。您可以通过将EstimateDrowEight设置为固定的正值,并将rowHeight设置为UIViewAutomaticDimension来完成此操作。这是第一部分

    现在您需要配置UIImageView,以便根据表视图所需的宽度和图像的纵横比请求高度。这将是第二部分

    首先,将contentMode设置为.AspectFit。这将导致视图根据所采用的任何尺寸调整图像外观的大小。但是,这仍然不会导致它使用自动布局请求所需的高度。相反,它将请求intrinsicContentSize的高度,这可能与调整大小的图像大不相同。因此,第二,向UIImageView添加一个约束,其形式为
    width=height*multiplier
    ,其中multiplier基于图像本身的纵横比

    现在,表格视图将需要正确的宽度,contentMode机制将确保图像在不失真的情况下正确调整大小,纵横比约束将通过自动布局确保图像视图需要正确的高度

    这很有效。它的缺点是,每次将新图像指定给图像视图时,您都需要更新纵横比约束,如果图像视图位于要重复使用的单元格中,这可能非常常见


    另一种方法是仅添加高度约束,并在包含图像视图的视图的LayoutSubview中更新它。这具有更好的性能,但代码模块性较差。

    在情节提要中,为您的
    UIImageView添加尾随、前导、底部和顶部约束。加载图像后,只需向
    UIImageView
    添加一个方面约束即可。“图像”单元格的外观如下所示:

    class ImageTableViewCell: UITableViewCell {
    
        @IBOutlet weak var customImageView: UIImageView!
    
        internal var aspectConstraint : NSLayoutConstraint? {
            didSet {
                if oldValue != nil {
                    customImageView.removeConstraint(oldValue!)
                }
                if aspectConstraint != nil {
                    customImageView.addConstraint(aspectConstraint!)
                }
            }
        }
    
        override func prepareForReuse() {
            super.prepareForReuse()
            aspectConstraint = nil
        }
    
        func setCustomImage(image : UIImage) {
    
            let aspect = image.size.width / image.size.height
    
            let constraint = NSLayoutConstraint(item: customImageView, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: customImageView, attribute: NSLayoutAttribute.height, multiplier: aspect, constant: 0.0)
            constraint.priority = 999
    
            aspectConstraint = constraint
    
            customImageView.image = image
        }
    }
    
    您可以在此处查看工作示例

    将图像加载到tableView时,每个图像可以具有不同的纵横比。 通过使用,我们可以从url获取图像-

     testImageView.sd_setImage(with: url, placeholderImage: nil, options: [], completed: { (downloadedImage, error, cache, url) in
                print(downloadedImage?.size.width)//prints width of image
                print(downloadedImage?.size.height)//prints height of image
            })
    
    UITableViewCell
    中,将imageView的约束设置为
    顶部
    底部
    前导
    尾随
    固定高度约束
    wi
     testImageView.sd_setImage(with: url, placeholderImage: nil, options: [], completed: { (downloadedImage, error, cache, url) in
                print(downloadedImage?.size.width)//prints width of image
                print(downloadedImage?.size.height)//prints height of image
            })
    
     var cellFrame = cell.frame.size
     cellFrame.height =  cellFrame.height - 15
     cellFrame.width =  cellFrame.width - 15
     cell.feedImageView.sd_setImage(with: url, placeholderImage: nil, options: [], completed: { (theImage, error, cache, url) in
                cell.feedImageHeightConstraint.constant = self.getAspectRatioAccordingToiPhones(cellImageFrame: cellFrame,downloadedImage: theImage!)
    
            })
    
      func getAspectRatioAccordingToiPhones(cellImageFrame:CGSize,downloadedImage: UIImage)->CGFloat {
            let widthOffset = downloadedImage.size.width - cellImageFrame.width
            let widthOffsetPercentage = (widthOffset*100)/downloadedImage.size.width
            let heightOffset = (widthOffsetPercentage * downloadedImage.size.height)/100
            let effectiveHeight = downloadedImage.size.height - heightOffset
            return(effectiveHeight)
        }
    
       func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
            if let height = self.rowHeights[indexPath.row]{
                return height
            }else{
                return defaultHeight
            }
        }
    
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return imageArray.count
        }
    
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let identifier = "editImageCell"
            let customCell : EdiPostImageCell = (self.imagesTableView.dequeueReusableCell(withIdentifier: identifier)) as! EdiPostImageCell
            let aspectRatio = (imageArray[indexPath.row]).size.height/(imageArray[indexPath.row]).size.width
            customCell.editlImageView.image = imageArray[indexPath.row]
            let imageHeight = self.view.frame.width*aspectRatio
            self.imagesTableView.beginUpdates()
            self.rowHeights[indexPath.row] = imageHeight
            tableView.endUpdates()
        }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
            let entity = self.fetchedResultController.object(at: indexPath as IndexPath) as! Message
            var newh:CGFloat = 100.00
    
            if let fileThumbnails =  entity.file_thumbnails as? NSArray{
                if fileThumbnails.count != 0{
                    fileThumbnails.map { (thumbNail) in
                        newh = self.getImageHeight(image:UIImage(data: thumbNail as! Data)! , h: UIImage(data: thumbNail as! Data)!.size.height , w: UIImage(data: thumbNail as! Data)!.size.width)
                    }
    
                }
    
            }
    
            if entity.fileStatus == "DeletedMedia" {
                newh = 100
            }
            if entity.fileStatus == nil{
                newh = 0.0
            }
            print ("newH " , newh)
            return newh
        }
        func getImageHeight(image : UIImage, h : CGFloat, w : CGFloat) -> CGFloat {
            let aspect = image.size.width / image.size.height
            var newH = (messagesTV.frame.size.width) / aspect
            // customise as you want in newH
            if(newH > 500){
                newH = 500
               //maximum height 500
            }
            if(newH < 100){
                newH = 100
                //minimum height = 100
            }
            return newH
        }