代码之家  ›  专栏  ›  技术社区  ›  Robert MouzmiSadiq

如何使UITableViewCell的ImageView具有固定大小(即使图像较小)

  •  95
  • Robert MouzmiSadiq  · 技术社区  · 14 年前

    我有一堆图片,我用细胞的图像视图,他们都不超过50x50大。e、 g.40x50、50x32、20x37。。。。。

    当我加载表视图时,文本不会排列,因为图像的宽度不同。另外,我想小的图像出现在中间,而不是在左边。

    下面是我在“cellforrowatinexpath”方法中尝试的代码

    cell.imageView.autoresizingMask = ( UIViewAutoresizingNone );
    cell.imageView.autoresizesSubviews = NO;
    cell.imageView.contentMode = UIViewContentModeCenter;
    cell.imageView.bounds = CGRectMake(0, 0, 50, 50);
    cell.imageView.frame = CGRectMake(0, 0, 50, 50);
    cell.imageView.image = [UIImage imageWithData: imageData];
    

    正如你所看到的,我试过一些方法,但没有一种有效。

    14 回复  |  直到 12 年前
        1
  •  158
  •   shim    6 年前

    没有必要重写所有的东西。我建议这样做:

    在自定义单元格的.m文件中发布。

    - (void)layoutSubviews {
        [super layoutSubviews];
        self.imageView.frame = CGRectMake(0,0,32,32);
    }
    

    这应该能很好地发挥作用。:]

        2
  •  140
  •   Matthew Cawley    7 年前

    UITableViewCell

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
     [...]
    
          CGSize itemSize = CGSizeMake(40, 40);
          UIGraphicsBeginImageContextWithOptions(itemSize, NO, UIScreen.mainScreen.scale);
          CGRect imageRect = CGRectMake(0.0, 0.0, itemSize.width, itemSize.height);
          [cell.imageView.image drawInRect:imageRect];
          cell.imageView.image = UIGraphicsGetImageFromCurrentImageContext();
          UIGraphicsEndImageContext();
    
     [...]
         return cell;
    }
    

    Swift 2号

        let itemSize = CGSizeMake(25, 25);
        UIGraphicsBeginImageContextWithOptions(itemSize, false, UIScreen.mainScreen().scale);
        let imageRect = CGRectMake(0.0, 0.0, itemSize.width, itemSize.height);
        cell.imageView?.image!.drawInRect(imageRect)
        cell.imageView?.image! = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    

    或者您可以使用@Tommy建议的另一种(未经测试的)方法:

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
     [...]
    
          CGSize itemSize = CGSizeMake(40, 40);
          UIGraphicsBeginImageContextWithOptions(itemSize, NO, 0.0)          
     [...]
         return cell;
    }
    

    雨燕3+

    let itemSize = CGSize.init(width: 25, height: 25)
    UIGraphicsBeginImageContextWithOptions(itemSize, false, UIScreen.main.scale);
    let imageRect = CGRect.init(origin: CGPoint.zero, size: itemSize)
    cell?.imageView?.image!.draw(in: imageRect)
    cell?.imageView?.image! = UIGraphicsGetImageFromCurrentImageContext()!;
    UIGraphicsEndImageContext();
    

        3
  •  33
  •   Chris    13 年前

    我是这样做的。此技术负责将文本和详细文本标签适当地向左移动:

    @interface SizableImageCell : UITableViewCell {}
    @end
    @implementation SizableImageCell
    - (void)layoutSubviews {
        [super layoutSubviews];
    
        float desiredWidth = 80;
        float w=self.imageView.frame.size.width;
        if (w>desiredWidth) {
            float widthSub = w - desiredWidth;
            self.imageView.frame = CGRectMake(self.imageView.frame.origin.x,self.imageView.frame.origin.y,desiredWidth,self.imageView.frame.size.height);
            self.textLabel.frame = CGRectMake(self.textLabel.frame.origin.x-widthSub,self.textLabel.frame.origin.y,self.textLabel.frame.size.width+widthSub,self.textLabel.frame.size.height);
            self.detailTextLabel.frame = CGRectMake(self.detailTextLabel.frame.origin.x-widthSub,self.detailTextLabel.frame.origin.y,self.detailTextLabel.frame.size.width+widthSub,self.detailTextLabel.frame.size.height);
            self.imageView.contentMode = UIViewContentModeScaleAspectFit;
        }
    }
    @end
    
    ...
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        static NSString *CellIdentifier = @"Cell";
    
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        if (cell == nil) {
            cell = [[[SizableImageCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
            cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
        }
    
        cell.textLabel.text = ...
        cell.detailTextLabel.text = ...
        cell.imageView.image = ...
        return cell;
    }
    
        4
  •  23
  •   Rinju Jain    12 年前

    图像视图作为子视图添加到tableview单元格

    UIImageView *imgView=[[UIImageView alloc] initWithFrame:CGRectMake(20, 5, 90, 70)];
    imgView.backgroundColor=[UIColor clearColor];
    [imgView.layer setCornerRadius:8.0f];
    [imgView.layer setMasksToBounds:YES];
    [imgView setImage:[UIImage imageWithData: imageData]];
    [cell.contentView addSubview:imgView];
    
        5
  •  15
  •   Peter Robert    9 年前

    整个细胞不需要改造。您可以使用tableViewCells的indentationLevel和indentationWidth属性来移动单元格的内容。然后将自定义imageView添加到单元格的左侧。

        6
  •  6
  •   Warrior    14 年前

    最好创建一个图像视图,并将其作为子视图添加到单元格中,这样就可以得到所需的帧大小。

        7
  •  6
  •   Zaid Pathan    9 年前

    一个简单的 斯威夫特

    第一步: UITableViewCell
    第二步: 将此方法添加到UITableViewCell的子类

    override func layoutSubviews() {
        super.layoutSubviews()
        self.imageView?.frame = CGRectMake(0, 0, 10, 10)
    }
    

    在中使用该子类创建单元对象 cellForRowAtIndexPath

    Ex: let customCell:CustomCell = CustomCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
    

    享受

        8
  •  3
  •   Derek    8 年前

    这在斯威夫特对我有效:

    创建UITableViewCell的子类(确保在情节提要中链接单元格)

    class MyTableCell:UITableViewCell{
        override func layoutSubviews() {
            super.layoutSubviews()
    
            if(self.imageView?.image != nil){
    
                let cellFrame = self.frame
                let textLabelFrame = self.textLabel?.frame
                let detailTextLabelFrame = self.detailTextLabel?.frame
                let imageViewFrame = self.imageView?.frame
    
                self.imageView?.contentMode = .ScaleAspectFill
                self.imageView?.clipsToBounds = true
                self.imageView?.frame = CGRectMake((imageViewFrame?.origin.x)!,(imageViewFrame?.origin.y)! + 1,40,40)
                self.textLabel!.frame = CGRectMake(50 + (imageViewFrame?.origin.x)! , (textLabelFrame?.origin.y)!, cellFrame.width-(70 + (imageViewFrame?.origin.x)!), textLabelFrame!.height)
                self.detailTextLabel!.frame = CGRectMake(50 + (imageViewFrame?.origin.x)!, (detailTextLabelFrame?.origin.y)!, cellFrame.width-(70 + (imageViewFrame?.origin.x)!), detailTextLabelFrame!.height)
            }
        }
    }
    

        let cell = tableView.dequeueReusableCellWithIdentifier("MyCell", forIndexPath: indexPath) as! MyTableCell
    

    显然,更改数值以适应您的布局

        9
  •  2
  •   Adrian P ddr    11 年前
    UIImage *image = cell.imageView.image;
    
    UIGraphicsBeginImageContext(CGSizeMake(35,35));
    // draw scaled image into thumbnail context
    
    [image drawInRect:CGRectMake(5, 5, 35, 35)]; //
    UIImage *newThumbnail = UIGraphicsGetImageFromCurrentImageContext();
    // pop the context
    UIGraphicsEndImageContext();
    if(newThumbnail == nil)
    {
        NSLog(@"could not scale image");
        cell.imageView.image = image;
    }
    else
    {
        cell.imageView.image = newThumbnail;
    }
    
        10
  •  2
  •   diegoreymendez    9 年前

    我用@germanatanasio的答案创建了一个扩展。它提供了一种将图像大小调整为所需大小的方法,以及另一种在向图像添加透明边距时执行相同操作的方法(这对于希望图像也具有边距的表视图很有用)。

    import UIKit
    
    extension UIImage {
    
        /// Resizes an image to the specified size.
        ///
        /// - Parameters:
        ///     - size: the size we desire to resize the image to.
        ///
        /// - Returns: the resized image.
        ///
        func imageWithSize(size: CGSize) -> UIImage {
    
            UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.mainScreen().scale);
            let rect = CGRectMake(0.0, 0.0, size.width, size.height);
            drawInRect(rect)
    
            let resultingImage = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();
    
            return resultingImage
        }
    
        /// Resizes an image to the specified size and adds an extra transparent margin at all sides of
        /// the image.
        ///
        /// - Parameters:
        ///     - size: the size we desire to resize the image to.
        ///     - extraMargin: the extra transparent margin to add to all sides of the image.
        ///
        /// - Returns: the resized image.  The extra margin is added to the input image size.  So that
        ///         the final image's size will be equal to:
        ///         `CGSize(width: size.width + extraMargin * 2, height: size.height + extraMargin * 2)`
        ///
        func imageWithSize(size: CGSize, extraMargin: CGFloat) -> UIImage {
    
            let imageSize = CGSize(width: size.width + extraMargin * 2, height: size.height + extraMargin * 2)
    
            UIGraphicsBeginImageContextWithOptions(imageSize, false, UIScreen.mainScreen().scale);
            let drawingRect = CGRect(x: extraMargin, y: extraMargin, width: size.width, height: size.height)
            drawInRect(drawingRect)
    
            let resultingImage = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();
    
            return resultingImage
        }
    }
    
        11
  •  1
  •   FredericP    7 年前

    雨燕3

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        ...
        cell.imageView?.image = myImage
        let itemSize = CGSize(width:42.0, height:42.0)
        UIGraphicsBeginImageContextWithOptions(itemSize, false, 0.0)
        let imageRect = CGRect(x:0.0, y:0.0, width:itemSize.width, height:itemSize.height)
        cell.imageView?.image!.draw(in:imageRect)
        cell.imageView?.image! = UIGraphicsGetImageFromCurrentImageContext()!
            UIGraphicsEndImageContext()
    }
    
        12
  •  1
  •   robwithhair    7 年前

    如果你使用 cell.imageView?.translatesAutoresizingMaskIntoConstraints = false

    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 80
    }
    
    
    
        override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell(style: .subtitle, reuseIdentifier: String(describing: ChangesRequiringApprovalTableViewController.self))
    
        let record = records[indexPath.row]
    
        cell.textLabel?.text = "Title text"
    
        if let thumb = record["thumbnail"] as? CKAsset, let image = UIImage(contentsOfFile: thumb.fileURL.path) {
            cell.imageView?.contentMode = .scaleAspectFill
            cell.imageView?.image = image
            cell.imageView?.translatesAutoresizingMaskIntoConstraints = false
            cell.imageView?.leadingAnchor.constraint(equalTo: cell.contentView.leadingAnchor).isActive = true
            cell.imageView?.widthAnchor.constraint(equalToConstant: 80).rowHeight).isActive = true
            cell.imageView?.heightAnchor.constraint(equalToConstant: 80).isActive = true
            if let textLabel = cell.textLabel {
                let margins = cell.contentView.layoutMarginsGuide
                textLabel.translatesAutoresizingMaskIntoConstraints = false
                cell.imageView?.trailingAnchor.constraint(equalTo: textLabel.leadingAnchor, constant: -8).isActive = true
                textLabel.topAnchor.constraint(equalTo: margins.topAnchor).isActive = true
                textLabel.trailingAnchor.constraint(equalTo: margins.trailingAnchor).isActive = true
                let bottomConstraint = textLabel.bottomAnchor.constraint(equalTo: margins.bottomAnchor)
                bottomConstraint.priority = UILayoutPriorityDefaultHigh
                bottomConstraint.isActive = true
                if let description = cell.detailTextLabel {
                    description.translatesAutoresizingMaskIntoConstraints = false
                    description.bottomAnchor.constraint(equalTo: margins.bottomAnchor).isActive = true
                    description.trailingAnchor.constraint(equalTo: margins.trailingAnchor).isActive = true
                    cell.imageView?.trailingAnchor.constraint(equalTo: description.leadingAnchor, constant: -8).isActive = true
                    textLabel.bottomAnchor.constraint(equalTo: description.topAnchor).isActive = true
                }
            }
            cell.imageView?.clipsToBounds = true
        }
    
        cell.detailTextLabel?.text = "Detail Text"
    
        return cell
    }
    
        13
  •  1
  •   Neil Poulin    5 年前

    我也有同样的问题。感谢所有其他回答的人-我能够使用其中几个答案的一部分找到一个解决方案。

    我的解决方案是使用swift 5

    我们试图解决的问题是,我们的图像中可能有不同纵横比的图像 TableViewCell 但我们希望它们以一致的宽度渲染。当然,这些图像应该不失真地渲染并填充整个空间。在我的例子中,我对一些高而瘦的图片的“裁剪”很好,所以我使用了内容模式 .scaleAspectFill

    UITableViewCell . 就我而言,我给它起了个名字 StoryTableViewCell . 整个类都粘贴在下面,并内联注释。

    在使用自定义附件视图和长文本标签时,这种方法对我很有效。以下是最终结果的图像:

    Rendered Table View with consistent image width

    class StoryTableViewCell: UITableViewCell {
    
        override func layoutSubviews() {
            super.layoutSubviews()
    
            // ==== Step 1 ====
            // ensure we have an image
            guard let imageView = self.imageView else {return}
    
            // create a variable for the desired image width
            let desiredWidth:CGFloat = 70;
    
            // get the width of the image currently rendered in the cell
            let currentImageWidth = imageView.frame.size.width;
    
            // grab the width of the entire cell's contents, to be used later
            let contentWidth = self.contentView.bounds.width
    
            // ==== Step 2 ====
            // only update the image's width if the current image width isn't what we want it to be
            if (currentImageWidth != desiredWidth) {
                //calculate the difference in width
                let widthDifference = currentImageWidth - desiredWidth;
    
                // ==== Step 3 ====
                // Update the image's frame,
                // maintaining it's original x and y values, but with a new width
                self.imageView?.frame = CGRect(imageView.frame.origin.x,
                                               imageView.frame.origin.y,
                                               desiredWidth,
                                               imageView.frame.size.height);
    
                // ==== Step 4 ====
                // If there is a texst label, we want to move it's x position to
                // ensure it isn't overlapping with the image, and that it has proper spacing with the image
                if let textLabel = self.textLabel
                {
                    let originalFrame = self.textLabel?.frame
    
                    // the new X position for the label is just the original position,
                    // minus the difference in the image's width
                    let newX = textLabel.frame.origin.x - widthDifference
                    self.textLabel?.frame = CGRect(newX,
                                                   textLabel.frame.origin.y,
                                                   contentWidth - newX,
                                                   textLabel.frame.size.height);
                    print("textLabel info: Original =\(originalFrame!)", "updated=\(self.textLabel!.frame)")
                }
    
                // ==== Step 4 ====
                // If there is a detail text label, do the same as step 3
                if let detailTextLabel = self.detailTextLabel {
                    let originalFrame = self.detailTextLabel?.frame
                    let newX = detailTextLabel.frame.origin.x-widthDifference
                    self.detailTextLabel?.frame = CGRect(x: newX,
                                                         y: detailTextLabel.frame.origin.y,
                                                         width: contentWidth - newX,
                                                         height: detailTextLabel.frame.size.height);
                    print("detailLabel info: Original =\(originalFrame!)", "updated=\(self.detailTextLabel!.frame)")
                }
    
                // ==== Step 5 ====
                // Set the image's content modoe to scaleAspectFill so it takes up the entire view, but doesn't get distorted
                self.imageView?.contentMode = .scaleAspectFill;
            }
        }
    }
    
        14
  •  0
  •   P.J.Radadiya Yevgen THD    8 年前

    常规UITableViewCell可以很好地定位对象,但cell.imageView的行为似乎与您所希望的不一样。我发现,首先给cell.imageView一个大小合适的图像,让UITableViewCell正确布局非常简单,比如

    // Putting in a blank image to make sure text always pushed to the side.
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(kGroupImageDimension, kGroupImageDimension), NO, 0.0);
    UIImage *blank = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    cell.imageView.image = blank;
    

    然后,您就可以将自己正常工作的UIImageView与

    // The cell.imageView increases in size to accomodate the image given it.
    // We don't want this behaviour so we just attached a view on top of cell.imageView.
    // This gives us the positioning of the cell.imageView without the sizing
    // behaviour.
    UIImageView *anImageView = nil;
    NSArray *subviews = [cell.imageView subviews];
    if ([subviews count] == 0)
    {
        anImageView = [[UIImageView alloc] init];
        anImageView.translatesAutoresizingMaskIntoConstraints = NO;
        [cell.imageView addSubview:anImageView];
    
        NSLayoutConstraint *aConstraint = [NSLayoutConstraint constraintWithItem:anImageView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:cell.imageView attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.0];
        [cell.imageView addConstraint:aConstraint];
    
        aConstraint = [NSLayoutConstraint constraintWithItem:anImageView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:cell.imageView attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0.0];
        [cell.imageView addConstraint:aConstraint];
    
        aConstraint = [NSLayoutConstraint constraintWithItem:anImageView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0.0 constant:kGroupImageDimension];
        [cell.imageView addConstraint:aConstraint];
    
        aConstraint = [NSLayoutConstraint constraintWithItem:anImageView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0.0 constant:kGroupImageDimension];
        [cell.imageView addConstraint:aConstraint];
    }
    else
    {
        anImageView = [subviews firstObject];
    }
    

    将图像设置为anImageView,它将执行UIImageView所期望的操作。无论你给它什么样的图像,它都是你想要的尺寸。这个应该放在第五张桌子上iew:cellForRowAtIndexPath:

        15
  •  0
  •   Nick    7 年前

    CGSize itemSize = CGSizeMake(80, 80);
    UIGraphicsBeginImageContextWithOptions(itemSize, NO, UIScreen.mainScreen.scale);
    UIImage *image = cell.imageView.image;
    
    CGRect imageRect;
    if(image.size.height > image.size.width) {
        CGFloat width = itemSize.height * image.size.width / image.size.height;
        imageRect = CGRectMake((itemSize.width - width) / 2, 0, width, itemSize.height);
    } else {
        CGFloat height = itemSize.width * image.size.height / image.size.width;
        imageRect = CGRectMake(0, (itemSize.height - height) / 2, itemSize.width, height);
    }
    
    [cell.imageView.image drawInRect:imageRect];
    cell.imageView.image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
        16
  •  0
  •   Simon Bengtsson trumpeter201    5 年前

    我们最终得到的解决方案与其他许多解决方案相似。但是为了得到正确的分隔符位置,我们必须在调用之前设置它 super.layoutSubviews()

    class ImageTableViewCell: UITableViewCell {
    
        override func layoutSubviews() {
            separatorInset.left = 70
            super.layoutSubviews()
    
            imageView?.frame = CGRect(x: 0, y: 0, width: 50, height: 50)
            textLabel?.frame = CGRect(x: 70, y: 0, width: 200, height: 50)
        }
    
    }