I was using UICollectionView for Images grid appearance.while scrolling i found duplicate images appearing there. I was using NYXProgressiveImageView for downloading and displaying images. I Have implemented several methods found on search..
This is my code
- (MyCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
MyCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"CELL" forIndexPath:indexPath];
if (cell == nil)
{
cell = [[MyCell alloc]init];
[cell.imgv setImage:nil];
}
NSMutableDictionary *d=[[NSMutableDictionary alloc]initWithDictionary:[arrSubCatAndItems objectAtIndex:indexPath.item]];
[cell.imgv setImage:nil];
cell.imgv.cakeIndex=indexPath.item;
cell.cellLabel.text = [d objectForKey:#"Name"];
return cell;
}
Where as Mycell is Custom UICollectionViewCell class having ImageView and label init
On scrolling iam loading visible images like this
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
_isDragging=NO;
if (!decelerate)
{
_isDragging=YES;
[self loadimages];
}
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
CGPoint contentOffset = testscroll.contentOffset;
CGRect contentFrame = testscroll.bounds;
contentFrame.origin = contentOffset;
if(!_isDragging)
[self loadimages];
}
-(void)loadimages
{
for (UICollectionViewCell *cell in [collectionview visibleCells]) {
NSIndexPath *indexPath = [collectionview indexPathForCell:cell];
MyCell *cell1 = (MyCell*)[collectionview cellForItemAtIndexPath:indexPath];
NSMutableDictionary *d=[[NSMutableDictionary alloc]initWithDictionary:[arrSubCatAndItems objectAtIndex:indexPath.item]];
[cell1.imgv loadImageAtURL:[NSURL URLWithString:[[d objectForKey:#"ImageUrl"]stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];
}
}
Main problem if i scroll collection view on loading image in Imageview it is appearing in below cells
I don't Know where I am going wrong....New to UICollectionView...Please help me ..Tnx in advance
Related
I've got a UICollectionView which displays as many cells as the amount of images passed through.
I want to make it so that when you tap an image, it copies that image to the clipboard.
Any help would be greatly appreciated.
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
CollectionViewCell *Cell = [collectionView
dequeueReusableCellWithReuseIdentifier:#"ImagesCell"
forIndexPath:indexPath];
UIImage *image;
int row = indexPath.row;
//set image of this cell
image = [UIImage imageNamed:localImages.imageFiles[row]];
Cell.imageCell.image = image;
//enable touch
[Cell.imageCell setUserInteractionEnabled:YES];
Cell.imageCell.tag = row;
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapGestureRecognizer:)];
[tapGesture setNumberOfTapsRequired:1];
[Cell.imageCell addGestureRecognizer:tapGesture];
return Cell;
}
- (void)tapGestureRecognizer:(UITapGestureRecognizer *)sender
{
NSInteger string = (sender.view.tag);
NSLog(#"this is image %i",string);
UIImage *copiedImage = I don't know what to put here..
[[UIPasteboard generalPasteboard] setImage:copiedImage];
}
It's actually easier if you just implement the delegate method of UICollectionView - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath and just do this:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
CollectionViewCell *cell = (CollectionViewCell *)[collectionView cellForItemAtIndexPath:indexPath];
UIImage *copiedImage = cell.imageCell.image;
[[UIPasteboard generalPasteboard] setImage:copiedImage];
}
Hope this helped you out!
Edit: In case you have different type of cells with images and text and you only want to enable copying under images, you will have to implement that UITapGestureRecognizer part and in the method called you just need to do this:
- (void)tapGestureRecognizer:(UITapGestureRecognizer *)sender
{
UIImageView *imageView = (UIImageView *)sender.view;
UIImage *copiedImage = imageView.image;
[[UIPasteboard generalPasteboard] setImage:copiedImage];
}
Since your UITapGestureRecognizer is attached to the UIImageView, it is the sending view and you can extract the image directly from it and copy to the pasteboard.
I built a CollectionView controller with fixed imageView in 4 cells.
I'd like the imageView to change on cell selection.
Could you help me with this one?
Thank you
here's my code
CollectionView controller .m
....
-(NSInteger)numberOfSectionsInCollectionView:
(UICollectionView *)collectionView
{
return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView
numberOfItemsInSection:(NSInteger)section
{
return 4;
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
Cell *myCell = [collectionView dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
UIImage *image;
int row = [indexPath row];
image = [UIImage imageNamed:#"ICUbedGREEN.png"];
myCell.imageView.image = image;
return myCell;
}
I'd like the image to change on press but I cannot figure it out...
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath: (NSIndexPath *)indexPath
{
UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:#"ICUbedRED.png"]];
cell.imageView.image = .....
NSLog(#"elementselected");
}
in your subclass for UICollectionViewCell implement the KVO listening method. Make sure you set multiselection to true if you want it to be deselected.
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
if ([keyPath isEqualToString#"selected"])
{
// check value of self.selected to know what you are currently.
// change picture of image here
}
}
in your cells init method you will need to add yourself as a listener so
[self addObserver:self forKeyPath:#"selected" options:nil context:nil];
It can be most stupid answer to your questions but it worked for me. I dont know how to work with KEy value paths as stated by Samuel.
Basically i made a NSMutableArray to store the status of icons, red or green..YES or NO..
selState = [[NSMutableArray alloc] initWithObjects:#"NO",#"NO",#"NO",#"NO",nil ];
and then in "ItemForIndexPath" method, checked the value to set image for that item
if ([[selState objectAtIndex:indexPath.row] isEqualToString:#"NO"]) {
image = [UIImage imageNamed:#"ICUbedGREEN.png"];
}
else
{
image = [UIImage imageNamed:#"ICUbedRED.jpg"];
}
When item is selected, using IndexPath, altered the value of NO into YES or vice versa..
if ([[selState objectAtIndex:indexPath.row] isEqualToString:#"NO"]) {
[selState replaceObjectAtIndex:indexPath.row withObject:#"YES"];
}
else if ([[selState objectAtIndex:indexPath.row] isEqualToString:#"YES"]) {
[selState replaceObjectAtIndex:indexPath.row withObject:#"NO"];
}
And then updated the collection View
[self.collectionView reloadData];
ALL CODE HERE
#interface ViewController (){
NSMutableArray *selState;
}
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
selState = [[NSMutableArray alloc] initWithObjects:#"NO",#"NO",#"NO",#"NO",nil ];
}
-(NSInteger)numberOfSectionsInCollectionView:
(UICollectionView *)collectionView
{
return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView
numberOfItemsInSection:(NSInteger)section
{
return 4;
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
Cell *myCell = [collectionView dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
UIImage *image;
if ([[selState objectAtIndex:indexPath.row] isEqualToString:#"NO"]) {
image = [UIImage imageNamed:#"ICUbedGREEN.png"];
}
else
{
image = [UIImage imageNamed:#"ICUbedRED.jpg"];
}
myCell.imageView.image = image;
return myCell;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath: (NSIndexPath *)indexPath
{
if ([[selState objectAtIndex:indexPath.row] isEqualToString:#"NO"]) {
[selState replaceObjectAtIndex:indexPath.row withObject:#"YES"];
}
else if ([[selState objectAtIndex:indexPath.row] isEqualToString:#"YES"]) {
[selState replaceObjectAtIndex:indexPath.row withObject:#"NO"];
}
[self.collectionView reloadData];
}
#end
Thanks
EDITING---->>
the above code in ItemForIndexPath can also be written in
image = [[selState objectAtIndex:indexPath.row] isEqualToString:#"NO"] ?
[UIImage imageNamed:#"ICUbedGREEN.png"] : [UIImage imageNamed:#"ICUbedRED.jpg"];
END EDITING
I am using a UICollectionView with a custom Cell containing one image and one label. I load the data via XML, but I am using a multithread to bind the data of the image in the cells. I am not setting the image to load on the cellForItemAtIndexPath, but I am loading the description from here.
My problem is that the images do not load initially. When I scroll, it does load because I have a method in scrollView:
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
if (!decelerate)
{
[self loadImagesForOnscreenCells];
}}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
[self loadImagesForOnscreenCells];
}
I use the following to load the description:
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath; {
Cell *cell = [cv dequeueReusableCellWithReuseIdentifier:kCellID forIndexPath:indexPath];
cell.label.text = xmlPhotosVideosRecordPointer.title;
This is the loadImagesForOnscreenCells:
- (void)loadImagesForOnscreenCells
{
if ([xmlPhotosVideosRecords count] > 0)
{
NSArray *visiblePaths = [newsTable indexPathsForVisibleItems];
for (NSIndexPath *indexPath in visiblePaths)
{
xmlPhotosVideosRecord *xmlPhotosVideosRecordPointer = [self.xmlPhotosVideosRecords objectAtIndex:indexPath.row];
if (!xmlPhotosVideosRecordPointer.thumbImage)
{
[self startIconDownload:xmlPhotosVideosRecordPointer forIndexPath:indexPath];
}
}
}
}
That being said, is there a way to delegate when the UICollectionView didLoad? This way, I could use
[self loadImagesForOnscreenCells]; to refresh the images on screen.
I figured it out and it works! Use:
- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath
I'm working with the google YouTube API, and I'm using this code found here http://pastebin.com/vmV2c0HT
The Code that slows things down is this one here
cell.imageView.image = [UIImage imageWithData:data];
When I remove that code it scrolls smoothly. Any idea on how I can go about having it load the images from google but still scroll smoothly? I've read some of the answers on loading images in a different way, but I still can't figure out how I'll make that work with the code I'm using.
Any help will be appreciated.
Bellow is the full code.
#import "RootViewController.h"
#interface RootViewController (PrivateMethods)
- (GDataServiceGoogleYouTube *)youTubeService;
#end
#implementation RootViewController
#synthesize feed;
- (void)viewDidLoad {
NSLog(#"loading");
GDataServiceGoogleYouTube *service = [self youTubeService];
NSString *uploadsID = kGDataYouTubeUserFeedIDUploads;
NSURL *feedURL = [GDataServiceGoogleYouTube youTubeURLForUserID:#"BmcCarmen"
userFeedID:uploadsID];
[service fetchFeedWithURL:feedURL
delegate:self
didFinishSelector:#selector(request:finishedWithFeed:error:)];
[super viewDidLoad];
}
- (void)request:(GDataServiceTicket *)ticket
finishedWithFeed:(GDataFeedBase *)aFeed
error:(NSError *)error {
self.feed = (GDataFeedYouTubeVideo *)aFeed;
[self.tableView reloadData];
}
#pragma mark Table view methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [[feed entries] count];
}
// Customize the appearance of table view cells.
- (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] autorelease];
}
// Configure the cell.
GDataEntryBase *entry = [[feed entries] objectAtIndex:indexPath.row];
NSString *title = [[entry title] stringValue];
NSArray *thumbnails = [[(GDataEntryYouTubeVideo *)entry mediaGroup] mediaThumbnails];
cell.textLabel.text = title;
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[thumbnails objectAtIndex:0] URLString]]];
cell.imageView.image = [UIImage imageWithData:data];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 100.0f;
}
- (void)dealloc {
[super dealloc];
}
- (GDataServiceGoogleYouTube *)youTubeService {
static GDataServiceGoogleYouTube* _service = nil;
if (!_service) {
_service = [[GDataServiceGoogleYouTube alloc] init];
[_service setShouldCacheDatedData:YES];
[_service setServiceShouldFollowNextLinks:YES];
}
// fetch unauthenticated
[_service setUserCredentialsWithUsername:nil
password:nil];
return _service;
}
#end
GCD is a wonderful thing. Here is what I do:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"youTubeCell";
UITableViewCell *cell = nil;
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell.
GDataEntryBase *entry = [[feed entries] objectAtIndex:indexPath.row];
NSString *title = [[entry title] stringValue];
NSArray *thumbnails = [[(GDataEntryYouTubeVideo *)entry mediaGroup] mediaThumbnails];
cell.textLabel.text = title;
// Load the image with an GCD block executed in another thread
dispatch_queue_t downloadQueue = dispatch_queue_create("image downloader", NULL);
dispatch_async(downloadQueue, ^{
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[thumbnails objectAtIndex:0] URLString]]];
UIImage * image = [UIImage imageWithData:data];
dispatch_async(dispatch_get_main_queue(), ^{
cell.imageView.image = image;
cell.imageView.contentMode = UIViewContentModeScaleAspectFit;
[cell setNeedsLayout];
});
});
dispatch_release(downloadQueue);
return cell;
}
Scrolling is now super smooth. The only drawback is that when you scroll quickly, cells are re-used and sometimes the images change as new ones come in.
I'm sure this is very simple but i can't find any documentation about it..
in my uitableview i have the text labels aligned to the right (my app is in heberw which is rtl)
i'm trying to add an image to the cell to the RIGHT of the text label, no luck, so far the image is aligned to the left and i can't find a way to align it to the right side of the cell.
here's my code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
cell.imageView.image = [UIImage imageNamed:#"tableicon.png"];
NSString *cellValue = [[stories objectAtIndex:indexPath.row] objectForKey:#"ArticleTitle"];
cell.textLabel.text = cellValue;
cell.textLabel.textAlignment = UITextAlignmentRight;
cell.textLabel.font = [UIFont systemFontOfSize:17];
cell.textLabel.numberOfLines = 2;
return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 50;
}
Instead of adding the image as a subview of your UITableViewCell, add a container with right aligned subviews.
UIImageView *pic = myImageView;
UIView *picContainer = [[UIView alloc] initWithFrame:cell.frame];
picContainer.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
picContainer.contentMode = UIViewContentModeRight;
pic.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
pic.center = CGPointMake(picContainer.frame.size.width-70, picContainer.frame.size.height/2);
[picContainer addSubview:pic];
[cell.contentView addSubview:picContainer];
This has the added benefit of automatically readjusting when the orientation changes.
try this one
cell.accessoryView=[UIImage imageNamed:#"tableicon.png"];