如何在下面顶部的集合视图中为部分添加标题

Posted

技术标签:

【中文标题】如何在下面顶部的集合视图中为部分添加标题【英文标题】:how to add Header for section in collection view on top below 【发布时间】:2015-11-02 23:14:21 【问题描述】:

我正在使用带有搜索栏的集合视图。我已经通过 cod 添加了搜索栏,其中 (0,0) 从顶部开始。所以现在我的图像看起来像这样:

[![在此处输入图片描述][1]][1]

但我需要在下面找到我的搜索栏。我是通过故事板完成的。但是在运行时,我的标题名称和搜索栏位于同一来源。我需要将标题部分放在 myseaarch 栏下方。

注意:我正在唱 3 节标题。任何想法或代码都非常有帮助。

这是我的搜索栏代码...

#import "CollectionViewController.h"
#import "CollectionViewCell.h"
@interface CollectionViewController ()<UISearchBarDelegate>

    @property (nonatomic,strong) NSArray        *dataSource;
    @property (nonatomic,strong) NSArray        *dataSourceForSearchResult;
    @property (nonatomic)        BOOL           searchBarActive;
    @property (nonatomic)        float          searchBarBoundsY;

    @property (nonatomic,strong) UISearchBar        *searchBar;
    @property (nonatomic,strong) UIRefreshControl   *refreshControl;

@end

@implementation CollectionViewController

static NSString * const reuseIdentifier = @"Cell";

- (void)viewDidLoad 
    [super viewDidLoad];

    // Do any additional setup after loading the view.
    // datasource used when user search in collectionView
    self.dataSourceForSearchResult = [NSArray new];

    // normal datasource
    self.dataSource =@[@"Modesto",@"Rebecka",@"Andria",@"Sergio",@"Robby",@"Jacob",@"Lavera",@"Theola",@"Adella",@"Garry", @"Lawanda", @"Christiana", @"Billy", @"Claretta", @"Gina", @"Edna", @"Antoinette", @"Shantae", @"Jeniffer", @"Fred", @"Phylis", @"Raymon", @"Brenna", @"Gus", @"Ethan", @"Kimbery", @"Sunday", @"Darrin", @"Ruby", @"Babette", @"Latrisha", @"Dewey", @"Della", @"Dylan", @"Francina", @"Boyd", @"Willette", @"Mitsuko", @"Evan", @"Dagmar", @"Cecille", @"Doug", @"Jackeline", @"Yolanda", @"Patsy", @"Haley", @"Isaura", @"Tommye", @"Katherine", @"Vivian"];




-(void)viewWillAppear:(BOOL)animated
    [super viewWillAppear:animated];
    [self prepareUI];

-(void)dealloc
    // remove Our KVO observer
    [self removeObservers];

- (void)didReceiveMemoryWarning 
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.



#pragma mark - actions
-(void)refreashControlAction
    [self cancelSearching];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^
        // stop refreshing after 2 seconds
        [self.collectionView reloadData];
        [self.refreshControl endRefreshing];
    );



#pragma mark - <UICollectionViewDataSource>
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView 
    return 1;

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section 
    if (self.searchBarActive) 
        return self.dataSourceForSearchResult.count;
    
    return self.dataSource.count;

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath 
    CollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];

    // Configure the cell
    if (self.searchBarActive) 
        cell.laName.text = self.dataSourceForSearchResult[indexPath.row];
    else
        cell.laName.text = self.dataSource[indexPath.row];
    
    return cell;



#pragma mark -  <UICollectionViewDelegateFlowLayout>
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView
                        layout:(UICollectionViewLayout*)collectionViewLayout
        insetForSectionAtIndex:(NSInteger)section
    return UIEdgeInsetsMake(self.searchBar.frame.size.height, 0, 0, 0);

- (CGSize)collectionView:(UICollectionView *)collectionView
                  layout:(UICollectionViewLayout*)collectionViewLayout
  sizeForItemAtIndexPath:(NSIndexPath *)indexPath
    CGFloat cellLeg = (self.collectionView.frame.size.width/2) - 5;
    return CGSizeMake(cellLeg,cellLeg);;



#pragma mark - search
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
    NSPredicate *resultPredicate    = [NSPredicate predicateWithFormat:@"self contains[c] %@", searchText];
    self.dataSourceForSearchResult  = [self.dataSource filteredArrayUsingPredicate:resultPredicate];


- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
    // user did type something, check our datasource for text that looks the same
    if (searchText.length>0) 
        // search and reload data source
        self.searchBarActive = YES;
        [self filterContentForSearchText:searchText
                                   scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
                                          objectAtIndex:[self.searchDisplayController.searchBar
                                                         selectedScopeButtonIndex]]];
        [self.collectionView reloadData];
    else
        // if text lenght == 0
        // we will consider the searchbar is not active
        self.searchBarActive = NO;
    


- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
    [self cancelSearching];
    [self.collectionView reloadData];

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
    self.searchBarActive = YES;
    [self.view endEditing:YES];

- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
    // we used here to set self.searchBarActive = YES
    // but we'll not do that any more... it made problems
    // it's better to set self.searchBarActive = YES when user typed something
    [self.searchBar setShowsCancelButton:YES animated:YES];

- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar
    // this method is being called when search btn in the keyboard tapped
    // we set searchBarActive = NO
    // but no need to reloadCollectionView
    self.searchBarActive = NO;
    [self.searchBar setShowsCancelButton:NO animated:YES];

-(void)cancelSearching
    self.searchBarActive = NO;
    [self.searchBar resignFirstResponder];
    self.searchBar.text  = @"";

#pragma mark - prepareVC
-(void)prepareUI
    [self addSearchBar];
    [self addRefreshControl];

-(void)addSearchBar
    if (!self.searchBar) 
        self.searchBarBoundsY = self.navigationController.navigationBar.frame.size.height + [UIApplication sharedApplication].statusBarFrame.size.height;
        self.searchBar = [[UISearchBar alloc]initWithFrame:CGRectMake(0,self.searchBarBoundsY, [UIScreen mainScreen].bounds.size.width, 44)];
        self.searchBar.searchBarStyle       = UISearchBarStyleMinimal;
        self.searchBar.tintColor            = [UIColor whiteColor];
        self.searchBar.barTintColor         = [UIColor whiteColor];
        self.searchBar.delegate             = self;
        self.searchBar.placeholder          = @"search here";

        [[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setTextColor:[UIColor whiteColor]];

        // add KVO observer.. so we will be informed when user scroll colllectionView
        [self addObservers];
    

    if (![self.searchBar isDescendantOfView:self.view]) 
        [self.view addSubview:self.searchBar];
    


-(void)addRefreshControl
    if (!self.refreshControl) 
        self.refreshControl                  = [UIRefreshControl new];
        self.refreshControl.tintColor        = [UIColor whiteColor];
        [self.refreshControl addTarget:self
                                action:@selector(refreashControlAction)
                      forControlEvents:UIControlEventValueChanged];
    
    if (![self.refreshControl isDescendantOfView:self.collectionView]) 
        [self.collectionView addSubview:self.refreshControl];
    

-(void)startRefreshControl
    if (!self.refreshControl.refreshing) 
        [self.refreshControl beginRefreshing];
    


#pragma mark - observer 
- (void)addObservers
    [self.collectionView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];

- (void)removeObservers
    [self.collectionView removeObserver:self forKeyPath:@"contentOffset" context:Nil];

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(UICollectionView *)object change:(NSDictionary *)change context:(void *)context
    if ([keyPath isEqualToString:@"contentOffset"] && object == self.collectionView ) 
        self.searchBar.frame = CGRectMake(self.searchBar.frame.origin.x,
                                          self.searchBarBoundsY + ((-1* object.contentOffset.y)-self.searchBarBoundsY),
                                          self.searchBar.frame.size.width,
                                          self.searchBar.frame.size.height);
    



@end

【问题讨论】:

【参考方案1】:

可以通过检查属性检查器下的Section Header将标题添加到情节提要中:

您还需要在您的集合视图数据源中实现以下方法:

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

    UICollectionReusableView *view = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"header" forIndexPath:indexPath];
    return view;

在情节提要中也为标题设置了标识符。

标题高度可以通过委托方法控制:

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section 
    return CGSizeMake(0, 80);

故事板的外观如下:

您在手动添加搜索栏时可能无法获得正确的布局。可以在情节提要中添加搜索栏。如果您选择在故事板中添加搜索栏,您将不得不重新构建您的视图,包括您的集合视图,以便它们包含在父视图中。否则,您必须手动操作约束以获得搜索栏的正确定位。

【讨论】:

似乎没有办法定位标题....我也尝试制作 (10,70)- 但只是 x-position 不起作用...请参阅我更新的帖子 标题位置正确,但您添加的搜索栏干扰了布局。我建议您按照这篇文章***.com/questions/25460764/… 的已接受答案来安排您的观点,以防止这种情况发生。 CGSize 仅用于高度,根据滚动方向仅使用一个值。由于您是垂直滚动,因此仅使用 y 值。 但是在这里我们以编程方式添加搜索栏,而不是通过故事板添加搜索栏来设置层次结构视图,就像接受的答案外观一样。有什么方法可以在代码中添加相同的层次结构视图.... 如果不是,那么我必须通过故事板添加搜索栏以获得我需要的视图的唯一方法——对吗?? 您可能能够以编程方式添加约束并在代码中执行调整大小,但这可能需要更多的努力。由于集合视图的约束之一,您的集合视图似乎不合适。我建议以情节提要的方式进行,因为它是一种更简洁的解决方案。【参考方案2】:

@Daniel Zhang 说,你是垂直滚动的。所以你不能使用x轴来改变位置。但你可以做一件事.....做步骤:

1. Add the code @Daniel Zhang suggest and do
2. In story board make the header size height = 80, then place the label over there.

3. Then add constraint (i.e as you want where to place your header title).Then give background color for label. so that it will show different from your cell,searchbar.
4. Make you cell top = 0. You can do when you click your collection view & move to size inspector.

就是这样,运行看看你会看到你的标题和单元格、搜索栏不同。

试试这个它对我的工作。如果它不起作用。试试看这个demo project where they use search bar using story-board

【讨论】:

以上是关于如何在下面顶部的集合视图中为部分添加标题的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Xcode 中为我的表格视图添加上边距?

tableview 顶部的视图显示在下面

我可以将集合视图添加到集合视图部分标题吗?

为 pandas hist plots 集合添加标题

AirBnb 如何创建具有不同单元格的集合视图?

如何使表格视图内的单元格开始向下?