动态单元格大小取决于从 iOS 中的 URL 获取的图像大小
Dynamic cell size depending on the size of Image fetched from URL in iOS
信息:
我有 Tableview
,其中包含 Imageview
的单元格。
在该 Imageview 中,我正在从 imgURL 中获取不同的图像...
我需要的:
我需要根据从 imgURL 获取的图像高度来动态调整单元格高度。
NOTE: I am not using auto layout, but i am using auto resizing.
到目前为止我做了什么:
我在 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;
}
有什么解决办法吗?或者我们可以只使用自动布局来调整单元格大小吗?
提前致谢..
此代码可自动调整大小,可能对您有所帮助。
#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;
}
在理想情况下,我通常希望 API 到 return 所有具有相同大小或可以通过查询字符串参数配置的大小的图像,例如:/get_image/?width=400&height=400
等等
无论如何,这里的问题是,一旦单元格创建并准备好绘制到屏幕上,您就无法更新单元格的高度(换句话说,一旦它是 returned from cellForRowAtIndexPath
) 除非您手动重新加载该单元格或整个 table 视图。对我们来说幸运的是,sd_setImageWithURL
以异步方式工作,这意味着您将有机会在获取和存储图像后调用 tableView.reloadRowsAtIndexPath
。
重新加载将导致在重新加载的单元格上调用 heightForRowAtIndexPath
,因此这次我们将获得正确的高度。
(由于 table 视图单元格是可重复使用的对象,它们不会存储有关它们使用的数据的任何信息以配置其 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 并试用它以更好地理解我上面所做的事情。
已关注,但快速滚动时会闪烁。
甚至 this 也没有帮助。
我发现 [self.tableView reloadData]
而不是
[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
或
[weakSelf.tableView beginUpdates];
[weakSelf.tableView endUpdates];
信息:
我有 Tableview
,其中包含 Imageview
的单元格。
在该 Imageview 中,我正在从 imgURL 中获取不同的图像...
我需要的:
我需要根据从 imgURL 获取的图像高度来动态调整单元格高度。
NOTE: I am not using auto layout, but i am using auto resizing.
到目前为止我做了什么:
我在 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;
}
有什么解决办法吗?或者我们可以只使用自动布局来调整单元格大小吗?
提前致谢..
此代码可自动调整大小,可能对您有所帮助。
#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;
}
在理想情况下,我通常希望 API 到 return 所有具有相同大小或可以通过查询字符串参数配置的大小的图像,例如:/get_image/?width=400&height=400
等等
无论如何,这里的问题是,一旦单元格创建并准备好绘制到屏幕上,您就无法更新单元格的高度(换句话说,一旦它是 returned from cellForRowAtIndexPath
) 除非您手动重新加载该单元格或整个 table 视图。对我们来说幸运的是,sd_setImageWithURL
以异步方式工作,这意味着您将有机会在获取和存储图像后调用 tableView.reloadRowsAtIndexPath
。
重新加载将导致在重新加载的单元格上调用 heightForRowAtIndexPath
,因此这次我们将获得正确的高度。
(由于 table 视图单元格是可重复使用的对象,它们不会存储有关它们使用的数据的任何信息以配置其 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 并试用它以更好地理解我上面所做的事情。
已关注
甚至 this 也没有帮助。
我发现 [self.tableView reloadData]
而不是
[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
或
[weakSelf.tableView beginUpdates];
[weakSelf.tableView endUpdates];