【问题标题】:Dynamic cell size depending on the size of Image fetched from URL in iOS动态单元格大小取决于从 iOS 中的 URL 获取的图像大小
【发布时间】:2017-01-19 11:50:40
【问题描述】:

信息:

我有Tableview,它的单元格带有Imageview。 在那个 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;
}

有什么解决办法吗?还是我们可以只使用自动布局来调整单元格大小?

提前谢谢..

【问题讨论】:

  • 查看category
  • 你能提供在我的情况下如何使用它的方法
  • 该类别可以获取图像元数据,即 EXIF,其中包含有关图像分辨率的信息,因此您可以在下载图像之前获取图像大小,并提供给您的单元格大小。
  • 这会很复杂,除非服务器提前发送大小。否则,您将不得不下载然后获取高度。之后,重新加载表格。
  • @Shubhank 图像始终具有 EXIF 和分辨率。

标签: ios objective-c uitableview uiimage autoresize


【解决方案1】:

在理想情况下,我通常希望 API 返回所有具有相同大小或可以通过查询字符串参数配置的大小的图像,例如:/get_image/?width=400&height=400 等。

无论如何,这里的问题是,一旦单元格被创建并准备好被绘制到屏幕上,你就无法更新它的高度(换句话说,一旦它从cellForRowAtIndexPath返回) 除非您手动重新加载该单元格或整个表格视图。幸运的是,sd_setImageWithURL 以异步方式工作,这意味着您将有机会在获取并存储图像后调用 tableView.reloadRowsAtIndexPath

重新加载将导致在重新加载的单元格上调用heightForRowAtIndexPath,因此我们这次将获得正确的高度。

(由于表格视图单元格是可重用的对象,它们不存储任何关于它们用于配置其 UI 的数据的信息。因此,您需要将图像存储在视图控制器中,最好是在数组。)

@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;
}

这是我最终得到的结果:

您可以下载test project 并使用它来更好地了解我在上面所做的事情。

【讨论】:

    【解决方案2】:

    此代码可用于自动调整大小,可能会对您有所帮助。

    #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;
    }
    

    【讨论】:

      【解决方案3】:

      已关注example of Ozgur Vatansever,但在快速滚动时会闪烁。

      即使this 也无济于事。

      我发现 [self.tableView reloadData] 可以代替

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

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

      【讨论】:

        猜你喜欢
        • 2016-09-21
        • 2011-10-29
        • 2020-03-14
        • 1970-01-01
        • 1970-01-01
        • 2017-01-18
        • 1970-01-01
        • 1970-01-01
        • 2018-01-13
        相关资源
        最近更新 更多