How to show image in UITableViewCell with DTCoreTe

2019-03-14 10:06发布

I have DTAttributedTextContentView in UITableViewCell and try to load it with html (with image), but can't find a proper way to do this. I have look into DemoTextViewController.m in Demo which have image load with

- (void)lazyImageView:(DTLazyImageView *)lazyImageView didChangeImageSize:(CGSize)size {
    NSURL *url = lazyImageView.url;
    CGSize imageSize = size;

    NSPredicate *pred = [NSPredicate predicateWithFormat:@"contentURL == %@", url];

    // update all attachments that matchin this URL (possibly multiple images with same size)
    for (DTTextAttachment *oneAttachment in [_textView.attributedTextContentView.layoutFrame textAttachmentsWithPredicate:pred])
    {
        oneAttachment.originalSize = imageSize;

        if (!CGSizeEqualToSize(imageSize, oneAttachment.displaySize))
        {
            oneAttachment.displaySize = imageSize;
        }
    }

    // redo layout
    // here we're layouting the entire string, might be more efficient to only relayout the paragraphs that contain these attachments
    [_textView.attributedTextContentView relayoutText];
}

But I don't know how this will apply to UITableViewCell I tried

- (void)lazyImageView:(DTLazyImageView *)lazyImageView didChangeImageSize:(CGSize)size {
    NSURL *url = lazyImageView.url;
    CGSize imageSize = size;

    NSPredicate *pred = [NSPredicate predicateWithFormat:@"contentURL == %@", url];

    for (UITableViewCell *cell in self.tableView.visibleCells) {
        if ([cell isKindOfClass:[CommentCell class]]) {
            CommentCell *cc = (CommentCell *)cell;
            for (DTTextAttachment *oneAttachment in [cc.attributedTextContentView.layoutFrame textAttachmentsWithPredicate:pred])
            {
                oneAttachment.originalSize = imageSize;

                if (!CGSizeEqualToSize(imageSize, oneAttachment.displaySize))
                {
                    oneAttachment.displaySize = CGSizeMake(300, 100);
                }
            }
            [cc.attributedTextContentView relayoutText];
        }

    }

}

But the cell height not show correctly and the image isn't resize to fit DTAttributedTextContentView size. I can't find any document of how to implement this.

If you have a better choice or solution, please tell me.

1条回答
冷血范
2楼-- · 2019-03-14 10:14

I had difficulty getting this to work too, not much info around on this but I finally got it working. When you make your DTAttributedTextCell set the delegate of it's DTAttributedTextContentView property to your tableviewcontroller

cell.attributedTextContextView.delegate = self;

and implement this method:

- (UIView *)attributedTextContentView:(DTAttributedTextContentView *)attributedTextContentView viewForAttachment:(DTTextAttachment *)attachment frame:    (CGRect)frame{

    if([attachment isKindOfClass:[DTImageTextAttachment class]]){

       FVLazyImageView *imageView = [[FVLazyImageView alloc] initWithFrame:frame];
       imageView.contextView = attributedTextContentView;
       imageView.delegate = self;

       // url for deferred loading
       imageView.url = attachment.contentURL;
       return imageView;
   }
    return nil;
}

From inside this method create your DTLazyImageView and set its delegate. I made a subclass of DTLazyImageView to hold an extra property, a reference to the DTAttributedTextContentView of that individual cell, to be used when the DTLazyImageViewDelegate is called.

Then when - (void)lazyImageView:(DTLazyImageView *)lazyImageView didChangeImageSize:(CGSize)size is called take the lazyImageView variable that was passed and cast it to your subclass to get the DTAttributedTextContentView you stored. Use the same method that comes in the example but just replace the _textView.attributedTextContentView with the DTAttributedTextContentView you carried over.

Also be sure to make the cells the way he does in the DemoSnippetsViewController, if you're loading images you will need to have variable height cells and you must implement - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

Update for Stricklands question

I haven't touched my code in about a year so I'm not so sure about this. But here is what I think is happening. I never call - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath, I just implement it and it is called when the cell is reloaded. When is it reloaded? From what i gather, I implement the delegate for the lazy image view - (void)lazyImageView:(DTLazyImageView *)lazyImageView didChangeImageSize:(CGSize)size; So after the image is downloaded from the web, in that call I check if the image size has changed and call [DTAttributedTextContentView relayoutText] , which I think kicks off the reloading.

Here's my heightForRowAtIndexPath implementation:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    DTAttributedTextCell *cell = (DTAttributedTextCell *)[self tableView:tableView preparedCellForIndexPath:indexPath];
    if([indexPath isEqual:self.selectedIndex]){
        return MAX([cell requiredRowHeightInTableView:tableView] + 40,120);
    }
    return MAX([cell requiredRowHeightInTableView:tableView], 80);
}

Once the download is complete and the refresh is called it calls the [DTAttributedTextCell requiredRowHeightInTableView:] to pass along the new size with a small buffer.

查看更多
登录 后发表回答