I am making social app and I have place there I need to make 6 images on page. In this place usually I gave text or one image. How can I set multi images in that place now?
I want set frame for this place and then I want that images scaled to my frame. Is it possible and that element I need to use here? UICOllections or that?
What I understood from your question you'll need to use UICollectionView.
Your should follow these steps:
Make an NSArray of all your images.
Ex. NSArray *imageArray=[[NSArray alloc]initWithObjects:#"image1.png",#"image2.png",#"image3.png", nil];
Drag a UICollectionView to your storyboard, create a custom cell, and use a UIImageView on that custom cell.
Assign a new class to your custom cell.
Connect an outlet for image view in your custom cell's class.
Connect delegate and datasource of your UICollectionView.
Use the following delegate methods for UICollectionView:
-(NSInteger)numberOfSectionsInCollectionView:
(UICollectionView *)collectionView
{
return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView
numberOfItemsInSection:(NSInteger)section
{
return imageArray.count;
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
CustomCellClass *myCell = [collectionView dequeueReusableCellWithReuseIdentifier:#"MyCell" forIndexPath:indexPath];
UIImage *image;
int row = [indexPath row];
image = [UIImage imageNamed:imageArray[row]];
myCell.imageview.image = image;
return myCell;
}
Hope this helps.
Related
I am using a UICollectionView to display some data. I am having one button on each cell. Now on the button click of at some specific index(ex: 9) I want to change buttons image for all cells. Can some one suggest how to do that?
I would loop through all the visible cells and change the image. For example:
for (CustomCellClass *cell in collectionView.visibleCells) {
[cell.button setImage:[UIImage imageNamed:#"new image"] forState:UIControlStateNormal];
}
For off-screen cells, I would make sure to set the new image in collectionView:cellForItemAtIndexPath: as the user scrolls to those cells.
We can simply add the logic in cellForItemAtIndexPath like this.
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
if (self.buttonClicked) { // boolean check
[cell.newButton setImage:buttonClickedImage];
}else {
[cell.newButton setImage:buttonNotClickedImage];
}
return cell;
}
After clicking the button, you can also just reload all visible cells.
[self.collectionView reloadItemsAtIndexPaths:self.collectionView.indexPathsForVisibleItems];
Feel free to suggest edits to make this answer better :)
I want to start populating my UICollectionView with my cells at the middle and not at the very top. I am not sure if this bit of code will help, but I will post it just in case.
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
Cell *cell = (Cell*)[collectionView dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
NSMutableArray *data = [sections objectAtIndex:indexPath.section];
cell.cellImg.image = [data objectAtIndex:indexPath.item];
return cell;
}
Why not populate your array in another order? Take a look on Apple UICollectionViewDataSource Reference:
"You do not need to set the location of the cell inside the collection
view’s bounds. The collection view sets the location of each cell
automatically using the layout attributes provided by its layout
object."
If you need some more info about Collection View Layout:
UICollectionview Layout Tutorial
I am using a UICollectionview to show a lot of Custom cells (250 more or less).
Those cells have a main Image and some text. As the images have to be downloaded from the Internet I am using the external library AsyncImageView to do the lazy load stuff.
But the problem is that the reusable property of the cells are making me crazy.
When I scroll the images appear in the wrong cells. How can I add a tag or something to the images apart from the indexpath to avoid the problem?
Maybe AsyncImageView has a solution to the problem which I ignore ...
Or another alternative would be a better choice?
Any clue?
Thanks in advance
Edit: A simplified version of my code
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = #"Cell";
CollectionComercioCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
if (cell == nil){
}
else{
[[AsyncImageLoader sharedLoader] cancelLoadingImagesForTarget: cell.myImage];
}
cell.myImage.imageURL = nil;
cell.myImage.image = nil;
cell.myImage.hidden = TRUE;
cell.myImage.imageURL = [[myArray objectAtIndex:indexPath.row] getLogoUrl];
cell.myText.text = [[myArray objectAtIndex:indexPath.row] getName];
cell.myImage.hidden = FALSE;
return cell;
}
CustomCell.m
- (void)prepareForReuse
{
[super prepareForReuse];
self.myImage.image = nil;
}
Make sure you set the image to nil in your cellForRowAtIndexPath: method. This way it will stay at least empty until the new image is loaded.
As you mentioned in your comments to the question that this is works if you scroll slow and not when you scroll fast you could maybe override - (void)prepareForReuse on your custom cell.
But be aware that Apple warns you not to use it for content changes:
For performance reasons, you should only reset attributes of the cell
that are not related to content, for example, alpha, editing, and
selection state. The table view's delegate in
tableView:cellForRowAtIndexPath: should always reset all content when
reusing a cell. If the cell object does not have an associated reuse
identifier, this method is not called. If you override this method,
you must be sure to invoke the superclass implementation.
I'm new to IOS Development,
I'm designing an interface where I want to use the collection view to place the controls as if in a grid,
For this, I'm using a collection as shown in the picture below
However, at runtime, this screen is appearing completely black:
I was expecting to see the interface I designed as in the first image. But why is the interface appearing completely black?
The default color of UIcollectionView will looks like black only if you want make it visible try to change the View color of UicollectionView and you want to make visible your grid Layout means connect your collection view with delegate and datasource and use collection view delegate functions.
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return 10;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = #"Cell";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
return cell;
}
and this is good tutorial for Uicollection view Look at this link
I am implementing a Table for iPad and facing some major problems.
For the GridView I implemented my own subclass of UITableViewCell which works fine.
The data is shown correctly, but I have a problem when I want to access a single cell to go to some new detail view. Since one row only contains one cell, the didSelectRowAtIndexPath only gives me access to the complete cell, but I don't know which column the single cell is in.
Then I implemented a TapGestureRecognizer. This shows me the row and column and works, but only until I start scrolling... the column part still works, but the row is shown incorrect since the TapRecognizer overlaps the didSelectRowAtIndexPath (bad but not so important side effect.. there is no blue highlighting of the selected row).
Is there a way to find out how many pixels I scrolled? Or is there an even better solution?
I highly recommend using UICollectionView over those 3rd party classes. There are quite a few advantages to having access to all of the delegate protocols (like showing the cut copy paste UIMenuController on a long press without a UIGestureRecognizer, for example) I use one myself as a grid.
To acheive a grid layout, I did the following...
1) I set the following Delegates in my .h file:
#interface YourViewControllerWithCollectionView : UIViewController <UICollectionViewDataSource, UICollectionViewDelegateFlowLayout> {
}
#property (nonatomic, retain) IBOutlet UICollectionView *myCollectionView;
#end
Notice, that I did not set the UICollectionViewDelegate because UICollectionViewDelegateFlowLayout is actually a sub-protocol of UICollectionViewDelegate, so there is no need to set both.
2) In the .m file, synthesize the collection view, and in viewDidLoad declare the datasource and delegates: (don't forget to connect your outlets, and you might want to put a background color on the cell so you can see it)
#synthesize myCollectionView;
viewdidLoad:
- (void)viewDidLoad
{
self.myCollectionView.delegate = self;
self.myCollectionView.dataSource = self;
//...
}
3) Implement the datasource
#pragma mark - UICollectionView Datasource
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
//the number of cells you want per row
return 4;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
//load sublassed UICollectionViewCell called MyCollectionViewCell
static NSString *cellIdentifier = #"cell";
MyCustomCollectionViewCell *cell = (MyCollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
cell.title.text = #"Title"
// customize the cell...
return cell;
}
5) Implement the UICollectionViewDelegateFlowLayout
#pragma mark – UICollectionViewDelegateFlowLayout
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
//this is what forces the collectionview to only display 4 cells for both orientations. Changing the "-80" will adjust the horizontal space between the cells.
CGSize retval = CGSizeMake((myCollectionView.frame.size.width - 80) / 4, 78);
return retval;
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
// for the entire section, which we have set to 1, adjust the space at
// (top, left, bottom, right)
// keep in mind if you change this, you will need to adjust the retVal
// in the method above
return UIEdgeInsetsMake(5, 20, 10, 20);
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
CGFloat interimSpacing = 0.0f;
return interimSpacing;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section {
CGFloat lineSpacing = 0.0f;
return lineSpacing;
}
6) Last, but certainly not least, invalidate the layout on orientation change to redraw the cells:
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration{
[self.myCollectionView.collectionViewLayout invalidateLayout];
}
And because you implemented UICollectionViewDelegateFlowLayout, you already have access to UICollectionViewDelegate to handle selection, etc. like:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
MyCollectionViewCell *cell = (MyCollectionViewCell *)[collectionView cellForItemAtIndexPath:indexPath];
//do something when a cell is tapped...
}
More information can be found here: http://www.raywenderlich.com/22324/beginning-uicollectionview-in-ios-6-part-12
Look at AQGridView or some of the other controls at CocoaControls.com.
I recommend AGAINST UICollectionView. UICollectionView is easy to use, but not stable enough at this moment. I am using GMGridView for my apps. After a few months operations, I can say that it is stable enough for the production release. Another alternative is PSTCollectionView, which is a 100% API compatible replacement for UICollectionView. However, it is unfinished and contains even more bugs than UICollectionView.
The disturbing issues I have with PSTCollectionView are:
poor performance if you want to display > 80 cells on screen
reloading sections is not implemented
decoration views are not implemented
The disturbing issues I have with UICollectionView are:
the items in the first column may disappear
inserting the first cell will crash
reloading sections with header view will crash
blurry text in cells
Check open radar
https://openradar.appspot.com/search?query=UICollectionView
for all current issues with UICollectionView.
I believe UICollectionView and PSTCollectionView will be good choices when they are stable. But at this moment, GMGridView is a better choice.