UICollectionView:在没有任何项目的部分中显示标签“无项目”

Posted

技术标签:

【中文标题】UICollectionView:在没有任何项目的部分中显示标签“无项目”【英文标题】:UICollectionView: Show label "No item" in the section that don't have any item 【发布时间】:2016-04-04 05:40:15 【问题描述】:

我有一个 UICollectionView 有 5 个部分,有些部分有数据,有些部分(在我的代码中是第 2 部分)没有(取决于服务器) 因此,我想在没有数据的选择中显示一个标签(“No item”)。

但是,我可以找到任何想法来做到这一点,我希望任何人都可以给我一些建议或指导来实现它。 我真的很感激任何帮助

这是我的跨级部分代码

-(UICollectionReusableView *) collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath

        FriendsFanLevelHeaderView *headerView = (FriendsFanLevelHeaderView *)[self.collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"FanLevelHeader" forIndexPath:indexPath];

            switch (indexPath.section) 
                case 0:
                    [headerView.lblFanLevelTitle setText:@"Gold"];
                    break;
                case 1:
                    [headerView.lblFanLevelTitle setText:@"Silver"];
                    break;
                case 2:
                    [headerView.lblFanLevelTitle setText:@"Bronze"];
                    break;
                case 3:
                    [headerView.lblFanLevelTitle setText:@"Green"];
                    break;
                case 4:
                    [headerView.lblFanLevelTitle setText:@"Other"];
                    break;
                default:
                    break;
            

            return headerView;
 


- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
    switch (section) 
        case 0:
            return 3;
        case 1:
            return 0; // it doesn't have any item
        case 2:
            return 2;
        case 3:
            return 3;
        case 4:
            return 5;
        default:
            return 0;
    


- (FriendsCollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
        FriendsCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"FriendsCollectionViewCell" forIndexPath:indexPath];

        [cell.lblFriendBand setText:@"Band: White Mash  "];
        [cell.lblFriendGenre setText:@"Freestyle house,  House,  Freestyle music,"];
        [cell.lblFriendECScore setText:@"EC score: 79"];

        return cell;

==============================================

这就是我想要的

【问题讨论】:

您是否获取数组格式的数据.. ?? 是的,我的数据是数组格式 你的意思是子数组的数组..?? 我是 ios 新手,我不知道不同的 beetween 数组和子数组。我正在使用 NSMutableArray 我已经添加了我的 ans ,检查并告诉我它是否有效。 【参考方案1】:

假设您在NSArray 中拥有每个部分的数据(项目)。

所以你有goldSectionItems 数组、silverSectionItems 数组、bronzeSectionItems 数组、greenSectionItems 数组和otherSectionItems 数组。

你想做的是:

    当您想要显示的部分中有一些项目时 当您想要显示“无项目”的部分中没有项目时

在情况 1 中,您希望使用包含您的项目的数组向集合视图指示您在您的部分中拥有的项目数。

在情况 2 中,您希望向集合视图表明您有 1 个项目,这将是“无项目”单元格。

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section 
    switch (section) 
        case 0:
            return MAX(1, goldSectionItems.count);
        case 1:
            // return at least 1 when you have no items from the server.
            // When you do not have any items in
            // you NSArray then you return 1, otherwise you return
            // the number of items in your array
            return MAX(1, silverSectionItems.count);
        case 2:
            return MAX(1, bronzeSectionItems.count);
        case 3:
            return MAX(1, greenSectionItems.count);
        case 4:
            return MAX(1, otherSectionItems.count);
        default:
            return 0;
    

注意:MAX 将返回其两个操作数之间的最大值。例如,如果您的silverSectionItems 数组为空,则count 属性将返回0,因此MAX(1, 0) 将返回1。如果您的silverSectionItems 不为空count 将返回N(其中@ 987654336@) 所以MAX(1, N) 将返回N

然后在您的-collectionView:cellForItemAtIndexPath: 中检查您是哪种情况:

如果您是第一种情况,您需要一个显示正常内容的单元格。

如果您是情况 2,您需要一个显示“无项目”的单元格。

- (FriendsCollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
    FriendsCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"FriendsCollectionViewCell" forIndexPath:indexPath];
    // get the array that contains the items for your indexPath
    NSArray *items = [self itemArrayForIndexPath:indexPath];

    // case 2
    // if the section does not have any items then set up the
    // cell to display "No item" 
    if (items.count == 0) 
        [cell.lblFriendBand setText:@"No item"];
        [cell.lblFriendGenre setText:@""];
        [cell.lblFriendECScore setText:@""];
    
    // case 1
    // setup the cell with your items
    else 
        // get you item here and set up the cell with your content
        // Item *item = items[indexPath.item];
        [cell.lblFriendBand setText:@"Band: White Mash  "];
        [cell.lblFriendGenre setText:@"Freestyle house,  House,  Freestyle music,"];
        [cell.lblFriendECScore setText:@"EC score: 79"];
    

    return cell;


// return array for the corresponding indexPath
- (NSArray *)itemArrayForIndexPath:(NSIndexPath *)indexPath 
    switch (indexPath.section) 
        case 0:
            return goldSectionItems;
        case 1:
            return silverSectionItems;
        case 2:
            return bronzeSectionItems;
        case 3:
            return greenSectionItems;
        case 4:
            return otherSectionItems;
        default:
            return nil;
    


-(UICollectionReusableView *) collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath

    FriendsFanLevelHeaderView *headerView = (FriendsFanLevelHeaderView *)[self.collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"FanLevelHeader" forIndexPath:indexPath];

        switch (indexPath.section) 
            case 0:
                [headerView.lblFanLevelTitle setText:@"Gold"];
                break;
            case 1:
                [headerView.lblFanLevelTitle setText:@"Silver"];
                break;
            case 2:
                [headerView.lblFanLevelTitle setText:@"Bronze"];
                break;
            case 3:
                [headerView.lblFanLevelTitle setText:@"Green"];
                break;
            case 4:
                [headerView.lblFanLevelTitle setText:@"Other"];
                break;
            default:
                break;
        

        return headerView;

有什么不懂的就问吧。

【讨论】:

感谢您给我一个好主意,它解决了我的问题。但是我认为,如果我按照 Kuba 的建议使用部分页脚来显示标签“No item”,我的代码会更清晰【参考方案2】:

您需要像使用节标题一样使用UICollectionElementKindSectionFooter。我构建了简单的 CollectionView 示例来展示我的想法:

所以基本上我所做的是创建通用页脚并在有内容填充单元格时隐藏它:

基本例子是:

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section 
    NSArray *sectionContent = self.collectionViewData[section][COLLECTIONVIEW_CONTENT_KEY];
    return ([sectionContent count] > 0) ? CGSizeMake(0, 0) : CGSizeMake(collectionView.frame.size.width, FOOTER_HEIGHT);
  

我的self.collectionViewDataNSArrayNSDictionary

但为了避免打破约束,我强烈建议为页脚创建单独的 xib 并将两者都应用于您的 collectionView。

-(UICollectionReusableView *) collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath

NSArray *sectionContent = self.collectionViewData[indexPath.section][COLLECTIONVIEW_CONTENT_KEY];

if([kind isEqualToString:UICollectionElementKindSectionHeader]) 
    UICollectionReusableView *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"header" forIndexPath:indexPath];
    return headerView;
 else 
    NSString *footerIdentifier = ([sectionContent count] > 0) ? @"blankFooter" : @"footer";
    UICollectionReusableView *footerView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:footerIdentifier forIndexPath:indexPath];
    return footerView;


您可以在此处下载示例项目以查看:https://bitbucket.org/Kettu/so_34526276

Bitbucket to this repository

【讨论】:

这是一个很好的解决方案,我解决了我的问题。但是请将代码更新到您的示例项目中,您的示例项目现在没有显示任何内容 对不起,我忘了推送更改,我更新了存储库。【参考方案3】:

我在我的一个项目中这样做了,但我在集合视图的每个部分中使用 collectionView 来水平滚动到每个部分,如下所示。你有什么想法吗

if (row==0)

    lblCoupons = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, collectionVCategory.frame.size.width, 50)];
  //  lblCoupons.tag = 99;
    [lblCoupons setText:@"No Coupons Found!"];
    [lblCoupons setTextAlignment:NSTextAlignmentCenter];
    [lblCoupons setFont:[UIFont systemFontOfSize:15]];
    [collctnView.backgroundView layoutSubviews];
    collctnView.backgroundView = lblCoupons;

else

    [lblCoupons removeFromSuperview];
    //[collectionVCategory.backgroundView removeAllSubviewsOfTag:99];
    collctnView.backgroundView = nil;

【讨论】:

现在,我不在CollectionView的每个部分都使用tableview。如果我找不到任何解决方案,我会考虑将 TableView 添加到 CollectionView 的每个部分的方式。谢谢你的好建议 就我而言,我认为当我为 UICollectionView 的每个部分添加 TableView 时,我的布局会更复杂:(。显示简单组件的代码太多 实际上在我的情况下,每个部分都有多个(0 到 100 或更多)项要显示,我必须滚动每个部分,所以我在那里使用了 tableview 对不起,这是每个部分的集合视图【参考方案4】:

如果您以这样一种格式获取数据,即数组本身的每个索引都包含一个完整的数组。像 recipeImages 包含 3 个对象,它们本身就是数组。

NSArray *mainDishImages = [NSArray arrayWithObjects:@"egg_benedict.jpg", @"full_breakfast.jpg", @"ham_and_cheese_panini.jpg", @"ham_and_egg_sandwich.jpg", nil];

NSArray *drinkDessertImages = [NSArray arrayWithObjects:@"green_tea.jpg", @"starbucks_coffee.jpg", @"white_chocolate_donut.jpg", nil];

NSArray *sideDishes = [NSArray arrayWithObjects:@"green_tea.jpg", @"starbucks_coffee.jpg", @"white_chocolate_donut.jpg", nil];

recipeImages = [NSArray arrayWithObjects:mainDishImages, drinkDessertImages, sideDishes ,nil];

您可以将集合视图中的部分数量指定为:

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView

return [recipeImages count];

每个部分的行数为

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
return [[recipeImages objectAtIndex:section] count];

如果您的数据是这种格式,您可以通过获取特定部分的数组来检查指定部分中是否有任何数据。

-(UICollectionReusableView *) collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath

NSArray *temp_arr_gold = [recipeImages objectAtIndex:0];
NSArray *temp_arr_silver = [recipeImages objectAtIndex:1];
NSArray *temp_arr_bronze = [recipeImages objectAtIndex:2];
NSArray *temp_arr_green = [recipeImages objectAtIndex:3];
NSArray *temp_arr_other = [recipeImages objectAtIndex:4];
FriendsFanLevelHeaderView *headerView = (FriendsFanLevelHeaderView *)[self.collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"FanLevelHeader" forIndexPath:indexPath];

switch (indexPath.section) 
    case 0:
        if (temp_arr_gold.count !=0)
        
            [headerView.lblFanLevelTitle setText:@"Gold"];
        
        else
        
            [headerView.lblFanLevelTitle setText:@"No item"];
        
        break;
    case 1:
        if (temp_arr_silver.count !=0)
        
            [headerView.lblFanLevelTitle setText:@"Silver"];
        
        else
        
            [headerView.lblFanLevelTitle setText:@"No item"];
        
        break;
    case 2:
        if (temp_arr_bronze.count !=0)
        
            [headerView.lblFanLevelTitle setText:@"Bronze"];
        
        else
        
            [headerView.lblFanLevelTitle setText:@"No item"];
        
        break;
    case 3:
        if (temp_arr_green.count !=0)
        
            [headerView.lblFanLevelTitle setText:@"Green"];
        
        else
        
            [headerView.lblFanLevelTitle setText:@"No item"];
        
        break;
    case 4:
        if (temp_arr_other.count !=0)
        
            [headerView.lblFanLevelTitle setText:@"Other"];
        
        else
        
            [headerView.lblFanLevelTitle setText:@"No item"];
        
        break;
    default:
        break;


return headerView;

希望它有所帮助.. 快乐编码。

【讨论】:

对不起,你可能错过了什么。使用您的代码,您将更改部分标题。未显示“No item”beetween 2 部分 在哪里定义了那个标签(“找不到朋友”).. ??您是否为相同的..创建了 IBOutlet??【参考方案5】:

一种方法是在 collectionView 中创建另一个单元格“No Item”

然后在collectionView:numberOfItemsInSection: 中始终返回最小值 1,以便为“No Item”单元格腾出空间。

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

    // TODO: check dataSource array for "NO FRIENDS"
    // TODO: If true 
    // NoFriendsCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"NoFriendsCollectionViewCell" forIndexPath:indexPath];
    // cell.label.text = "No Item";
    // return cell;
    // else

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

    [cell.lblFriendBand setText:@"Band: White Mash  "];
    [cell.lblFriendGenre setText:@"Freestyle house,  House,  Freestyle music,"];
    [cell.lblFriendECScore setText:@"EC score: 79"];

    return cell;

【讨论】:

【参考方案6】:

如果要显示“无项目”标签,则需要在 numberOfItemsInSection 中返回 1,然后当 collectionview 请求单元格时,取决于项目的实际计数,您可以返回“当 indexpath 的行号为 1 时,没有项目”标签或集合中的实际第一项。

【讨论】:

感谢您给我一个好主意,它解决了我的问题。但是我认为,如果我按照 Kuba 的建议使用部分页脚来显示标签“No item”,我的代码会更清晰

以上是关于UICollectionView:在没有任何项目的部分中显示标签“无项目”的主要内容,如果未能解决你的问题,请参考以下文章

为啥 uicollectionview 没有显示任何内容

UICollectionView 呈现比故事板更高

UIPageControl的无限UICollectionview

UICollectionView - 将 Storyboard 项目移植到没有 IB 项目

UICollectionview 不工作,我没有得到任何 Cell

停止滚动时获取 UICollectionView 的项目(或索引)