一.写一个类用于显示相机和系统相册界面
在plist文件设置相应的权限框文本
1.创建一个XLImagePicker类,并定义一个block用于回调数据到类方法创建的地方
//定义一个block用于回调数据
typedef void(^PickingBlock)(NSArray *pictureModelArray);
@interface XLImagePicker : NSObject
//显示挑选界面
+(void)showPickerWithType:(ActionType)type handle:(PickingBlock)block;
@end
2.让该类遵从系统以及我们自身创建的协议,实现相应的代理方法
@interface XLImagePicker()
//定义一个变量用于保存block
@property (nonatomic, copy) PickingBlock PickerBlock;
@end
//全局化,便于操作
XLImagePicker *picker = nil;
@implementation XLImagePicker
#pragma mark -------显示挑选界面 ---------
+(void)showPickerWithType:(ActionType)type handle:(PickingBlock)block{
//初始化一个实例
picker = [XLImagePicker new];
//保存block
picker.PickerBlock = block;
//判断是否授权
if ([XLSystemAlbumManager isXLHaveAuthorityWithType:type]) {
//判断显示什么挑选界面
if (type == ActionTypeLibrary) {
//授权点击
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
if(status == PHAuthorizationStatusAuthorized) {
//用户点击允许
//系统相册
[picker showSystemAlbum];
} else {
// 用户点击 不允许访问
}
}];
}else{
//读取设备授权状态
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
if (granted) {
//允许了
//相机
[picker showCamera];
}
}];
}
}else{
//警告框
XLActionViewController *myAlert = [XLActionViewController showAlertControllerWithType:AlertTypeAlert AndName:@"请设置相关权限"];
//解决循环引用的可能
__block typeof(myAlert) weakAlert = myAlert;
//移除
[myAlert setCancelblock:^{
[weakAlert dismiss];
}];
}
}
#pragma mark -------相册 ---------
-(void)showSystemAlbum{
//创建系统相册界面
XLSystemAlbumController *sac = [XLSystemAlbumController new];
//设置系统相册界面遵循代理对象
sac.delegate = self;
//监听设置代理的消息
[[NSNotificationCenter defaultCenter] addObserverForName:kPictureSetDelegateNotificationName object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
//获得界面
XLSystemPictureController *spc = (XLSystemPictureController *)note.object;
//设置系统相册内部界面遵循代理对象
spc.delegate = self;
}];
//弹出相册
//中途需要导航栏
XLNavigationController *mynav = [[XLNavigationController alloc] initWithRootViewController:sac];
//找到当前界面的视图
//1.通过窗口找到当前的界面
XLNavigationController *nav = (XLNavigationController *)[UIApplication sharedApplication].keyWindow.rootViewController;
//2.找到导航栏控制器当前显示的界面
UIViewController *pictureView = nav.visibleViewController;
//跳转
[pictureView presentViewController:mynav animated:YES completion:nil];
}
#pragma mark -------相机 ---------
-(void)showCamera{
//先判断相机是否可用
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
//创建相机
UIImagePickerController *ipc = [[UIImagePickerController alloc] init];
//设置来源
ipc.sourceType = UIImagePickerControllerSourceTypeCamera;
//支持的类型
ipc.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera];
//设置代理
ipc.delegate = picker;
//弹出相机
//中途需要导航栏
XLNavigationController *mynav = [[XLNavigationController alloc] initWithRootViewController:ipc];
//找到当前界面的视图
//1.通过窗口找到当前的界面
XLNavigationController *nav = (XLNavigationController *)[UIApplication sharedApplication].keyWindow.rootViewController;
//2.找到导航栏控制器当前显示的界面
UIViewController *pictureView = nav.visibleViewController;
//跳转
[pictureView presentViewController:mynav animated:YES completion:nil];
}else{
//警告框
XLActionViewController *myAlert = [XLActionViewController showAlertControllerWithType:AlertTypeAlert AndName:@"你的摄像头不可用"];
//解决循环引用的可能
__block typeof(myAlert) weakAlert = myAlert;
//移除
[myAlert setCancelblock:^{
[weakAlert dismiss];
}];
}
}
#pragma mark -------相册的代理方法 ---------
//Cancel按钮被点击了
-(void)XLImagesPickerControllerDidCancel:(XLSystemAlbumController *)picker{
//移除视图
[picker dismissViewControllerAnimated:YES completion:nil];
}
//Done按钮被点击了
-(void)XLImagesPickerController:(XLSystemPictureController *)picker didFinishedPickingWithInfo:(NSArray *)info{
//移除视图
[picker dismissViewControllerAnimated:YES completion:nil];
}
#pragma mark -------相机的代理方法 ---------
//点击Cancel按钮
-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker{
//移除imagePickerController
[picker dismissViewControllerAnimated:YES completion:nil];
}
//内容被封装在info里面
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
//移除imagePickerController
[picker dismissViewControllerAnimated:YES completion:nil];
}
@end
3.由于系统相册内部界面不是在当前界面创建的,而是和当前界面隔了一层界面,我们通过消息通知设置代理对象,在StringConstants中加入消息,监听消息,接受就好
//系统相册内部界面设置代理的消息
#define kPictureSetDelegateNotificationName @"kPictureSetDelegateNotificationName"
二.完善XLPictureCell的显示
1..h文件里面定义一个变量接受数据显示信息,还要定义一个变量接受状态,加上之前的接受Cell类型的变量,最后添加一个更改按钮的状态的接口
@interface XLPictureCell : UICollectionViewCell
//接受外界传递过来的数据
@property (nonatomic,strong) XLPictureModel *model;
//接受外界传递过来的Cell类型
@property (nonatomic,assign) CellType type;
/**接受外界传递过来的编辑状态*/
@property (nonatomic,assign) BOOL isEditing;
//更改勾选按钮的状态
- (void)changeStatus:(BOOL)status;
@end
2.重写type的set方法,确定勾选按钮和添加按钮是否需要添加
#pragma mark -------重写type的set方法 ---------
-(void)setType:(CellType)type{
_type = type;
//判断type的类型
if (type == CelllTypeAdd) {
//隐藏勾选按钮
self.selectImageView.hidden = YES;
//显示添加按钮
self.addImageView.hidden = NO;
}else if(type == CellTypeSystem){
//显示勾选按钮
self.selectImageView.hidden = NO;
//隐藏添加按钮
self.addImageView.hidden = YES;
}else{
//隐藏勾选按钮
self.selectImageView.hidden = YES;
//隐藏添加按钮
self.addImageView.hidden = YES;
}
}
3.重写isEditing的set方法,判断勾选按钮是否需要显示
#pragma mark -------重写isEditing的set方法 ---------
-(void)setIsEditing:(BOOL)isEditing{
_isEditing = isEditing;
if (isEditing == YES) {
//显示勾选按钮
self.selectImageView.hidden = NO;
}else{
//隐藏勾选按钮
self.selectImageView.hidden = YES;
}
}
4.实现勾选按钮状态改变的方法
#pragma mark -------更改勾选按钮的状态 ---------
- (void)changeStatus:(BOOL)status{
if (status == YES) {
//选中
self.selectImageView.image = [UIImage imageNamed:@"selected_selected"];
}else{
//未选中
self.selectImageView.image = [UIImage imageNamed:@"selected_normal"];
}
}
5.重写model的set方法,让Cell显示数据
#pragma mark -------重写model的set方法一有数据就赋值 ---------
-(void)setModel:(XLPictureModel *)model{
_model = model;
//缩略图
self.iconImageView.image = model.iconImage;
//判断时长
if (model.duration > 0) {
//显示视频时间
self.timeBgView.hidden = NO;
self.timeLabel.text = model.duration;
}else{
//隐藏视频时间
self.timeBgView.hidden = YES;
}
//selected的视图 默认不选中
[self changeStatus:self.isSelected];
}
三.系统相册界面显示跳转到个人相册界面
1.显示:我们通过XLSystemAlbumManager的getAllSystemAlbumArray方法获得所有系统相册的模型数据,并显示数据
#pragma mark -------类方法创建 ---------
+(XLAlbumTableView *)showAlbumView:(CGRect)frame ViewType:(ViewType)type Array:(NSMutableArray *)modelsArray superView:(UIView *)sView{
//创建
XLAlbumTableView *atv = [[XLAlbumTableView alloc] initWithFrame:frame];
//保存类型
atv.type = type;
//保存数据
atv.modelsArray = modelsArray;
//显示
[sView addSubview:atv];
return atv;
}
#pragma mark -------重写initWithFrame方法 布局 ---------
-(instancetype)initWithFrame:(CGRect)frame{
if (self = [super initWithFrame:frame]) {
//创建tableView
self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];
//设置代理
_tableView.delegate = self;
_tableView.dataSource = self;
//去除纵向滚动条
_tableView.showsVerticalScrollIndicator = NO;
//设置分割线风格
_tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
//编辑模式下是否允许多选
_tableView.allowsMultipleSelectionDuringEditing = YES;
//显示
[self addSubview:_tableView];
//注册cell
[_tableView registerNib:[UINib nibWithNibName:@"XLAlbumCell" bundle:nil] forCellReuseIdentifier:@"cellID"];
}
return self;
}
#pragma mark -------UITableView ---------
//配置有多少个相册
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return self.modelsArray.count;
}
//配置每个相册具体显示什么内容
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//创建cell
XLAlbumCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cellID"];
//传递数据
cell.model = self.modelsArray[indexPath.row];
return cell;
}
//配置cell的高度
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 100;
}
//某个cell被点击了
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
//判断编辑状态
if (self.tableView.editing) {
//编辑状态
//告诉manager某一个被点击了
[[XLAlbumManager sharedManager] albumEditingStatusChanged:YES index:indexPath.row];
}else{
//正常状态
//1.取消选中
[tableView deselectRowAtIndexPath:indexPath animated:YES];
//判断是什么相册
if (_type == ViewTypePerson) {
//个人相册
}else{
//系统相册
}
}
}
//某个cell取消选中了
-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath{
//判断是不是编辑状态
if (self.tableView.editing) {
//告诉manager某一个取消点击了
[[XLAlbumManager sharedManager] albumEditingStatusChanged:NO index:indexPath.row];
}
}
//设置tableView的编辑状态 左边显示的样式 delete insert none
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{
//可以勾选的样式
return UITableViewCellEditingStyleInsert | UITableViewCellEditingStyleDelete;
}
@end
2.跳转:因为我们的XLAlbumTableView既会用来创建个人相册界面,又会被用来创建系统相册界面,在cell被点击的方法里面判断是哪一种情况被点击。当是系统相册时,创建系统相册内部界面并跳转,此时,该类被创建,就可以向XLImagePicker中发送消息,设置其代理对象
//某个cell被点击了
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
//判断编辑状态
if (self.tableView.editing) {
//编辑状态
//告诉manager某一个被点击了
[[XLAlbumManager sharedManager] albumEditingStatusChanged:YES index:indexPath.row];
}else{
//正常状态
//1.取消选中
[tableView deselectRowAtIndexPath:indexPath animated:YES];
//判断是什么相册
if (_type == ViewTypePerson) {
//个人相册
}else{
//系统相册
//2.进入下一个界面
XLSystemPictureController *svc = [XLSystemPictureController new];
//设置代理对象
[[NSNotificationCenter defaultCenter] postNotificationName:kPictureSetDelegateNotificationName object:svc];
//3.传递数据
svc.albumModel = self.modelsArray[indexPath.row];
//4.找到当前的导航栏控制器
XLNavigationController *nav = (XLNavigationController *)[UIApplication sharedApplication].keyWindow.rootViewController;
//5.找到导航栏控制器的顶部视图
XLPersonPictureController *ppc = (XLPersonPictureController *)nav.topViewController;
//6.找到顶部视图present的视图
XLNavigationController *navPresent = (XLNavigationController *)ppc.presentedViewController;
//7.跳转
[navPresent pushViewController:svc animated:YES];
}
}
}
四.系统相册内部界面显示
我们通过XLSystemAlbumManager的getAllPictureInAssetCollection方法获得某个系统相册里面的资源模型数据,并显示数据
@interface XLPictureCollectionView ()
/**接受传递的类型*/
@property (nonatomic,assign) ViewType type;
/**接受传递的相册模型*/
@property (nonatomic,strong) XLAlbumModel *albumModel;
/**保存我们显示的资源模型*/
@property (nonatomic,strong) NSMutableArray *pictureModelArray;
/**属性化的collectionView*/
@property (nonatomic,strong) UICollectionView *collectionView;
/**记录编辑状态*/
@property (nonatomic,assign) BOOL isEditing;
@end
@implementation XLPictureCollectionView
#pragma mark -------类方法创建 ---------
+(XLPictureCollectionView *)showCollectionView:(CGRect)frame ViewType:(ViewType)type Model:(XLAlbumModel *)model toView:(UIView *)superView{
//创建
XLPictureCollectionView *pcv = [[XLPictureCollectionView alloc] initWithFrame:frame];
//保存类型
pcv.type = type;
//保存传递过来的相册模型
pcv.albumModel = model;
//保存数据
if (type == ViewTypeSystem) {
//加载系统相册的图片
pcv.pictureModelArray = [[XLSystemAlbumManager sharedSystemAlbum] getAllPictureInAssetCollection:model.assetCollection ascending:NO];
}else{
//加载个人相册的图片
}
//显示
[superView addSubview:pcv];
return pcv;
}
#pragma mark -------重写initWithFrame方法 布局 ---------
-(instancetype)initWithFrame:(CGRect)frame{
if (self = [super initWithFrame:frame]) {
//当前视图的背景颜色
self.backgroundColor = [UIColor clearColor];
//创建布局对象
UICollectionViewFlowLayout *layout = [UICollectionViewFlowLayout new];
//每一个item的大小
layout.itemSize = CGSizeMake(kSize, kSize);
//竖向最小间距
layout.minimumLineSpacing = 1;
//横向最小间距
layout.minimumInteritemSpacing = 0.001f;
//layout.sectionInset = UIEdgeInsetsMake(5, 5, 5,5);
//创建collectionView
self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height) collectionViewLayout:layout];
//collectionView的背景颜色
_collectionView.backgroundColor = [UIColor clearColor];
//设置代理
_collectionView.delegate = self;
_collectionView.dataSource = self;
//显示
[self addSubview:_collectionView];
//注册
[_collectionView registerNib:[UINib nibWithNibName:@"XLPictureCell" bundle:nil] forCellWithReuseIdentifier:@"cellID"];
}
return self;
}
#pragma mark -------UICollectionView代理方法 ---------
//返回item的数量
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
//判断是什么类型
if (self.type == ViewTypePerson) {
//个人相册
return 1;
}else{
//系统相册
return self.pictureModelArray.count;
}
}
//每个cell显示什么
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
//创建
XLPictureCell *cell;
//判断类型
if (self.type == ViewTypePerson) {
//个人相册
//判断是不是第一个cell被点击了
if (indexPath.row == 0) {
//初始化cell
cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cellID" forIndexPath:indexPath];
//cell的类型
cell.type = CelllTypeAdd;
}else{
}
}else{
//系统相册
//初始化cell
cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cellID" forIndexPath:indexPath];
//传递数据
cell.model = self.pictureModelArray[indexPath.row];
//cell的类型
cell.type = CellTypeSystem;
}
return cell;
}
//item被点击了
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
//判断类型
if (self.type == ViewTypePerson) {
//个人相册
//判断是不是第一个被点击了
if (indexPath.row == 0) {
}else{
//第一个之外的被点击了
//判断是不是编辑状态
if (self.isEditing) {
//编辑状态
}else{
//进入浏览界面
}else{
//系统相册
//获取indexPath.row对应的model
XLPictureModel *model = self.pictureModelArray[indexPath.row];
//更改isSelected的状态
model.isSelected = !model.isSelected;
//获取当前的cell
XLPictureCell *cell = (XLPictureCell*)[collectionView cellForItemAtIndexPath:indexPath];
//将状态传递给cell
[cell changeStatus:model.isSelected];
//判断资源有没有被选中
if (model.isSelected == YES) {
//加入临时资源数组中
[[XLSystemAlbumManager sharedSystemAlbum].selectedArray addObject:model];
}else{
//从临时资源数组中移除
[[XLSystemAlbumManager sharedSystemAlbum].selectedArray removeObject:model];
}
}
}
@end