Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using UICollectionView in a universal app

I need to create a universal app with a listing. And on clicking a cell it shows the detail view of the cell. I have created the listing for a iPad by using a UICollectionView inside a UIViewController. But when I try the same in iPhone it doesn't show properly. Its kind of a zoomed version of iPad cell.

For iPad I need the cell to be like this
http://i.stack.imgur.com/8mJnI.png

And for iPhone I need the cell to be like this
http://i.stack.imgur.com/moUxm.png

What is the best way to do this?

Any help will be appreciated

like image 250
avrospirit Avatar asked Aug 08 '14 13:08

avrospirit


People also ask

What is the difference between Uitableview and UICollectionView?

UICollectionView is the model for displaying multidimensional data — it was introduced just a year or two ago with iOS 6, I believe. The main difference between the two is how you want to display 1000 items. UITableViewhas a couple of styles of cells stacked one over the other.

How does swift implement UICollectionView?

Select the Main storyboard from the file browser. Add a CollectionView by pressing command shift L to open the storyboard widget window. Drag the collectionView onto the main view controller. Add constraints to the UICollectionView widget to ensure that the widget fills the screen on all devices.

What is the use of datasource and delegate in UICollectionView in iOS?

This method asks the data source object to provide a supplementary view to display in the collection view. It asks the datasource object whether the specified item can be moved to another location in the collectionview. This method moves the specified item to the specified indexpath.

What is UICollectionView flow layout?

A layout object that organizes items into a grid with optional header and footer views for each section.


2 Answers

I would suggest create to abstract subclass of UICollectionViewCell with properties like image, title, desc and two subclasses of the abstract class, for example iPadCell and iPhoneCell.

In the storyboard add two prototype cells and change it class and identifier to iPhoneCell and iPadCell. Layout the cell as you need and in collectionView:cellForItemAtIndexPath: dequeue right cell, for appropriate device:

- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {

    YourAbstractClass *cell = nil;
    if ( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ) {
        // Make sure it match storyboard identifier for iPad cell
        cell = [cv dequeueReusableCellWithReuseIdentifier:@"iPadCellIdentifier" forIndexPath:indexPath];
    }
    else { //iPhone device
        cell = [cv dequeueReusableCellWithReuseIdentifier:@"iPhoneCellIdentifier" forIndexPath:indexPath];
    }
    cell.imageView.image = ...;
    cell.title = ...;
    cell.description = ...;

    return cell;
}

In very similar way you can set up cell size, if it's different for iPhone/ipad:

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    if ( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ) {
            return CGSizeMake(400.0f, 500.0f);
        }
        return CGSizeMake(200.0f, 300.0f)

}
like image 124
Greg Avatar answered Sep 27 '22 21:09

Greg


since the content of you cell is same i.e.,

  1. ImageView
  2. UILabel for Title
  3. UILabel for Description

Instead of making a abstract class and then subclassing them, What you could also do is, you just make one custom class of UICollectionViewCell, for example name it as GenericCollectionViewCell, Now this class should have two nib files, and make sure you assign different reuse Identifier to both of them and different file name ofcourse, e.g.

  1. iPhoneCell
  2. iPadCell

So, now basically you have GenericCollectionViewCell.h with IBOutlets to two different nibs.

You will have to create a ENUM to in the GenericeCollectionViewCell e.g.

typedef NS_ENUM(NSUInteger, CellType) {
    CELLIPHONE = 0,
    CELLIPAD = 1
};

you will use this ENUM to initialise, What type of nib to use for this cell e.g.

+ (UINib*)cellNibForCellType:(CellType)cellType{

    switch (cellType) {
        case CELLIPHONE:
            cellNib = [UINib nibWithNibName:@"IPhoneCollectionViewCell"
                                     bundle:nil];
            break;
        case CELLIPAD:
            cellNib = [UINib nibWithNibName:@"IPadCollectionViewCell"
                                     bundle:nil];
            break;
}

Once you have done that, you need to register this cell in viewDidLoad of your ViewController,

- (void)viewDidLoad
{

[super viewDidLoad];

[_collectionView registerNib:[GenericCollectionViewCell cellNibForCellType:CELLIPHONE] forCellWithReuseIdentifier:@"iPhoneCell"];

[_collectionView registerNib:[GenericCollectionViewCell cellNibForCellType:CELLIPAD] forCellWithReuseIdentifier:@"iPadCell"];

}

And then you could proceed with what, @Greg has explained above,

- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {

    GenericCollectionViewCell *cell = nil;
    if ( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ) {
        // Make sure it match storyboard identifier for iPad cell
        cell = [cv dequeueReusableCellWithReuseIdentifier:@"iPadCell" forIndexPath:indexPath];
    }
    else { //iPhone device
        cell = [cv dequeueReusableCellWithReuseIdentifier:@"iPhoneCell" forIndexPath:indexPath];
    }
    cell.imageView.image = ...;
    cell.title = ...;
    cell.description = ...;

    return cell;
}

Basically this is what I have come up with, if the content of the cells are same, what's the point of making super class, I mean I don't know I might be wrong.

like image 38
Amit Singh Avatar answered Sep 27 '22 21:09

Amit Singh