Как мне сделать ImageView UITableViewCell фиксированного размера, даже когда изображение меньше - PullRequest
98 голосов
/ 07 мая 2010

У меня есть куча изображений, которые я использую для просмотра изображений в ячейке, все они не больше, чем 50x50. например 40х50, 50х32, 20х37 .....

Когда я загружаю табличное представление, текст не выравнивается, потому что ширина изображений изменяется. Также мне бы хотелось, чтобы маленькие изображения появлялись в центре, а не слева.

Вот код, который я пытаюсь использовать в моем методе cellForRowAtIndexPath

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];

Как видите, я пробовал несколько вещей, но ни одна из них не работает.

Ответы [ 15 ]

0 голосов
/ 09 мая 2019

У меня была такая же проблема.Спасибо всем, кто ответил - мне удалось найти решение, используя части нескольких из этих ответов.

Мое решение использует swift 5

Проблема, которую мы пытаемся решить, заключается в том, что у нас могут быть изображения с различными пропорциями в наших TableViewCell с, но мы хотим, чтобы они отображались с согласованнойширина.Изображения, конечно, должны отображаться без искажений и заполнять все пространство.В моем случае я справился с некоторым «обрезанием» высоких худых изображений, поэтому я использовал режим содержимого .scaleAspectFill

. Для этого я создал собственный подкласс UITableViewCell.В моем случае я назвал это StoryTableViewCell.Весь класс вставлен ниже, с комментариями.

Этот подход сработал для меня, когда я также использовал собственный вид аксессуара и длинные текстовые метки.Вот изображение окончательного результата:

Визуализированный табличный вид с постоянной шириной изображения

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;
        }
    }
}
0 голосов
/ 16 мая 2017

Если вы используете cell.imageView?.translatesAutoresizingMaskIntoConstraints = false, вы можете установить ограничения для imageView. Вот рабочий пример, который я использовал в проекте. Я избегал создания подклассов и не нуждался в создании раскадровки с ячейками-прототипами, но мне потребовалось довольно много времени, чтобы начать работать, поэтому, вероятно, лучше использовать его только в том случае, если нет более простого или более краткого способа, доступного для вас.

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
}
0 голосов
/ 29 апреля 2017

Вот метод работы @germanattanasio, написанный для Swift 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()
}
0 голосов
/ 07 апреля 2017

Это решение, по существу, рисует изображение как «аспектное соответствие» в пределах данного прямоугольника.

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();
0 голосов
/ 05 августа 2015

Обычный UITableViewCell хорошо работает для позиционирования вещей, но cell.imageView, похоже, ведет себя не так, как вы этого хотите.Я обнаружил, что достаточно просто правильно настроить UITableViewCell, сначала предоставив cell.imageView изображение правильного размера, например

// 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.Будьте размером, который вы хотите, независимо от изображения, которое вы даете.Это должно идти в tableView: cellForRowAtIndexPath:

...