Динамический размер ячейки в зависимости от размера изображения, полученного из 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;
}
Есть ли какое-либо решение для этого? или мы можем использовать автоматическую разметку только для изменения размера ячейки?
Заранее благодарю..
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];