前两天有一个需要点击一个按钮控件弹出 UIPopoverPresentationController 的需求,并且在 弹出的 Controller 中需要显示一个 UICollectionView ,Cell 中又一张图片,一个Label,数据需要充数据库中读取。
我们首先要做的事情就是 创建一个用于 UIPopoverPresentationController 弹出的 Controller ,
下面是 h 文件
//
// PDPeopleCollectionView.h
// PeopleView
//
// Created by Will Han on 12/23/15.
// Copyright © 2015 GearPart. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "Entities.h"
@interface PDPeopleView : UIViewController
@property(copy, nonatomic) NSArray *titles;
@property(copy, nonatomic) NSArray *groupOne; /**< DataEntity */
@property(copy, nonatomic) NSArray *groupTwo; /**< DataEntity */
@end
我们在该 h 文件中设置了三个数组,titles 用于显示 UICollectionView 中 Section 的 Header,因为可能有多个Section 所以用到了数组, groupOne 和 groupTwo 是为了存放 Section1 和 Section2 中cell 中的Label 中的数据(这里先放两个Section,以后可以根据需求自行增加或者减少)
下面是 m 文件
//
// PDPeopleCollectionView.m
//
// Created by Jack on 12/23/15.
// Copyright © 2015 GearPart. All rights reserved.
//
#import "PDPeopleView.h"
#pragma mark - header
#import <UIKit/UIKit.h>
#define kCollectionHeaderViewIdentifier @"aHeader"
@interface PDPeopleCollectionHeaderView : UICollectionReusableView
@property(strong, nonatomic) UILabel *headerLabel;
@end
@implementation PDPeopleCollectionHeaderView
@synthesize headerLabel;
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = kBackgroundColor_RGB255;
headerLabel = [[UILabel alloc] init];
headerLabel.translatesAutoresizingMaskIntoConstraints = NO;
headerLabel.contentMode = UIViewContentModeBottomLeft;
headerLabel.font = TheSystemBoldFont(15);
headerLabel.textColor = kFontColor_R102G119GB136;
[self addSubview:headerLabel];
AddConstraints(self, @[ @"H:|-20-[headerLabel]-20-|", @"V:|-(>=0)-[headerLabel]-5-|" ], nil, NSDictionaryOfVariableBindings(headerLabel));
}
return self;
}
@end
#pragma mark - cell
#define kCellIndentifier @"aCell"
@interface PeopleViewCell : UICollectionViewCell
@property(strong, nonatomic) UIImageView *iv;
@property(strong, nonatomic) UILabel *lb;
@end
@implementation PeopleViewCell
@synthesize iv;
@synthesize lb;
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
iv = [[UIImageView alloc] init];
iv.translatesAutoresizingMaskIntoConstraints = NO;
iv.layer.cornerRadius = 45.f / 2.f;
#if DEBUG
iv.layer.borderWidth = 1.f;
iv.layer.borderColor = [[UIColor orangeColor] CGColor];
iv.contentMode = UIViewContentModeScaleToFill;
#endif
iv.clipsToBounds = YES;
lb = [[UILabel alloc] init];
lb.translatesAutoresizingMaskIntoConstraints = NO;
lb.font = TheSystemFont(14);
lb.textColor = kFontColor_R102G119GB136;
lb.lineBreakMode = NSLineBreakByTruncatingTail;
lb.numberOfLines = 0;
[self addSubview:iv];
[self addSubview:lb];
AddCenterYConstraints(self, iv, lb, nil);
AddHeightConstraints(self, 45, iv, nil);
AddConstraints(self, @[ @"H:|[iv(45)]-5-[lb(100)]|", @"V:|[lb]|" ], nil, NSDictionaryOfVariableBindings(iv, lb));
}
return self;
}
@end
#pragma mark - controller
@interface PDPeopleView () <UICollectionViewDataSource, UICollectionViewDelegate>
@property(strong, nonatomic) UICollectionView *cw;
@end
@implementation PDPeopleView
@synthesize titles;
@synthesize groupOne;
@synthesize groupTwo;
@synthesize cw;
- (void)viewDidLoad {
[super viewDidLoad];
UICollectionViewFlowLayout *flowLayout = [UICollectionViewFlowLayout instance];
flowLayout.itemSize = CGSizeMake(150, 57);
flowLayout.minimumInteritemSpacing = 10.0f;
flowLayout.minimumLineSpacing = 0.0f;
if ([flowLayout respondsToSelector:@selector(setSectionHeadersPinToVisibleBounds:)]) {
flowLayout.sectionHeadersPinToVisibleBounds = YES;
}
if ([flowLayout respondsToSelector:@selector(setSectionFootersPinToVisibleBounds:)]) {
flowLayout.sectionFootersPinToVisibleBounds = YES;
}
self.cw = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:flowLayout];
self.cw.translatesAutoresizingMaskIntoConstraints = NO;
self.cw.dataSource = self;
self.cw.delegate = self;
self.cw.backgroundColor = [UIColor whiteColor];
[self.cw registerClass:[PeopleViewCell class] forCellWithReuseIdentifier:kCellIndentifier];
[self.cw registerClass:[PDPeopleCollectionHeaderView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:kCollectionHeaderViewIdentifier];
[self.view addSubview:self.cw];
AddConstraints(self.view, @[ @"H:|[cw]|", @"V:|[cw]|" ], nil, @{ @"cw" : cw });
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
CGSize size;
CGFloat v1 = (groupOne.count / 2 + groupOne.count % 2) * 57 + 45 + 20;
CGFloat v2 = v1 + (groupTwo.count / 2 + groupTwo.count % 2) * 57 + 45;
if (groupTwo.count == 0) {
if (v1 > 338) {
v1 = 338;
}
size = (groupOne.count == 1) ? CGSizeMake(190, v1) : CGSizeMake(350, v1);
} else {
if (v2 > 338) {
v2 = 338;
}
size = (groupTwo.count == 1 && groupOne.count == 1) ? CGSizeMake(190, v2) : CGSizeMake(350, v2);
}
[self setPreferredContentSize:size];
UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)cw.collectionViewLayout;
size.height = 45.f;
layout.headerReferenceSize = size;
}
#pragma mark - data source
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
if (groupTwo.count == 0) {
return 1;
}
return 2;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
if (section == 0) {
return groupOne.count;
}
return groupTwo.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
PeopleViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kCellIndentifier forIndexPath:indexPath];
UserEntity *user;
if (indexPath.section == 0) {
user = groupOne[indexPath.row];
cell.lb.text = user.DisplayName;
cell.iv.image = [UIImage imageNamed:@"idle"];
} else {
// user = groupTwo[indexPath.row];
// cell.lb.text = user.DisplayName;
// cell.iv.image = [UIImage imageNamed:@"document"];
cell.lb.text = groupTwo[indexPath.row];
cell.iv.image = [UIImage imageNamed:@"idle"];
}
return cell;
}
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
if ([UICollectionElementKindSectionHeader isEqualToString:kind]) {
PDPeopleCollectionHeaderView *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:kCollectionHeaderViewIdentifier forIndexPath:indexPath];
headerView.headerLabel.text = (indexPath.section == 0 ? titles[0] : titles[1]);
return headerView;
}
return nil;
}
#pragma mark - delegate
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
return UIEdgeInsetsMake(0, 20, (section == 1 || groupTwo.count == 0) ? 20 : 0, 20);
}
@end
在上面的 m 文件中 定义并规划了 section 的Header , UICollectionViewCell 和 在UIViewController 中实现整体布局以及UICollectionView 的代理,这个 m 文件是有点大,不过滤清了,思路并不复杂。。
这样我们为 UIPopoverPresentationController 准备的 弹出的 Controller 就完成了,下面我们用 UIPopoverPresentationController 来弹出它。
if (self.selectAction.AssignedToList.count == 0) {
return;
}
PDPeopleView *peopleView = [PDPeopleView instance];
peopleView.groupOne = self.selectAction.AssignedToList;
peopleView.titles = @[kAssignee];
peopleView.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController *popover = peopleView.popoverPresentationController;
popover.backgroundColor = kBackgroundColor_RGB255;
popover.sourceView = button.titleLabel;
popover.sourceRect = button.titleLabel.bounds;
popover.permittedArrowDirections = UIPopoverArrowDirectionAny;
[[UIWindow TopViewController] presentViewController:peopleView animated:YES completion:nil];
上面的那段代码就是 UIPopoverPresentationController 弹出的 Controller 的过程了,需要注意的是 最好写成是 popover.sourceView = button.titleLabel; 而不要写成 popover.sourceView = button; 因为我们要指向的是文字文字,所以如果写成 popover.sourceView = button如果 Button 中还有包含其他控件,箭头有可能会偏离文字。。
效果如下图 :
单列数据:
双排数据:
这样就完成了需求,有问题欢迎留言交流~~