Динамический размер ячейки в зависимости от размера изображения, полученного из URL-адреса в iOS


Информация:

У меня есть Tableview, который имеет ячейки с Imageview. В этой книги, я получения различных изображений из imgurl на панели...

Что мне нужно:

Мне нужна динамическая высота ячейки в соответствии с высотой изображения, полученного из imgURL.

Примечание: Я не использую автоматический макет, но я использую автоматическое изменение размера.

Что я делал до сих пор:

Я использовал асинхронную загрузку изображений в ImageView. ( по #import "UIImageView+WebCache.h")

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

    HomePostCell *cell=[tableView dequeueReusableCellWithIdentifier:strIdentifier];
    if (cell==nil) {
        cell = [[HomePostCell alloc]
                initWithStyle:UITableViewCellStyleDefault
                reuseIdentifier:strIdentifier];
    }

    [cell.imgMain sd_setImageWithURL:[NSURL URLWithString:strImgURL] placeholderImage:[UIImage imageNamed:@"postPlaceholder"] completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
        if (!error) {

    }];


    return cell;
}

прямо сейчас экран tableview

Есть ли какое-либо решение для этого? или мы можем использовать автоматическую разметку только для изменения размера ячейки?

Заранее благодарю..

3 2

3 ответа:

В идеальном случае я обычно ожидаю, что API вернет все изображения с одинаковым размером или размером, который можно настроить с помощью параметров строки запроса, таких как: /get_image/?width=400&height=400 и т. д.

В любом случае, проблема здесь заключается в том, что вы никак не можете обновить высоту ячейки, как только она была создана и готова к отображению на экране (другими словами, как только она была возвращена из cellForRowAtIndexPath) если только вы не перезагрузите эту ячейку или все представление таблицы вручную. К счастью для нас, sd_setImageWithURL работает в асинхронный способ, который означает, что у вас будет возможность вызвать tableView.reloadRowsAtIndexPath, как только образ будет извлечен и сохранен.

Перезагрузка вызовет вызов heightForRowAtIndexPath в перегруженной ячейке, поэтому на этот раз мы получим правильную высоту.

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

@interface ViewController ()

@property (nonatomic, strong) NSMutableArray *fetchedImages;
@end

@implementation ViewController
...

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
  UIImage *image = [self.fetchedImages objectAtIndex:indexPath.row];
  if (image) {
    return image.size.height + 1.0; // 1.0 for the separator.
  }
  else {
    return 50.0; // Default value..
  }
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  return self.fetchedImages.count;
}

Со всем сказанным, вы можете сделать что-то вроде следующего в (tableView:cellForRowAtIndexPath:) методе:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  ...

  UIImage *image = [self.fetchedImages objectAtIndex:indexPath.row];

  if (image) {
    // If there is image don't bother fetching the image.
    cell.imageView.image = image;
  }
  else {
    NSURL *imageURL = [self.imageURLs objectAtIndex:indexPath.row];
    [cell.imageView sd_setImageWithURL:imageURL placeholderImage:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
    if (image) {
      [self.fetchedImages replaceObjectAtIndex:indexPath.row withObject:image];
      [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
    }
  }];
  return cell;
}

Вот результат, который я получил:

Введите описание изображения здесь

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

Этот код работает с автоматическим изменением размера, может помочь вам.

#define Screen_Width [[UIScreen mainScreen] bounds].size.width
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
{
    return imageHeight;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
 NativeStreamAdCell *cell=(NativeStreamAdCell *)[tableView dequeueReusableCellWithIdentifier:@"SimpleTable"];
        if(cell==nil)
        {
            NSArray *nib=[[NSBundle mainBundle]loadNibNamed:@"NativeStreamAdCell" owner:self options:nil];
            cell=[nib objectAtIndex:0];
        }
         [cell.postImg sd_setImageWithURL:[NSURL URLWithString:[dic_feed valueForKey:@"feed_image"]] placeholderImage:cell.postImg.image options:SDWebImageRefreshCached];
        //Display image based on size
        UIImage *img = cell.postImg.image;

        int image_width = img.size.width;
        int image_height = img.size.height;
        image_width = Screen_Width;
        image_height = (Screen_Width * img.size.height / img.size.width);
        if(image_width > image_height) {
            image_height = (Screen_Width * image_height / image_width);
        }
        cell.postImg.frame = CGRectMake(cell.postImg.frame.origin.x, cell.postImg.frame.origin.y,
                                     image_width,image_height);

        imageHeight =  CGRectGetMaxY(cell.postImg.frame);
        return cell;
}

Последовал примеру Ozgur Vatansever , но он мигает при быстрой прокрутке.

Даже это не помогло.

Я обнаружил, что [self.tableView reloadData] работает вместо

[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];

Или

[weakSelf.tableView beginUpdates];
[weakSelf.tableView endUpdates];