I tried to add checkmark image to cell but i have a problem, i just select 1 cell although i set the multiselection = YES for collectionview. And 1 more issue is when I scroll the collectionview, the selected cell is reuse, all checkmark images is incorrect. Below is the code i'm using.
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
TDPhotoCell *photoCell =
[collectionView dequeueReusableCellWithReuseIdentifier:TDPhotoCellIdentifier forIndexPath:indexPath];
TDPhoto *photo = self.photosArray[indexPath.row];
[photoCell.photoImage sd_setImageWithURL:photo.imageURL placeholderImage:[UIImage imageNamed:#"placeholder.png"] completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL)
{
[activity removeFromSuperview];
}];
if (self.isSelectMode) {
// check the selected photo
if (self.selectedItemIndexPath != nil && [indexPath compare:self.selectedItemIndexPath] == NSOrderedSame) {
UIImageView *CheckedImage = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 102, 102)];
CheckedImage.tag = 118;
CheckedImage.image = [UIImage imageNamed:#"Checked_Overlay"];
[photoCell.contentView addSubview:CheckedImage];
} else {
//remove checkimage
for(UIImageView *IMGview in photoCell.contentView.subviews)
{
if (IMGview.tag == 118) {
[IMGview removeFromSuperview];
}
}
}
}
return photoCell;
}
and this is didSelectItemAtIndexPath():
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSMutableArray *indexPaths = [NSMutableArray arrayWithObject:indexPath];
if (self.selectedItemIndexPath)
{
// if we had a previously selected cell
if ([indexPath compare:self.selectedItemIndexPath] == NSOrderedSame)
{
// if it's the same as the one we just tapped on, then we're unselecting it
self.selectedItemIndexPath = nil;
}
else
{
// if it's different, then add that old one to our list of cells to reload, and
// save the currently selected indexPath
[indexPaths addObject:self.selectedItemIndexPath];
self.selectedItemIndexPath = indexPath;
}
}
else
{
// else, we didn't have previously selected cell, so we only need to save this indexPath for future reference
self.selectedItemIndexPath = indexPath;
}
// and now only reload only the cells that need updating
[collectionView reloadItemsAtIndexPaths:indexPaths];
}
}
Where is the incorrect in my code? Pls. give me some advice. Thanks in advance.
Related
I have 4 UICollectionViewCell in which I want to make first 2 cell to have image in it mandatory. Sample code is as below. Below is a usecase:
There are 4 UICollectionViewCell if I click on each cell will open camera and we can either take a photo or select image from image gallery. How to know first 2 cell must have image. Looking for condition to check this logic.
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
Image *image = (Image *)self.defect.imageSet[indexPath.item];
ADRPhotoCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([ADRPhotoCollectionViewCell class]) forIndexPath:indexPath];
cell.image = image.thumbnailImage ? image.thumbnailImage : nil;
cell.photoType = [self.defect defectPhotoTypeForIndex:indexPath];
return cell;
}
#pragma mark - UICollectionViewDelegate
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
Image *image = self.defect.imageSet[indexPath.item];
if (self.selectedImage != image) {
[self updateAnnotatedImage];
self.selectedImage = image;
[self.jotController clearAll];
[self updateUserInterface];
if (image.thumbnailImage) {
[self transitionImage:YES];
} else {
self.imageView.image = nil;
[self showCameraPicker];
}
} else if (!image.thumbnailImage) {
//clicked the + to add a new image
[self showCameraPicker];
}
}
You can check if there is an image in UIImageView or not by this way:
-(BOOL) checkImages {
for (int i=0, i<2 , i++) {
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
ADRPhotoCollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
if (cell.imageView.image == nil || CGSizeEqualToSize(cell.imageView.image.size, CGSizeZero)) {
//there isn't any image or the image is empty
return NO;
}
}
return YES;
}
Hello every one please help me in this:
As I took a UICollectionView in this UICollectionView I am adding the images, I want to delete a particular Image on button click.
the image I want to delete is having the close button on it.
How could I perform this task.
Note:
1)Please see the image once before helping.
2)Please see the code I did for adding Image.
Image:
My Image
//**** For image work ****
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *ident = #"Cell";
OwnerPropertyCollectionViewCell *cell = (OwnerPropertyCollectionViewCell*)[collectionView dequeueReusableCellWithReuseIdentifier:ident forIndexPath:indexPath];
imgView = (UIImageView*)[cell viewWithTag:100];
if (indexPath.row ==0) {
cell.Imgprofile_pic.image = [UIImage imageNamed:[imgArray objectAtIndex:indexPath.row]];
cell.btnImageCancel.image = [UIImage imageNamed:#"add"];
UITapGestureRecognizer *reconizer = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(addphoto:)];
[cell addGestureRecognizer:reconizer];
}
else {
// get image not name
cell.Imgprofile_pic.image = [imgArray objectAtIndex:indexPath.row];
cell.btnImageCancel.image = [UIImage imageNamed:#"close"];
}
return cell;
}
// To add image:
-(void)addphoto:(UITapGestureRecognizer*)reconizer
{
imageHelper = [UIImagePickerHelper new];
[imageHelper imagePickerInViewController:self WithSuccess:^(UIImage *image) {
imgView.image = image;
[imgArray addObject:image];
[self.collectionView reloadData];
} failure:^(NSError *error) {
}];
NSLog(#"Image added successfully");
}
// What to code for delete image:
- (IBAction)btnCancelButtonAction:(id)sender {
NSLog(#"Delete button pressed");
}
Take a tag value as a cell index path for your selected delete button.(ex : for first row button tag will be 0)
then remove that image from your array. Then reload your UICollectionView
[imgArray removeObjectAtIndex:index];
[self.collectionView reloadData];
First of all add the following lines
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.yourCollectionView];
NSIndexPath *indexPath = [self.yourCollectionView indexPathForItemAtPoint:buttonPosition];
in this way you get the indexpath of the item and then
[YourImageArray removeObjectAtIndex:indexPath];
[self.yourCollectionView reloadData];
If need any help ask me
I have a UICollectionView that holds 10 items (images retrieved from Parse.com) Every cell covers the entire screen and it is set as a Horizontal Scroll.
Inside the cell I have a 'Like Button' that when clicked it changes color. The problem is that if I click the like button in cell 1 then cell 3, cell 5, and so on also changes the buttons color.. and if I click on cell 0 then cell 2, cell 4 and so on changes it color also.
I tried changing the UICollectionView cells size and made is so that the 10 cells fit in the screen. When I did that, no buttons repeated. The only change was in the button I clicked. Any thoughts as why this is happening and how can I fix it? I need the Cells to be the entire Screen.
My Code:
VestimentaDetailViewController.m
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return 10;
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"Cell";
VestimentaDetailCell *cell = (VestimentaDetailCell *) [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
cell.progressView.hidden = NO;
[cell.progressView setProgress:0.02];
cell.imageFile.image = [UIImage imageNamed:#"loadingLook.png"];
PFFile *storeLooks = [self.vestimenta objectForKey:[NSString stringWithFormat:#"image_%ld", (long)indexPath.item]];
[storeLooks getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
if (!error && data.length > 0) {
cell.imageFile.image = [UIImage imageWithData:data];
} else {
cell.progressView.hidden = YES;
}
} progressBlock:^(int percentDone) {
float percent = percentDone * 0.02;
[cell.progressView setProgress:percent];
if (percentDone == 100){
cell.progressView.hidden = YES;
} else {
cell.progressView.hidden = NO;
}
}];
return cell;
}
VestimentaDetailCell.m
- (IBAction)likeLook:(id)sender {
if ([sender isSelected]) {
[sender setImage:[UIImage imageNamed:#"Like.png"] forState:UIControlStateNormal];
[sender setSelected:NO];
} else {
[sender setImage:[UIImage imageNamed:#"Liked.png"] forState:UIControlStateSelected];
[sender setSelected:YES];
NSLog(#"Liked Image");
}
}
Collection and table views recycle their cells. I think what's happening is that if you like cell 1 then cell 3, cell 5, so on... are all using a recycled cell 1.
To fix this, set the button color for all cells the are being dequeued into cellForRowAtItemPath to be the default button color.
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
// get cell and stuff
...
cell.likeButton.backgroundColor = [UIColor whiteColor];
}
My problem is that the ProgressView only shows up in the first 2 cells. What is wrong with my code?
Note: My CollectionView scrolls horizontally and each cell covers the whole screen. I think this might have something to do since I tried showing all cells in the same view and they work fine. All ProgressViews show.
EDITED CODE:
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"Cell";
VestimentaDetailCell *cell = (VestimentaDetailCell *) [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
cell.progressView.hidden = NO;
[cell.progressView setProgress:0.02];
PFFile *storeLooks = [self.vestimenta objectForKey:[NSString stringWithFormat:#"image_%ld", (long)indexPath.item]];
NSMutableString *precio = [NSMutableString string];
for (NSString* precios in [self.vestimenta objectForKey:[NSString stringWithFormat:#"precios_%ld", (long)indexPath.item]]) {
[precio appendFormat:#"%#\n", precios];}
[storeLooks getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
if (!error && data.length > 0) {
cell.imageFile.image = [UIImage imageWithData:data];
} else {
cell.progressView.hidden = YES;
}
} progressBlock:^(int percentDone) {
float percent = percentDone * 0.02;
[cell.progressView setProgress:percent];
if (percentDone == 100){
cell.progressView.hidden = YES;
} else {
cell.progressView.hidden = NO;
}
}];
return cell;
}
Instead of removing the progress view from the cell, you should simply setHidden:YES.
This way when the cells are reused, the progress view will be present and you can then setHidden:NO when you want to start loading stuff in that cell.
Also be careful with progress blocks inside your cells when they are reused. Remember to either cancel the loading operation if the cell is reused, or make sure the progress block only continues updating it's cell if the cell hasn't been reused for a different data item.
So for example I would set the progress to 0. where you're showing the progress view like so:
VestimentaDetailCell *cell = (VestimentaDetailCell *) [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
cell.progressView.hidden = NO;
[cell.progressView setProgress:0.];
And because you're hiding the progressView when the data is finished loading, I would just get rid of this code in the progressBlock:
if (percentDone == 100){
cell.progressView.hidden = YES;
} else {
cell.progressView.hidden = NO;
}
I think this is related to the cells being reused as they come on screen. Since you are removing the progressView from the cell [cell.progressView removeFromSuperview] , once it is dequeued, it is still missing. You could try overriding the prepareForReuse method in your VestimentaDetailCell class to add it back so that all dequeued cells are brought back to their original state.
I am trying to select a cell in UICollectionView, it gets selected but on scroll down it selects the some other cell on the bottom and scroll up it shows some other to be selected.
Below is the code which I am using didSelectItemAtIndexPath
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSIndexPath *newIndex = indexPath;
cell = (CustomCollectionCell *)[collectionView cellForItemAtIndexPath:newIndex];
NSString *strId = [[masterArray valueForKey:#"id"]objectAtIndex:indexPath.row];
NSString *tempIndexRow = [NSString stringWithFormat:#"%ld",(long)indexPath.row];
NSLog(#"%#, %#,%d ,%#, %d", strId,tempIndexRow,cell.imageView.tag,[boolArray objectAtIndex:indexPath.row],indexPath.row);
if (strId && [[boolArray objectAtIndex:indexPath.row] isEqualToString:#"False"] && cell.imageView.tag == indexPath.row) {
cell.selectedImage.image = [UIImage imageNamed:#"select.png"];
[boolArray replaceObjectAtIndex:indexPath.row withObject:#"True"];
}
else{
cell.selectedImage.image = Nil;
[boolArray replaceObjectAtIndex:indexPath.row withObject:#"False"];
}
}
This is what I select for the first time
This is what I get when I scroll down
Thanks
You need to set selected item index store in to one array and at cellForRowIndex time check this array index with indexPath.row like bellow:-
selectedCellsArray alloc this array at ViewDIdLoad method
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
cell = (CustomCollectionCell *)[collectionView cellForItemAtIndexPath:newIndex];
if ( [selectedCellsArray containsObject:[NSString stringWithFormat:#"%d",indexPath.row]] )
{
[selectedCellsArray removeObject:[NSString stringWithFormat:#"%d",indexPath.row]];
cell.selectedImage.image = Nil;
}
else
{
[selectedCellsArray addObject:[NSString stringWithFormat:#"%d",indexPath.row]];
cell.selectedImage.image = [UIImage imageNamed:#"select.png"];
}
}
and
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
NSNumber *rowNsNum = [NSNumber numberWithUnsignedInt:indexPath.row];
if ( [selectedCellsArray containsObject:[NSString stringWithFormat:#"%#",rowNsNum]] )
{
cell.selectedImage.image = [UIImage imageNamed:#"select.png"];
}
else
{
cell.selectedImage.image = Nil;
}
}
It is not selecting another cell. Problem is mostlikely due to you reusing cells and not reintializing them correctly when they come back on the screen. When Cells not visible, it unloaded to save memory.
So better check this condtion as well in cellForItemAtIndexPath datasource
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
//You cell initialization code.
if ([[boolArray objectAtIndex:indexPath.row] isEqualToString:#"True"] ) {
cell.selectedImage.image = [UIImage imageNamed:#"select.png"];
}
else{
cell.selectedImage.image = Nil;
}
}