I have a UICollectionView. No caching as I haven't needed to apply so far, only have sum of 7 different images, but possibly 40 cells. I am also not experienced in that method.
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
UIImageView *collectionImageView = (UIImageView *)[cell viewWithTag:102];
UILabel *ballLabel = (UILabel *)[cell viewWithTag:103];
UILabel *ballLabelInfo = (UILabel *)[cell viewWithTag:110];
ballShot *selectedBall = [self.statsView.visitBallShotCollection objectAtIndex:indexPath.row];
NSString *ballDetail;
NSString *labelInfo;
ballDetail = [NSString stringWithFormat:#"Foul"];
labelInfo = [NSString stringWithFormat:#"%#",[selectedBall getFoulTypeText:selectedBall.foulid]];
collectionImageView.image = [UIImage imageNamed:selectedBall.imageNameLarge];
ballLabel.text = ballDetail;
ballLabelInfo.text = labelInfo;
return cell;
}
I am able to save displayed content of UICollectionView with even the correct content size, but not whole content.
- (UIImage *) imageWithCollectionView:(UICollectionView *)collectionBreakView
{
CGSize widthHeight = CGSizeMake(collectionBreakView.contentSize.width, collectionBreakView.contentSize.height);
UIGraphicsBeginImageContextWithOptions(widthHeight, collectionBreakView.opaque, 0.0);
[collectionBreakView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
How can I obtain whole content and place into the UIImage? If caching is the answer can somebody please give me a starter in setting that up?
Thanks in advance.
Related
My UICollectionView has a UIImageView with autolayout constraints. I require a fixed number of cells in a row so need to scale the image if cell requires.
Even if I do not resize the cells, but set UIimageView in storyboard larger than the cells expected dimension the first time cell is populated the image size is incorrect, however when each cell is reused afterwards they scale perfectly.
The scaling works once cells are reused, but please what am I missing?
example view is the second call to reloaddata on the 'balls' lower middle of view. The first call filled the first 4 cells. The second call corrects the now reused cells, but fails to scale the 4 new cells content.
Below is some code as requested. generalBreakCollection is in focus :
- (UICollectionViewCell *) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
if (collectionView == self.p1HiBreakCollection) {
breakBallCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:#"P1Cell" forIndexPath:indexPath];
UIImageView *collectionImageView = (UIImageView *)[cell viewWithTag:106];
ballShot *selectedBall = [self.p1BreakBalls objectAtIndex:indexPath.row];
cell.ball = [self.p1BreakBalls objectAtIndex:indexPath.row];
collectionImageView.image = [UIImage imageNamed:selectedBall.imageNameLarge];
return cell;
} else if (collectionView == self.p2HiBreakCollection) {
breakBallCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:#"P2Cell" forIndexPath:indexPath];
UIImageView *collectionImageView = (UIImageView *)[cell viewWithTag:108];
ballShot *selectedBall = [self.p2BreakBalls objectAtIndex:indexPath.row];
cell.ball = [self.p2BreakBalls objectAtIndex:indexPath.row];
collectionImageView.image = [UIImage imageNamed:selectedBall.imageNameLarge];
return cell;
} else {
// generalBreakCollection
breakBallCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:#"GeneralCell" forIndexPath:indexPath];
ballShot *selectedBall = [self.breakShots objectAtIndex:indexPath.row];
cell.ball = [self.breakShots objectAtIndex:indexPath.row];
cell.ballStoreImage.image = [UIImage imageNamed:selectedBall.imageNameLarge];
cell.ballStoreImage.highlightedImage = [UIImage imageNamed:[NSString stringWithFormat:#"highlighted_%#",selectedBall.imageNameLarge]];
cell.ballStoreImage.contentMode = UIViewContentModeScaleAspectFit;
return cell;
}
}
The resize block contains:
- (CGSize)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
if (collectionView == self.generalBreakCollection) {
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenWidth = screenRect.size.width;
float cellWidth = screenWidth / 10.0; //Replace the divisor with the column count requirement. Make sure to have it in float.
CGSize size = CGSizeMake(cellWidth, cellWidth);
return size;
}
else {
CGSize defaultSize = [(UICollectionViewFlowLayout*)collectionViewLayout itemSize];
return defaultSize ;
}
}
I have my own UICollectionViewCell class with a UIImageView property ballStoreImage. I do not do so much with it, but I have linked it to the UIImageView inside the cell in the storyboard:
#property (strong, nonatomic) IBOutlet UIImageView *ballStoreImage;
The autolayout was not getting recognised until I added the code line:
[[cell contentView] setFrame:[cell bounds]];
So full block reads:
} else {
breakBallCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:#"breakCell" forIndexPath:indexPath];
[[cell contentView] setFrame:[cell bounds]];
ballShot *selectedBall = [self.breakShots objectAtIndex:indexPath.row];
cell.ball = [self.breakShots objectAtIndex:indexPath.row];
cell.ballStoreImage.image = [UIImage imageNamed:selectedBall.imageNameLarge];
cell.ballStoreImage.highlightedImage = [UIImage imageNamed:[NSString stringWithFormat:#"highlighted_%#",selectedBall.imageNameLarge]];
return cell;
}
I have an UICollectionView and I want to load picture from web to the UIImageView which on cell. (The UIImageView with tag:100 on the cell.)
The picture isn't appear when I use this method:
- (void)viewDidLoad
{
[super viewDidLoad];
Img = [NSArray arrayWithObjects:#"http://192.168.1.103:8088/Images/1.png",#"http://192.168.1.103:8088/Images/2.png",nil];
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = #"List";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
UIImageView *chImage = (UIImageView *)[cell viewWithTag:100];
NSURL *imageUrl = [NSURL URLWithString:[Img objectAtIndex:indexPath.row]];
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:imageUrl]];
chlImage.image = image;
NSLog("%#",[Img objectAtIndex:indexPath.row]); //Here can show Img's values correctly
cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"backgroung.png"]];
return cell;
}
But when I use the picture in project, it can appear correctly. like this:
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = #"List";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
UIImageView *chImage = (UIImageView *)[cell viewWithTag:100];
chImage.image = [UIImages imageNames:#"123.jpg"];
cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"backgroung.png"]];
return cell;
}
Why it can't work when I used picture load from web? (The picture can be opened by "browser".)
Can give me some tips or correct code? Thank you very much!
You are expecting to get an UIImageView from this line:
UIImageView *chImage = (UIImageView *)[cell viewWithTag:100];
But you are not. You are getting just an UIView. So you must create an UIImageView and then use addSubview: method to add this UIImageView to the backgroudViewView.
So, it should be:
UIImageView *chImage = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, cell.backgroundView.frame.size.width,cell.backgroundView.frame.size.height)];
NSURL *imageUrl = [NSURL URLWithString:[Img objectAtIndex:indexPath.row]];
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:imageUrl]];
chImage.image = image;
NSLog("%#",[Img objectAtIndex:indexPath.row]); //Here can show Img's values correctly
[cell.backgroundView addSubview:chImage];
And finally, I have a suggestion for you. Take a look at SDWebImage library. It's an awesome feature to fetch images from URL.
Create a class ImageCell by subclassing UICollectioViewCell and create a property ImageCell.h:
#interface ImageCell : UICollectionViewCell
#property (nonatomic, strong) UIImage *dImage;
#end
Then add a function in ImageCell.m
- (void)downloadImageFromURL:(NSURL *)imageUrl
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dImage = [UIImage imageWithData:[NSData dataWithContentsOfURL:imageUrl]];
dispatch_sync(dispatch_get_main_queue(), ^{
UIImageView *chImageView = (UIImageView *)[cell viewWithTag:100];
chImageView.image = dImage;
});
});
}
Now from UICollectionView delegate:
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = #"List";
ImageCell *cell = (ImageCell *)[collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
NSURL *imageUrl = [NSURL URLWithString:[Img objectAtIndex:indexPath.row]];
[cell downloadImageFromURL:imageUrl];
cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"background.png"]];
return cell;
}
And at last please make sure that you set the tag 100 to that ImageView you are trying to get. Let me know if you have any confusions.
Simply move your data fetching part from the collection view's delegate to it's viewDidLoad.
Store the images into an array. And use this as the datasource for your collection view.
ie.Each time an image gets added to the array just reload the collection view.
Or you could create a custom cell that does this as 'iOSGeek' suggested.
I'm pretty new to Objective-C so hopefully this all makes sense..I ran code provided in first answer Creating a UICollectionView programmatically..It is working fine .Now i want to add some pictures in cell that can expanded by mouse click .I searched many tutorial but all using nib files or storyboard files .How i can accomplish this task programmatically ?
Any help would be greatly appreciated. Thanks in advance.
as Logan suggest:
#define IMG_TAG 1000
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"MyCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
cell.textLabel.text = #"test.....";
UIImage * img = [UIImage imageNamed: #"sampleImage"];
UIImageView * customImageView = (UIImageView*) [cell viewWithTag: IMG_TAG];
// two cases:
// 1) we got a "recycled" cell, so we already have an image view added
// 2) we got a "new" cell, so we must create, add image view AND TAg
// in both cases we will set image
if (customImageView){
// case 1
// nothing special
}else{
// case 2:
// add and tag:
customImageView = [[UIImageView alloc]initWithFrame:CGRectMake(100, 2, 30, 30)];
[cell addSubview: customImageView];
customImageView.tag = IMG_TAG;
}
customImageView.image = img;
return cell;
}
pls review and upvote :)
Beginner read tutroial and understand first everyting in below link and apple doc
ios-programming-uicollectionview-tutorial-with-sample-code
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UICollectionView_class/Reference/Reference.html
change this your blackground color like this approach
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:#"cellIdentifier" forIndexPath:indexPath];
UIImageView *recipeImageView = (UIImageView *)[cell viewWithTag:100];
recipeImageView.image = [UIImage imageNamed:[recipeImages objectAtIndex:indexPath.row]];
cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"photo-frame.png"]];
[self.view addSubview:recipeImageView];
cell.backgroundColor=[UIColor colorWithPatternImage:[UIImage imageNamed:[recipeImages objectAtIndex:indexPath.row]]];
return cell;
}
output:
NOTE:
code above is WRONG!
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:#"cellIdentifier" forIndexPath:indexPath];
UIImageView *recipeImageView = (UIImageView *)[cell viewWithTag:100];
recipeImageView.image = [UIImage imageNamed:[recipeImages objectAtIndex:indexPath.row]];
cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"photo-frame.png"]];
[self.view addSubview:recipeImageView];
cell.backgroundColor=[UIColor colorWithPatternImage:[UIImage imageNamed:[recipeImages objectAtIndex:indexPath.row]]];
return cell;
}
You allocate (better to allocate ONCE unsung TAGs...) but the code will ADD subview EVERY time cellForItemAtIndexPath is called.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Set the data for this cell:
cell.textLabel.text = [namesArray objectAtIndex:indexPath.row];
cell.textLabel.textColor = [UIColor grayColor];
cell.textLabel.font = [UIFont fontWithName:#"Trebuchet MS" size:14];
cell.textLabel.textAlignment = UITextAlignmentLeft;
cell.imageView.image = [UIImage imageNamed:[imagesArray objectAtIndex:indexPath.row ]];
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 5, 5)];
imgView.image = [UIImage imageNamed:[imagesArray objectAtIndex:indexPath.row ]];
cell.imageView.image = imgView.image;
[cell.imageView setFrame:CGRectMake(0, 0, 55, 55)];
cell.selectionStyle = UITableViewCellSelectionStyleGray;
return cell;
}
Here I'm using just TableView not UITableViewCell, but I want to resize images on TableView. I've taken a look at many examples on the internet, however I don't understand how any of them work - I'm not able to get them resized on TableView. Could someone explain how to get it working? [cell.imageView setFrame:CGRectMake(0, 0, 55, 55)]; is not working
Here i put logic of both Crop and resize image, use it as per your requirement.
For Get Cropped Image:
UIImage *croppedImg = nil;
CGRect cropRect = CGRectMake(AS YOu Need); // set frame as you need
croppedImg = [self croppIngimageByImageName:self.imageView.image toRect:cropRect];
The following method that return UIImage (as You want size of image)
- (UIImage *)croppIngimageByImageName:(UIImage *)imageToCrop toRect:(CGRect)rect
{
//CGRect CropRect = CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height+15);
CGImageRef imageRef = CGImageCreateWithImageInRect([imageToCrop CGImage], rect);
UIImage *cropped = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return cropped;
}
Here you get Croped Image that return by above method;
OR RESIZING
And also use following method with specific hight and width of image for Resizing:
+ (UIImage*)resizeImage:(UIImage*)image withWidth:(CGFloat)width withHeight:(CGFloat)height
{
CGSize newSize = CGSizeMake(width, height);
CGFloat widthRatio = newSize.width/image.size.width;
CGFloat heightRatio = newSize.height/image.size.height;
if(widthRatio > heightRatio)
{
newSize=CGSizeMake(image.size.width*heightRatio,image.size.height*heightRatio);
}
else
{
newSize=CGSizeMake(image.size.width*widthRatio,image.size.height*widthRatio);
}
UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
This method return NewImage, with specific size that you want.
If you want to customize the aspect of the cell (for example the size of the image view) you need to use a custom UITableViewCell. Currently you are using a standard cell UITableViewCellStyleDefault which doesn't let you customize the size of the image view.
Create an UITableViewCell in storyboard or in a Xib file, add it your image view and set its tag to a number. After that you need to retrieve the cell for configuring it:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CellIdentifier";
UITableViewCell *cell = (UITableViewCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
UIImageView *imageView = (UIImageView *) [cell viewWithTag:TAG_NUMBER];
// do your stuff
return cell;
}
Maybe you can do something like this. Just add a new imageView under the cell's contentView atleast it will be easier for you to set the frame.
And just to clarify you are already using UITableviewCell.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
// Create a new imageview to have your desired frame
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 5, 5)];
// Add tag
imgView.tag = 100;
// Add the imageView to the contentView of the cell
[cell.contentView addSubview:imgView];
}
// Other codes
UIImageView *imageV = (UIImageView *)[cell.contentView viewWithTag:100];
// Assign Image here
imageV.image = [UIImage imageNamed:[imagesArray objectAtIndex:indexPath.row ]];
cell.selectionStyle = UITableViewCellSelectionStyleGray;
return cell;
}
I'm new building UICollectionView and I have an issue. I would like to display images that have 300px width and calculate the right height scale. To do this, I did :
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [cv dequeueReusableCellWithReuseIdentifier:#"MyCell" forIndexPath:indexPath];
UIImage *image = [photos objectAtIndex:indexPath.row];
if(image){
UIImageView *imageView = [[UIImageView alloc]initWithImage:image];
float scale = (image.size.height/image.size.width)*300;
[imageView setFrame:CGRectMake(imageView.frame.origin.x, imageView.frame.origin.y, 300, scale )];
[cell addSubview:imageView];
cell.backgroundColor = [UIColor clearColor];
}else{
cell.backgroundColor = [UIColor redColor];
}
return cell;
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
UIImage *image = [photos objectAtIndex:indexPath.row];
float scale = (image.size.height/image.size.width)*300;
return CGSizeMake(300, scale);
}
This seems to work at the beginning but as soon as I scroll down, images start to overlap each others. Is that any way to avoid this ?
You have to resize cells in UICollectionView, use UICollectionViewFlowLayout
Check out the Ray Wenderlich Tutorial: http://www.raywenderlich.com/22324/beginning-uicollectionview-in-ios-6-part-12