如何创建自定义 UICollectionViewCell

Posted

技术标签:

【中文标题】如何创建自定义 UICollectionViewCell【英文标题】:how to create custom UICollectionViewCell 【发布时间】:2016-11-16 13:39:44 【问题描述】:

我有一个UICollectionView,我试图在collectionViewCell 中设置一个label 和一个image。不幸的是,我似乎无法显示任何标签或其他任何东西。

这是我的代码:

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

    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cellIdentifier" forIndexPath:indexPath];

    UILabel *issue = [[UILabel alloc] initWithFrame:CGRectMake(0,10,cell.bounds.size.width,40)];
    if(indexPath.item %2 == 0)
        cell.backgroundColor=[UIColor blueColor];
        issue.text = @"Some Text";
        issue.textColor = [UIColor greenColor];
        issue.textAlignment = NSTextAlignmentCenter;
    
    else 
        cell.backgroundColor=[UIColor redColor];
        issue.text = @"Some Text";
        issue.textColor = [UIColor greenColor];
        issue.textAlignment = NSTextAlignmentCenter;
    

很遗憾,没有显示标签,标签中的文本也没有显示。

更新:我已经添加了这个类文件中的其余代码。

#import "ContainerListController.h"
#import "ContainerController.h"
#import "ContainerList.h"


@implementation ContainerListController


//Deallocate temp variables
- (void)dealloc 
    [[NSNotificationCenter defaultCenter] removeObserver:self];


//Initiate objects
- (id)init 
    if (self = [super initWithTitle:LocStr(@"CONTAINER_LIST_TITLE") navBarHidden:NO]) 
        m_paths = [ContainerList shared].paths;

        [[NSNotificationCenter defaultCenter] addObserver:self
            selector:@selector(onContainerListDidChange)
            name:kSDKLauncherContainerListDidChange object:nil];
    

    return self;


//Load all the views.
- (void)loadView 
    //Allocate a UI view
    self.view = [[UIView alloc] init];

    //Create flow layout
    UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];

    //Force Horizontal Scroll
    [layout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
    layout.minimumInteritemSpacing =[[UIScreen mainScreen] bounds].size.width;
    layout.minimumLineSpacing=0.0;


    //Create Collection
    UICollectionView *coll =[[UICollectionView alloc] initWithFrame:self.view.frame collectionViewLayout:layout];

    //Allocations
    m_coll = coll;
    coll.dataSource =self;
    coll.delegate =self;
    coll.pagingEnabled = YES;
    coll.collectionViewLayout = layout;

    //Customize Cells
    [coll registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cellIdentifier"];
    [coll setBackgroundColor:[UIColor orangeColor]];

    [layout invalidateLayout];

    //Create the subview
    [self.view addSubview:coll];




    //set minimum spacing
    /*if(UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation))
        NSLog(@"Changed to landscape Spacing");
        layout.minimumLineSpacing = 100.0f;
        layout.minimumInteritemSpacing = 100.0f;
    
    else

        layout.minimumLineSpacing = 40.0f;
        layout.minimumInteritemSpacing = 40.0f;
    */

    //Old Layout
    //UITableView *table = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
    //m_table = table;
    //table.dataSource = self;
    //table.delegate = self;
    //[self.view addSubview:table];



- (void)onContainerListDidChange 
    m_paths = [ContainerList shared].paths;
    [m_table reloadData];
    [m_coll reloadData];


//Debugging components function
/*-(void)printComps:(NSArray* ) components
    for (NSInteger i =0; i<16; i++) 
        NSString * item;
        item=components[i];
    
*/

//old tableview cell
- (UITableViewCell *)
    tableView:(UITableView *)tableView
    cellForRowAtIndexPath:(NSIndexPath *)indexPath

    UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
        reuseIdentifier:nil];
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    NSString *path = [m_paths objectAtIndex:indexPath.row];
    NSArray *components = path.pathComponents;
    cell.textLabel.text = (components == nil || components.count == 0) ?
        @"" : components.lastObject;
    return cell;


//Old tableView
- (void)
    tableView:(UITableView *)tableView
    didSelectRowAtIndexPath:(NSIndexPath *)indexPath

    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    NSString *path = [m_paths objectAtIndex:indexPath.row];
    ContainerController *c = [[ContainerController alloc] initWithPath:path];

    if (c != nil) 
        [self.navigationController pushViewController:c animated:YES];
    
    NSLog(@"Selected an item");


//old TableView count for epubs
- (NSInteger)
    tableView:(UITableView *)tableView
    numberOfRowsInSection:(NSInteger)section
    return m_paths.count;


- (void)viewDidLayoutSubviews 

    //m_table.frame = self.view.bounds;
    m_coll.frame = self.view.bounds;


//Collection View Cell Data Allocation
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
                  cellForItemAtIndexPath:(NSIndexPath *)indexPath

    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cellIdentifier" forIndexPath:indexPath];
    UILabel *issue = [[UILabel alloc] initWithFrame:CGRectMake(0,10,cell.bounds.size.width,40)];
    //UICollectionViewCell *content = [[UICollectionViewCell alloc] init];
    if(indexPath.item %2 == 0)
        cell.backgroundColor=[UIColor blueColor];
        issue.text = @"Some Text";
        issue.textColor = [UIColor greenColor];
        issue.textAlignment = NSTextAlignmentCenter;
    
    else 
        cell.backgroundColor=[UIColor redColor];
        issue.text = @"Some Text";
        issue.textColor = [UIColor greenColor];
        issue.textAlignment = NSTextAlignmentCenter;
    
    NSString *path = [m_paths objectAtIndex:indexPath.row];
    NSArray *components = path.pathComponents;
    NSString *Title = components.lastObject;

    NSLog(@"Title: %@",Title);
    NSString *Titletest = components.lastObject;
     NSInteger comp1 = components.count;
     NSString *comps = @"components";
     NSLog(@"There are: %ld %@", (long)comp1,comps);
     NSLog(@"Title: %@",Titletest);
     for (NSInteger i =0; i<15; i++) 
     NSString * item;
     item=components[i];
     NSLog(@"Component:%ld %@",(long)i,components[i]);
     

    return cell;


//Collection View Cell Data De-Allocation
- (void)
collectionView:(UICollectionView *)collectionView
numberofItemsInSection:(NSIndexPath *)indexPath

    [collectionView deselectItemAtIndexPath:indexPath animated:YES];
    NSString *path = [m_paths objectAtIndex:indexPath.row];
    ContainerController *c = [[ContainerController alloc] initWithPath:path];

    if(c !=nil)
        [self.navigationController pushViewController:c animated:YES];
    


//Collection
-(NSInteger)
    collectionView:(UICollectionView *)collectionView
    numberOfItemsInSection:(NSInteger)section

    return m_paths.count;



//Set Collection View Cell Size
-(CGSize)
    collectionView:(UICollectionView *) collectionView
    layout:(UICollectionViewLayout*)collectionViewLayout
    sizeForItemAtIndexPath:(NSIndexPath *)indexPath


    //Set Landscape size of cells
    /*if(UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation))
        CGFloat cellWidth =  [[UIScreen mainScreen] bounds].size.width-360;
        CGFloat cellHeigt = [[UIScreen mainScreen] bounds].size.height-60;
        NSLog(@"Is Landscape");
        return CGSizeMake(cellWidth, cellHeigt);
    
    //Set Potrait size of cells
    else
        CGFloat cellWidth =  [[UIScreen mainScreen] bounds].size.width-60;
        CGFloat cellHeigt = [[UIScreen mainScreen] bounds].size.height-160;
        NSLog(@"Is Portrait");
        return CGSizeMake(cellWidth, cellHeigt);
    */

    return CGSizeMake(collectionView.bounds.size.width, collectionView.bounds.size.height);


//Collection View Cell Position
- (UIEdgeInsets)collectionView:
(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section 

    if(UIDeviceOrientationIsPortrait([UIDevice currentDevice].orientation))
         return UIEdgeInsetsMake(150.0,0.0,150.0,0.0);  // top, left, bottom, right
     
     else
         return UIEdgeInsetsMake(20.0,0.0,0.0,0.0);  // top, left, bottom, right
     


- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation

    [m_coll performBatchUpdates:nil completion:nil];


-(void)viewWillTransitionToSize:withTransitionCoordinator

    [m_coll performBatchUpdates:nil completion:nil];


/*-(CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)
collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section

    CGFloat cellSpacing = ((UICollectionViewFlowLayout *) collectionViewLayout).minimumLineSpacing;
    CGFloat cellWidth = ((UICollectionViewFlowLayout *) collectionViewLayout).itemSize.width;
    NSInteger cellCount = [collectionView numberOfItemsInSection:section];
    CGFloat inset = (collectionView.bounds.size.width - ((cellCount-1) * (cellWidth + cellSpacing))) * 0.5;
    inset = MAX(inset, 0.0);

    if(UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation))

        NSLog(@"Changed to landscape Spacing");
        return inset;

    
    else

        return inset;
    

*/
@end

【问题讨论】:

您需要创建自定义类并使用而不是UICollectionViewCell 所以UICollectionViewCell 自定义类包含标签详细信息和任何其他对象? 通过创建自定义类,您可以通过引用 cell.yourLabel.text = @"some value" 和其他预先声明的对象来维护 ui 组件。 所以你知道我是个白痴。这是怎么做的吗?UICollectionViewCell *content = [[UICollectionViewCell alloc] init]; 然后我只是引用 CollectionViewCell 中的内容 好的,您现在需要更多关于您的问题的帮助示例吗? 【参考方案1】:

使用自定义collectionViewCell 的清晰示例。

创建UICollectionViewCell的单独类子类见以下代码:

.h 文件:

#import <UIKit/UIKit.h>

@interface CollectionViewCell : UICollectionViewCell
@property (weak, nonatomic) IBOutlet UILabel *customLabel;
@end

.m 文件:

#import "CollectionViewCell.h"

@implementation CollectionViewCell

@end

现在使用storyboardcollectionView 拖放到viewController 中,然后为其选择单元设置自定义类并连接其标签IBOutlet,见下图。

设置自定义类:

连接标签的出口: 如果从情节提要中添加标签和其他 ui 组件

注意:在连接其IBOutlet之前,将uilabel拖入单元格内。


现在在 viewController 类中配置单元格。并通过连接delegatedataSuorceIBOutlet来正确配置collectionView

#import "ViewController.h"
#import "CollectionViewCell.h"

@interface ViewController ()
    // instance variable deceleration part 
    NSMutableArray *yourArray;

@end

@implementation ViewController

- (void)viewDidLoad
    [super viewDidLoad];
    _yourCollView.delegate = self;
    _yourCollView.dataSource = self;

    yourArray = [[NSMutableArray alloc] initWithObjects:@"1st cell",@"2nd cell",@"3rd cell",@"4th cell", nil];
    // Do any additional setup after loading the view, typically from a nib.


// collection view delegate methods
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
    return [yourArray count];


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

    CollectionViewCell *cell = (CollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:@"MyCustomCell" forIndexPath:indexPath];

    // configuring cell
    // cell.customLabel.text = [yourArray objectAtIndex:indexPath.row]; // comment this line if you do not want add label from storyboard 

    // if you need to add label and other ui component programmatically 
    UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, cell.bounds.size.width, cell.bounds.size.height)];
    label.tag = 200;
    label.text = [yourArray objectAtIndex:indexPath.row];

    // this adds the label inside cell
    [cell.contentView addSubview:label];

    return cell;


//Note: Above two "numberOfItemsInSection" & "cellForItemAtIndexPath" methods are required.

// this method overrides the changes you have made to inc or dec the size of cell using storyboard.
- (CGSize)collectionView:(UICollectionView *)collectionView layout:   (UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
    return CGSizeMake(100, 100);


  // class ends

设置单元格标识符(通过选择一个单元格)MyCustomCell 您在使用前在cellForItemAtIndexPath 方法中给出,请参见下图:

注意:之前将uilabel的文字颜色改为白色,因为collectionView默认显示为黑色。

希望你能理解。

【讨论】:

当我尝试创建一个新的UICollectionViewCell 时,我得到一个重复错误。我也无法将UILabel 添加到我的 .h 文件中 让我给几个小时。我会尽快更新答案。 谢谢你 @ZaydBhyat 现在努力并尊重我的时间,谢谢。 好的,我想我明白了,我必须为 UICollectionViewCell 创建一个带有 .h 和 .m 的单独类文件,并且该类可以包含所有需要成为单元格一部分的对象。对吗?【参考方案2】:
    创建UICollectionViewCell 的子类。例如TestCollectionViewCell。 在Storyboard 中将label 拖动到单元格中,并使用您创建的类为此UICollectionViewCell 设置"Custom class"。设置Reusable identifier,如果您在UIViewController 中的收藏视图不要忘记为collectionView 设置DataSourceDelegate。 在您的 Cell 子类中连接 IBOutlet。 在 numberOfItemsInSection 方法中设置至少 1 个值。 然后在cellForItemAt 中使用您的单元格子类并尝试为标签设置文本。

【讨论】:

由于收集数据的第三方框架的性质,我需要以编程方式创建它。所以我不能使用故事板 做同样的事情,但在 awakeFromNib 中没有 IBOutlets 和 init 视图【参考方案3】:

你错过了:

  [cell.contentView addSubview:issue];

【讨论】:

以上是关于如何创建自定义 UICollectionViewCell的主要内容,如果未能解决你的问题,请参考以下文章

Delphi 如何创建自定义的文件类型关联

如何创建自定义 MKAnnotationView 和自定义注释标题和副标题

如何创建一个自定义的Authentication Provider

如何创建自定义 JQuery 函数以及如何使用它?

如何使用 2 个或更多自定义单元格创建自定义 UICollectionView?

如何从自定义集合视图单元(使用 xib 创建的单元)到 tabBar 控制器创建自定义 segue