Powered By Blogger
Showing posts with label kCGImagePropertyPixelWidth. Show all posts
Showing posts with label kCGImagePropertyPixelWidth. Show all posts

Monday, March 10, 2014

UICollectionView with dynamic image height

Hi,
Dear readers,

I had successfully used UICollectionView with dynamic heights of images which fetches data from NSURL string. iOS 6.0 and later versions can use "UICollectionView" to make a model like "Water Flow" or "Pinterest Layout".

Please see below steps to have it in your application.


=======================================================================

*** STEP 1 : 
A. Include these two files into your project source directory.
     1.) " CHTCollectionViewWaterfallLayout.h"
     2.) " CHTCollectionViewWaterfallLayout.m"
B. You can download these files from CHTCollectionViewWaterfallLayout .
C. Import "ImageIO.framework" into project.

=======================================================================

*** STEP 2:  

A) Generate two class files “CategoryCell.h” and “CategoryCell.m” for UICollectionViewCell.


#import "FXImageView.h"
@interface CategoryCell : UICollectionViewCell

@property (nonatomic, strong) UIButton *btnPhoto;
@property (nonatomic, strong) FXImageView *photoView;
@property (nonatomic, strong) UILabel *titleLabel;
@property (nonatomic, strong) UIView *bottomView;


#import "CategoryCell.h"

const CGFloat kTMPhotoQuiltViewMargin = 5;

@implementation CategoryCell

@synthesize photoView = _photoView;
@synthesize titleLabel = _titleLabel;
@synthesize btnPhoto = _btnPhoto;
@synthesize bottomView = _bottomView;

#pragma mark - Accessors

- (UILabel *)titleLabel {
if (!_titleLabel) {
_titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 0.0, self.contentView.bounds.size.width, 30.0)];
_titleLabel.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth;
_titleLabel.backgroundColor = [UIColor clearColor];
_titleLabel.textColor = WHITE_COLOR;
        if (IS_IPAD) {
            _titleLabel.font = FONT_BOLD(14.0);
        }
        else
        {
            _titleLabel.font = FONT_BOLD(12.0);
        }
_titleLabel.textAlignment = NSTextAlignmentCenter;
}
return _titleLabel;
}

- (UIView *)bottomView {
if (!_bottomView) {
_bottomView = [[UIView alloc] initWithFrame:CGRectMake(0.0, self.contentView.bounds.size.height - 30.0, self.contentView.bounds.size.width, 30.0)];
_bottomView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth;
_bottomView.backgroundColor = BLACK_COLOR;
        _bottomView.alpha = 0.6;
}
return _bottomView;
}

- (FXImageView *)photoView {
if (!_photoView) {
_photoView = [[FXImageView alloc] initWithFrame:self.contentView.bounds];
        _photoView.asynchronous = YES;
        _photoView.contentMode = UIViewContentModeScaleAspectFit;
_photoView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
_photoView.backgroundColor = CLEAR_COLOR;
        _photoView.layer.shadowOpacity = 2.0;
        _photoView.layer.shadowColor = LIGHT_GRAY_COLOR.CGColor;
        _photoView.layer.shadowRadius = 2.0;
        _photoView.layer.shadowOffset = CGSizeMake(-0.5, 0.5);
}
return _photoView;
}

- (UIButton *)btnPhoto{
if (!_btnPhoto) {
_btnPhoto = [UIButton buttonWithType:UIButtonTypeCustom];
        _btnPhoto.frame = self.contentView.bounds;
        _btnPhoto.contentMode = UIViewContentModeScaleAspectFill;
_btnPhoto.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
_btnPhoto.backgroundColor = CLEAR_COLOR;
        _btnPhoto.layer.shadowOpacity = 5.0;
        _btnPhoto.layer.shadowColor = LIGHT_GRAY_COLOR.CGColor;
        _btnPhoto.layer.shadowRadius = 5.0;
        _btnPhoto.layer.shadowOffset = CGSizeMake(-1.0, 1.0);
}
return _btnPhoto;
}

#pragma mark - Life Cycle

#if !__has_feature(objc_arc)
- (void)dealloc {
[_photoView removeFromSuperview];
_photoView = nil;
    
    [_titleLabel removeFromSuperview];
_titleLabel = nil;
    
    [super dealloc];
}
#endif

- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self.contentView addSubview:self.photoView];
        [self.contentView addSubview:self.btnPhoto];
        [self.bottomView addSubview:self.titleLabel];
        [self.contentView addSubview:self.bottomView];
}
return self;
}

@end

========================================================================

*** STEP 3:  

#import <ImageIO/ImageIO.h>

#import "CHTCollectionViewWaterfallLayout.h"
#define CELL_WIDTH 150.0
#define CELL_IDENTIFIER @"GCCategoryCell"
#import "CategoryCell.h"

@interface CategoryViewController () <UICollectionViewDataSource, CHTCollectionViewDelegateWaterfallLayout>
{
    NSMutableArray *cellHeights;
    NSMutableArray *arrCategory;
    UICollectionView *collectionView;
    CGFloat cellWidth;
}
@property (nonatomic, strong) NSMutableArray *cellHeights;
@property (nonatomic, strong) NSMutableArray * arrCategory;
@property (nonatomic, strong) UICollectionView *collectionView;
@property (nonatomic) CGFloat cellWidth;

@implementation CategoryViewController
@synthesize cellHeights;
@synthesize arrCategory;
@synthesize collectionView;

@synthesize cellWidth;

- (void)viewDidLoad
{
       self.arrCategory = [[NSMutableArray alloc] init];

        self.cellWidth = CELL_WIDTH;    // Default if not setting runtime attribute
        CHTCollectionViewWaterfallLayout *layout = [[CHTCollectionViewWaterfallLayout alloc] init];
        layout.sectionInset = UIEdgeInsetsMake(0.0, 10, 10, 5.0);
        layout.headerHeight = 0;
        layout.footerHeight = 0;
        if (IS_IPAD) {
            layout.minimumColumnSpacing = 30;
            layout.minimumInteritemSpacing = 30;
        }
        else
        {
            layout.minimumColumnSpacing = 5;
            layout.minimumInteritemSpacing = 5;
        }
        CGRect frame;
        if (IS_IPAD) {
            frame = CGRectMake(0, lblTitle.frame.size.height, self.view.frame.size.width, self.view.frame.size.height-36.0);
        }
        else
        {
            frame = CGRectMake(0, lblTitle.frame.size.height, self.view.frame.size.width, self.view.frame.size.height-(Appdel.objTab.frame.size.height + 36.0));
        }
        self.collectionView = [[UICollectionView alloc] initWithFrame:frame collectionViewLayout:layout];
        self.collectionView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
        self.collectionView.dataSource = self;
        self.collectionView.delegate = self;
        self.collectionView.backgroundColor = [UIColor clearColor];
        [self.collectionView registerClass:[GCCategoryCell class] forCellWithReuseIdentifier:CELL_IDENTIFIER];

        [self.view addSubview:self.collectionView];
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    [self updateLayoutForOrientation:[UIApplication sharedApplication].statusBarOrientation];
}

#pragma mark --------------------------
#pragma mark Accessors
#pragma mark --------------------------

- (NSMutableArray *)cellHeights
{
    if (!cellHeights)
    {
        cellHeights = [[NSMutableArray alloc] init];
    }
    return cellHeights;
}

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
                                         duration:(NSTimeInterval)duration {
    [super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation
                                            duration:duration];
    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"6.0")) {
        [self updateLayoutForOrientation:toInterfaceOrientation];
    }
}

- (void)updateLayoutForOrientation:(UIInterfaceOrientation)orientation
{
    CHTCollectionViewWaterfallLayout *layout = (CHTCollectionViewWaterfallLayout *)self.collectionView.collectionViewLayout;
    layout.columnCount = UIInterfaceOrientationIsPortrait(orientation) ? 2 : 3;
}

========================================================================

*** STEP 4:

// Call this method first to fill height array after you objects list
-(void)fillHeightArray
{
                for (NSMutableDictionary *dictGCCatInfo in self.arrCategory)
                {
                    NSNumber *width = [NSNumber numberWithFloat:200];
                    NSNumber *height = [NSNumber numberWithFloat:200];
                    
                    NSString *urlString = [dictGCCatInfo valueForKey:@"Photo"];
                    NSURL *imageFileURL = [NSURL URLWithString:urlString];
                    CGImageSourceRef imageSource = CGImageSourceCreateWithURL((__bridge CFURLRef)imageFileURL, NULL);
                    if (imageSource) {
                        NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:NO], (NSString *)kCGImageSourceShouldCache, nil];
                        CFDictionaryRef imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, (__bridge CFDictionaryRef)options);
                        if (imageProperties) {
                            width = (NSNumber *)CFDictionaryGetValue(imageProperties, kCGImagePropertyPixelWidth);
                            height = (NSNumber *)CFDictionaryGetValue(imageProperties, kCGImagePropertyPixelHeight);
                            CFRelease(imageProperties);
                        }
                    }
                    CFRelease(imageSource); // Added
                    CGSize size = CGSizeMake([width floatValue], [height floatValue]);
                    [self.cellHeights addObject:[NSValue valueWithCGSize:size]];
                }
[self.collectionView reloadData];
}

#pragma mark -----------------------------
#pragma mark UICollectionViewDataSource
#pragma mark -----------------------------

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return [arrCategory count];
}

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
    return 1;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView1 cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    CategoryCell *cell = (CategoryCell *)[collectionView1 dequeueReusableCellWithReuseIdentifier:CELL_IDENTIFIER
                                                                                       forIndexPath:indexPath];
    NSString *urlString = [[arrCategory objectAtIndex:indexPath.row] valueForKey:@"Photo"];
    if (urlString)
    {
        [cell.photoView setProcessedImage:nil];
        //set image
        [cell.photoView setImageWithContentsOfURL:[NSURL URLWithString:urlString]];
    }
    else
    {
        [cell.photoView setImage:[UIImage imageNamed:@"no-image.png"]];
    }
    [cell.photoView setTag:indexPath.row];
    [cell.btnPhoto setTag:indexPath.row];
    cell.titleLabel.text = [[arrCategory objectAtIndex:indexPath.row] valueForKey:@"GiftCertificateCatName"];
    [cell.btnPhoto addTarget:self action:@selector(btnCategoryClicked:) forControlEvents:UIControlEventTouchUpInside];
    return cell;
}

#pragma mark ------------------------------------
#pragma mark CHTCollectionViewDelegateWaterfallLayout
#pragma mark ------------------------------------

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
    CGSize size = [[self.cellHeights objectAtIndex:indexPath.row] CGSizeValue];
    return size;
}

Hope, you will fully enjoy this post about UICollectionView.

Best Regards,
Nilesh M. Prajapati