1.下拉刷新控件
2.上拉加载更多控件
3.自定义UIAlertView
4.自定义照片选择器(可多选)
下拉刷新控件
//VRefreshHeadView.h文件
//
// VRefreshHeadView.h
// 下拉刷新控件
//
// Created by Vie on 2016/10/10.
// Copyright © 2016年 Vie. All rights reserved.
//
#import <UIKit/UIKit.h>
typedef NS_ENUM(NSUInteger, VRefreshType) {
VRefreshTypeDefault = 0,//默认下拉刷新样式
};
@interface VRefreshHeadView : UIView
typedef void (^beginRefreshBlock) (VRefreshHeadView *vrefresh);//刷新事件回调
@property(nonatomic,assign) NSUInteger type;//刷新视图样式
/**
创建下拉刷新视图
@param scrollView 滚动视图
@param beginRefreshBlock 开始刷新回调
@return 刷新视图对象
*/
-(instancetype)initWithScrollView:(UIScrollView *)scrollView beginRefreshBlock:(beginRefreshBlock)beginRefreshBlock;
//停止刷新
-(void)endRefresh;
@end
//VRefreshHeadView.m文件
//
// VRefreshHeadView.m
// 下拉刷新控件
//
// Created by Vie on 2016/10/10.
// Copyright © 2016年 Vie. All rights reserved.
//
#import "VRefreshHeadView.h"
#define vRefreshHeadViewHeight 40
#define navBarHeight 64 //竖屏导航栏和控制器高度(竖屏导航栏高度44,竖屏状态栏高度为20、打电话或者某些情况为40)
@interface VRefreshHeadView ()
@property (nonatomic,copy) beginRefreshBlock beginRefreshBlock;
@property(nonatomic,weak) UIScrollView *scrollView;
/**
*头部提示语
*/
@property(nonatomic,weak) UILabel *headTipLable;
/**
* 加载提示
*/
@property (nonatomic, weak) UIActivityIndicatorView *indicatorView;
/**
*是否处于刷新状态
*/
@property(nonatomic,assign) BOOL isRefresh;
@end
@implementation VRefreshHeadView
#pragma mark - init方法
-(instancetype)initWithScrollView:(UIScrollView *)scrollView beginRefreshBlock:(beginRefreshBlock)beginRefreshBlock{
self=[super initWithFrame:CGRectMake(0, -vRefreshHeadViewHeight, scrollView.frame.size.width, vRefreshHeadViewHeight)];
if (self) {
_scrollView=scrollView;
_beginRefreshBlock=beginRefreshBlock;
//把当前视图加载到scrollView的UI
[_scrollView addSubview:self];
//设置背景颜色
self.backgroundColor=[UIColor clearColor];
//默认不在刷新状态
self.isRefresh=false;
//注册观察者,监听下拉刷新改变
[_scrollView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];
}
return self;
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
if ([keyPath isEqualToString:@"contentOffset"]) {
if (_scrollView.contentOffset.y<(-navBarHeight-vRefreshHeadViewHeight)&&!self.isRefresh&&_scrollView.dragging) {
[self.indicatorView startAnimating];
self.isRefresh=true;
self.headTipLable.text=@"加载中..";
_scrollView.contentInset = UIEdgeInsetsMake(vRefreshHeadViewHeight+navBarHeight, 0, 0, 0);
if (_beginRefreshBlock) {
_beginRefreshBlock(self);
}
}
}
}
//停止刷新
-(void)endRefresh{
[UIView animateWithDuration:0.3 animations:^{
// _scrollView.contentInset = UIEdgeInsetsZero;
_scrollView.contentInset = UIEdgeInsetsMake(navBarHeight, 0, 0, 0);
} completion:^(BOOL finished) {
[self.indicatorView stopAnimating];
self.isRefresh=false;
_headTipLable.text=@"下拉刷新数据";
}];
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
*/
- (void)drawRect:(CGRect)rect {
// Drawing code
if (_type) {
}else{
//没有指定type用默认视图
[self setDefaultView];
}
}
//默认样式
-(void)setDefaultView{
[self headTipLable];
}
#pragma mark - 懒加载创建控件
- (UIActivityIndicatorView *)indicatorView
{
if (!_indicatorView)
{
UIActivityIndicatorView *act = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(50, 0, 30, self.frame.size.height)];
act.color = [UIColor grayColor];
[self addSubview:act];
_indicatorView = act;
}
return _indicatorView;
}
-(UILabel *)headTipLable{
if (!_headTipLable) {
UILabel *lb = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width,self.frame.size.height)];
lb.textAlignment = NSTextAlignmentCenter;
lb.textColor = [UIColor grayColor];
lb.font = [UIFont systemFontOfSize:13];
lb.text = @"下拉刷新数据";
[self addSubview:lb];
_headTipLable = lb;
}
return _headTipLable;
}
-(void)dealloc{
[_scrollView removeObserver:self forKeyPath:@"contentOffset"];
}
@end
//使用
#import "VRefreshHeadView.h"
@property(nonatomic,strong) VRefreshHeadView *vrefresh;
-(VRefreshHeadView *)vrefresh{
__weak typeof(self) weakSelf = self;
if (!_vrefresh) {
_vrefresh=[[VRefreshHeadView alloc] initWithScrollView:weakSelf.tbView beginRefreshBlock:^(VRefreshHeadView *vrefresh) {
NSLog(@"进入刷新回调");
[self performSelector:@selector(endVrefresh) withObject:nil afterDelay:3.0f];
}];
}
return _vrefresh;
}
[self vrefresh];
上拉加载更多控件
//VLoadMoreFootView.h文件
//
// VLoadMoreFootView.h
// 上拉加载更多控件
//
// Created by Vie on 2016/10/17.
// Copyright © 2016年 Vie. All rights reserved.
//
#import <UIKit/UIKit.h>
typedef NS_ENUM(NSUInteger, VLoadMoreType) {
VLoadMoreTypeDefault = 0,//默认上拉加载样式
};
@interface VLoadMoreFootView : UIView
typedef void (^beginLoadMoreBlock) (VLoadMoreFootView *vrefresh);//加载更多事件回调
@property(nonatomic,assign) NSUInteger type;//加载更多视图样式
/**
创建上拉加载新视图
@param scrollView 滚动视图
@param beginLoadMoreBlock 开始加载更多回调
@return 加载视图对象
*/
-(instancetype)initWithScrollView:(UIScrollView *)scrollView beginLoadMoreBlock:(beginLoadMoreBlock)beginLoadMoreBlock;
//停止加载
-(void)endLoadMore;
@end
//VLoadMoreFootView.m文件
//
// VLoadMoreFootView.m
// 上拉加载更多控件
//
// Created by Vie on 2016/10/17.
// Copyright © 2016年 Vie. All rights reserved.
//
#import "VLoadMoreFootView.h"
#define vLoadMoreBottomViewHeight 40
#define navBarHeight 64 //竖屏导航栏和控制器高度(竖屏导航栏高度44,竖屏状态栏高度为20、打电话或者某些情况为40)
@interface VLoadMoreFootView()
@property(nonatomic,copy) beginLoadMoreBlock beginLoadMoreBlock;
@property(nonatomic,weak) UIScrollView *scrollView;
/**
*底部提示语
*/
@property(nonatomic,weak) UILabel *bottomTipLable;
/**
*加载提示
*/
@property(nonatomic,weak) UIActivityIndicatorView *indicatorView;
/**
*是否处于加载状态
*/
@property(nonatomic,assign) BOOL isLoad;
@end
@implementation VLoadMoreFootView
#pragma mark - init方法
-(instancetype)initWithScrollView:(UIScrollView *)scrollView beginLoadMoreBlock:(beginLoadMoreBlock)beginLoadMoreBlock{
self=[super initWithFrame:CGRectMake(0, 0, scrollView.frame.size.width, vLoadMoreBottomViewHeight)];
if (self) {
_scrollView=scrollView;
_beginLoadMoreBlock=beginLoadMoreBlock;
//把当前视图加载到scrollView的UI
[_scrollView addSubview:self];
//设置背景颜色
self.backgroundColor=[UIColor clearColor];
//默认不在加载状态
self.isLoad=false;
//注册观察这,监听上拉加载改变
[_scrollView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];
}
return self;
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
if ([keyPath isEqualToString:@"contentOffset"]) {
if (_scrollView.contentOffset.y>(_scrollView.contentSize.height-_scrollView.frame.size.height)&&!self.isLoad&&_scrollView.dragging) {
[self.indicatorView startAnimating];
self.isLoad=true;
self.bottomTipLable.text=@"加载中..";
_scrollView.contentInset = UIEdgeInsetsMake(0, 0, vLoadMoreBottomViewHeight, 0);
if (_beginLoadMoreBlock) {
_beginLoadMoreBlock(self);
}
}
}
}
//停止加载
-(void)endLoadMore{
[UIView animateWithDuration:0.3 animations:^{
// _scrollView.contentInset = UIEdgeInsetsZero;
_scrollView.contentInset = UIEdgeInsetsMake(navBarHeight, 0, 0, 0);
} completion:^(BOOL finished) {
[self.indicatorView stopAnimating];
self.isLoad=false;
_bottomTipLable.text = @"上拉加载更多数据";
}];
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
*/
- (void)drawRect:(CGRect)rect {
// Drawing code
if (_type) {
}else{
//没有指定type用默认视图
[self setDefaultView];
}
}
//默认样式
-(void)setDefaultView{
[self bottomTipLable];
}
-(UILabel *)bottomTipLable{
if (!_bottomTipLable) {
UILabel *lb = [[UILabel alloc] initWithFrame:CGRectMake(0, _scrollView.contentSize.height, self.frame.size.width,self.frame.size.height)];
lb.textAlignment = NSTextAlignmentCenter;
lb.textColor = [UIColor grayColor];
lb.font = [UIFont systemFontOfSize:13];
lb.text = @"上拉加载更多数据";
[self addSubview:lb];
_bottomTipLable = lb;
}
return _bottomTipLable;
}
#pragma mark - 懒加载创建控件
- (UIActivityIndicatorView *)indicatorView
{
if (!_indicatorView)
{
UIActivityIndicatorView *act = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(50, _scrollView.contentSize.height, 30, self.frame.size.height)];
act.color = [UIColor grayColor];
[self addSubview:act];
_indicatorView = act;
}
return _indicatorView;
}
-(void)dealloc{
[_scrollView removeObserver:self forKeyPath:@"contentOffset"];
}
@end
//使用
#import "VLoadMoreFootView.h"
@property(nonatomic,strong) VLoadMoreFootView *vload;
-(VLoadMoreFootView *)vload{
__weak typeof(self) weakSelf=self;
if (!_vload) {
_vload=[[VLoadMoreFootView alloc] initWithScrollView:weakSelf.tbView beginLoadMoreBlock:^(VLoadMoreFootView *vrefresh) {
NSLog(@"进入上拉加载");
[self performSelector:@selector(endVload) withObject:nil afterDelay:3.0f];
}];
}
return _vload;
}
-(void)endVload{
[_vload endLoadMore];
}
[self vload];
自定义UIAlertView
//TKIMAlertView.h文件
//
// TKIMAlertView.h
// 泰隆微信
// 自定义alertview
// Created by Vie on 2017/1/18.
// Copyright © 2017年 liupm. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface TKIMAlertView : UIAlertView
@property(nonatomic, assign) NSTextAlignment textAlignment;//文本对齐方式
@end
//TKIMAlertView.m文件
//
// TKIMAlertView.m
// 泰隆微信
// 自定义alertview
// Created by Vie on 2017/1/18.
// Copyright © 2017年 liupm. All rights reserved.
//
#import "TKIMAlertView.h"
@implementation TKIMAlertView
//iOS7以后获取alertview的subviews为空
-(void)show{
[super show];
float alertWith=268;
float textLabelX=20;
//文本占用空间
CGSize messageSize=[self.message boundingRectWithSize:CGSizeMake(alertWith-textLabelX-5, 500) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:15]} context:nil].size;
messageSize.height+=15;
//文本
UILabel *textLabel = [[UILabel alloc] initWithFrame:CGRectMake(textLabelX, 0, alertWith-textLabelX, messageSize.height)];
textLabel.font = [UIFont systemFontOfSize:15];
textLabel.textColor = [UIColor blackColor];
textLabel.backgroundColor = [UIColor clearColor];
textLabel.lineBreakMode =NSLineBreakByWordWrapping;
textLabel.numberOfLines =0;
textLabel.textAlignment =_textAlignment;
textLabel.text =self.message;
//文本背景视图
UIScrollView *view=[[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, alertWith, messageSize.height)];
view.contentSize=CGSizeMake(alertWith, messageSize.height);
//指定控件是否只能在一个方向上滚动(默认为NO)
view.directionalLockEnabled=YES;
[view addSubview:textLabel];
[self setValue:view forKey:@"accessoryView"];
self.message=@"";
}
@end
//使用
TKIMAlertView *alert= [[TKIMAlertView alloc] initWithTitle:[NSString stringWithFormat:@"新版本升级 %@",self.versionModel.version] message:@"1.新版\n2.修复Bug\n" delegate:self cancelButtonTitle:nil otherButtonTitles:@"升级", nil];
alert.textAlignment=NSTextAlignmentLeft;
[alert show];
自定义照片选择器(可多选)
//ChoosePhotosCollectionViewCell.h文件
//
// ChoosePhotosCollectionViewCell.h
// CustomChoosePhotoDemo
// 照片展示器单元格
// Created by Vie on 2017/2/15.
// Copyright © 2017年 Vie. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "ChoosePhotosBlock.h"
@interface ChoosePhotosCollectionViewCell : UICollectionViewCell
@property (strong, nonatomic)UIImageView * photoImageView;//展示缩略图
@property (nonatomic, assign) BOOL chooseFlag;//是否被选中,初始化为否
@property (nonatomic, copy) ChoosePhotosFlag chooseBlock;
//未被选中
-(void)didUncheck;
//被选中
-(void)didSelected;
@end
//ChoosePhotosCollectionViewCell.m文件
//
// ChoosePhotosCollectionViewCell.m
// CustomChoosePhotoDemo
// 照片展示器单元格
// Created by Vie on 2017/2/15.
// Copyright © 2017年 Vie. All rights reserved.
//
#import "ChoosePhotosCollectionViewCell.h"
@interface ChoosePhotosCollectionViewCell ()
@property (strong, nonatomic) UIButton *chooseBtn;//选中按钮
@end
@implementation ChoosePhotosCollectionViewCell
#pragma mark 懒加载
-(UIImageView *)photoImageView{
if (!_photoImageView) {
_photoImageView = [[UIImageView alloc]init];
_photoImageView.translatesAutoresizingMaskIntoConstraints = false;
_photoImageView.contentMode = UIViewContentModeScaleAspectFill;
_photoImageView.layer.masksToBounds = true;
}
return _photoImageView;
}
//显示选择按钮的视图
- (UIButton *)chooseBtn
{
if (_chooseBtn == nil)
{
_chooseBtn= [UIButton buttonWithType:UIButtonTypeCustom];
_chooseBtn.translatesAutoresizingMaskIntoConstraints = false;
[_chooseBtn addTarget:self action:@selector(chooseAction:) forControlEvents:UIControlEventTouchUpInside];
_chooseBtn.translatesAutoresizingMaskIntoConstraints = false;
[_chooseBtn setImage:[UIImage imageNamed:@"uncheck.png"] forState:UIControlStateNormal];
}
return _chooseBtn;
}
#pragma mark 处理界面
-(instancetype)initWithFrame:(CGRect)frame{
self=[super initWithFrame:frame];
if (self) {
[self loadView];
[self layoutVFL];
}
return self;
}
/*加载视图*/
-(void)loadView{
[self addSubview:self.photoImageView];
[self addSubview:self.chooseBtn];
}
/*VFL约束*/
-(void)layoutVFL{
/*photoImageView的约束*/
//水平约束
NSArray * photoImageViewHorizotal = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[_photoImageView]-0-|" options:0 metrics:nil views:@{@"_photoImageView":_photoImageView}];
[self addConstraints:photoImageViewHorizotal];
//垂直约束
NSArray * photoImageViewVertical = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[_photoImageView]-0-|" options:0 metrics:nil views:@{@"_photoImageView":_photoImageView}];
[self addConstraints:photoImageViewVertical];
NSArray * chooseBtnViewHorizotal = [NSLayoutConstraint constraintsWithVisualFormat:@"H:[_chooseBtn(22)]-5-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_chooseBtn)];
[self addConstraints:chooseBtnViewHorizotal];
NSArray * chooseBtnViewVertical = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-5-[_chooseBtn(22)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_chooseBtn)];
[self addConstraints:chooseBtnViewVertical];
}
#pragma mark 事件处理
-(void)chooseAction:(UIButton *)sender{
if (self.chooseFlag) {
[_chooseBtn setImage:[UIImage imageNamed:@"uncheck.png"] forState:UIControlStateNormal];
self.chooseFlag=false;
}else{
[_chooseBtn setImage:[UIImage imageNamed:@"selected.png"] forState:UIControlStateNormal];
self.chooseFlag=true;
}
_chooseBlock(self.chooseFlag);
}
-(void)didUncheck{
[_chooseBtn setImage:[UIImage imageNamed:@"uncheck.png"] forState:UIControlStateNormal];
self.chooseFlag=false;
}
-(void)didSelected{
[_chooseBtn setImage:[UIImage imageNamed:@"selected.png"] forState:UIControlStateNormal];
self.chooseFlag=true;
}
@end
//ChoosePhotoGroupTableViewCell.h文件
//
// ChoosePhotoGroupTableViewCell.h
// CustomChoosePhotoDemo
// 相册簿组群单元格
// Created by Vie on 2017/2/15.
// Copyright © 2017年 Vie. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <AssetsLibrary/AssetsLibrary.h>
@interface ChoosePhotoGroupTableViewCell : UITableViewCell
@property (nonatomic ,strong) ALAssetsGroup * group;//相册簿组群
@end
//ChoosePhotoGroupTableViewCell.m文件
//
// ChoosePhotoGroupTableViewCell.m
// CustomChoosePhotoDemo
// 相册簿组群单元格
// Created by Vie on 2017/2/15.
// Copyright © 2017年 Vie. All rights reserved.
//
#import "ChoosePhotoGroupTableViewCell.h"
@interface ChoosePhotoGroupTableViewCell()
@property (nonatomic, strong) UIImageView *headImgView;//相册簿群组缩略图
@property (nonatomic, strong) UILabel *groupNameLable;//相册簿群组名称
@property (nonatomic, strong) UILabel *numberLable;//相册簿群组照片数量
@end
@implementation ChoosePhotoGroupTableViewCell
-(void)setGroup:(ALAssetsGroup *)group{
if (group) {
//获得当前的预览图
CGImageRef imageRef = [group posterImage];
UIImage * image = [UIImage imageWithCGImage:imageRef];
self.headImgView.image=image;
self.groupNameLable.text=NSLocalizedString([group valueForProperty:ALAssetsGroupPropertyName],@"");
self.numberLable.text=[NSString stringWithFormat:@"%@",@([group numberOfAssets])];
}
}
#pragma mark 懒加载
-(UIImageView *)headImgView{
if (!_headImgView) {
_headImgView=[[UIImageView alloc] init];
_headImgView.translatesAutoresizingMaskIntoConstraints=NO;
}
return _headImgView;
}
-(UILabel *)groupNameLable{
if (!_groupNameLable) {
_groupNameLable=[[UILabel alloc] init];
_groupNameLable.translatesAutoresizingMaskIntoConstraints=NO;
_groupNameLable.font=[UIFont systemFontOfSize:14];
}
return _groupNameLable;
}
-(UILabel *)numberLable{
if (!_numberLable) {
_numberLable=[[UILabel alloc] init];
_numberLable.translatesAutoresizingMaskIntoConstraints=NO;
_numberLable.font=[UIFont systemFontOfSize:12];
}
return _numberLable;
}
#pragma mark 视图处理
-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
self=[super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
[self loadView];
[self layoutVFL];
}
return self;
}
/*加载视图*/
-(void)loadView{
[self addSubview:self.headImgView];
[self addSubview:self.groupNameLable];
[self addSubview:self.numberLable];
}
/*VFL约束*/
-(void)layoutVFL{
//相册簿群组缩略图约束
/*Horizontal距离左边20*/
NSArray *headImgViewHorizotal=[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-20-[_headImgView]" options:0 metrics:nil views:@{@"_headImgView":_headImgView}];
[self addConstraints:headImgViewHorizotal];
/*Vertical距离顶部和底部各10个距离等于设置了高度*/
NSArray *headImgViewVertical=[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-10-[_headImgView]-10-|" options:0 metrics:nil views:@{@"_headImgView":_headImgView}];
[self addConstraints:headImgViewVertical];
/*设置headImgView宽等于高度*/
NSLayoutConstraint *headImgViewConstraint=[NSLayoutConstraint constraintWithItem:_headImgView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:_headImgView attribute:NSLayoutAttributeHeight multiplier:1 constant:0];
[self addConstraint:headImgViewConstraint];
//相册簿群组名称约束groupNameLable
/*_groupNameLable距离左边_headImgView20个单位,距离右边20个距离,等于设置了宽度*/
NSArray *groupNameLableHorizontal=[NSLayoutConstraint constraintsWithVisualFormat:@"H:[_headImgView]-20-[_groupNameLable]-20-|" options:0 metrics:nil views:@{@"_headImgView":_headImgView,@"_groupNameLable":_groupNameLable}];
[self addConstraints:groupNameLableHorizontal];
/*_groupNameLable距离顶部10个单位,高度为21*/
NSArray *groupNameLableVertical=[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-10-[_groupNameLable(21)]" options:0 metrics:nil views:@{@"_groupNameLable":_groupNameLable}];
[self addConstraints:groupNameLableVertical];
//相册簿群组照片数量约束
/*_numberLable左边距离_headImgView20个距离,距离右边20个距离,等于设置了宽度*/
NSArray *numberLableHorizontal=[NSLayoutConstraint constraintsWithVisualFormat:@"H:[_headImgView]-20-[_numberLable]-20-|" options:0 metrics:nil views:@{@"_headImgView":_headImgView,@"_numberLable":_numberLable}];
[self addConstraints:numberLableHorizontal];
/*_numberLable顶部距离_groupNameLable有0个距离,高度15*/
NSArray *numberLableVertical=[NSLayoutConstraint constraintsWithVisualFormat:@"V:[_groupNameLable]-0-[_numberLable(15)]" options:0 metrics:nil views:@{@"_groupNameLable":_groupNameLable,@"_numberLable":_numberLable}];
[self addConstraints:numberLableVertical];
}
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
@end
//ChoosePhotosBlock.h文件
//
// ChoosePhotosBlock.h
// CustomChoosePhotoDemo
// block定义
// Created by Vie on 2017/2/15.
// Copyright © 2017年 Vie. All rights reserved.
//
#ifndef ChoosePhotosBlock_h
#define ChoosePhotosBlock_h
typedef void(^ChoosePhotosFlag)(BOOL flag) ;//是否选中状态回调
typedef void(^ReturnImagesArray)(NSArray<UIImage *>* choosedImages);//选中照片返回
#endif /* ChoosePhotosBlock_h */
//BrowseChooseImgViewController.h文件
//
// BrowseChooseImgViewController.h
// CustomChoosePhotoDemo
// 浏览点击的图片
// Created by Vie on 2017/2/16.
// Copyright © 2017年 Vie. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface BrowseChooseImgViewController : UIViewController
@property (nonatomic, strong) UIImageView * tempImgView;//显示一个当前点击的图
@end
//BrowseChooseImgViewController.m文件
//
// BrowseChooseImgViewController.m
// CustomChoosePhotoDemo
// 浏览点击的图片
// Created by Vie on 2017/2/16.
// Copyright © 2017年 Vie. All rights reserved.
//
#import "BrowseChooseImgViewController.h"
@interface BrowseChooseImgViewController ()
@end
@implementation BrowseChooseImgViewController
-(instancetype)init{
self=[super init];
if (self) {
[self.view addSubview:self.tempImgView];
[self layoutVFL];
}
return self;
}
#pragma mark 懒加载
-(UIImageView *)tempImgView{
if (!_tempImgView) {
_tempImgView = [[UIImageView alloc] init];
_tempImgView.contentMode = UIViewContentModeScaleAspectFit;
_tempImgView.backgroundColor = [UIColor blackColor];
_tempImgView.translatesAutoresizingMaskIntoConstraints=NO;
}
return _tempImgView;
}
#pragma mark 界面处理
- (void)viewDidLoad {
[super viewDidLoad];
}
-(void)layoutVFL{
/*tableview水平方法距离两边各0距离等于设了x值和宽度*/
NSArray *tableViewHorizontal=[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[_tempImgView]-0-|" options:0 metrics:nil views:@{@"_tempImgView":_tempImgView}];
[self.view addConstraints:tableViewHorizontal];
/*tableview垂直方向距离两边各0距离等于设置了y值和高度*/
NSArray *tableViewVertical=[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[_tempImgView]-0-|" options:0 metrics:nil views:@{@"_tempImgView":_tempImgView}];
[self.view addConstraints:tableViewVertical];
}
@end
//ChoosePhotosCollectionViewController.h文件
//
// ChoosePhotosCollectionViewController.h
// CustomChoosePhotoDemo
// 照片展示器
// Created by Vie on 2017/2/15.
// Copyright © 2017年 Vie. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <AssetsLibrary/AssetsLibrary.h>
#import "ChoosePhotosBlock.h"
@interface ChoosePhotosCollectionViewController : UIViewController
@property (nonatomic, strong) NSMutableArray <ALAsset *> * photos;//存储ALAsset对象的数组
@property (nonatomic, copy) ReturnImagesArray returnImagesArray;//确认选中照片回调
@end
//ChoosePhotosCollectionViewController.m文件
//
// ChoosePhotosCollectionViewController.m
// CustomChoosePhotoDemo
// 照片展示器
// Created by Vie on 2017/2/15.
// Copyright © 2017年 Vie. All rights reserved.
//
#import "ChoosePhotosCollectionViewController.h"
#import "ChoosePhotosCollectionViewCell.h"
#import "BrowseChooseImgViewController.h"
@interface ChoosePhotosCollectionViewController ()<UICollectionViewDelegate,UICollectionViewDataSource>
@property (nonatomic, strong) UICollectionView *collectionView;
@property (nonatomic, assign) CGFloat cellLength; //标准大小
@property (nonatomic, strong) NSMutableArray<UIImage *> *choosedImages;//存放选中的图片对象
@property (nonatomic, strong) NSMutableArray<NSNumber *> *imagesFlag;//所以图片的标志位,记录是否被选中,避免在cell记录导致重用错乱问题
@property (nonatomic, strong) NSMutableArray<UIImage *> *allImages;//全部图片
@end
@implementation ChoosePhotosCollectionViewController
-(void)setPhotos:(NSMutableArray<ALAsset *> *)photos{
if (photos) {
_photos=photos;
[self loadImagesFlag:_photos.count];
[self loadAllImages];
[self.collectionView reloadData];
}
}
/*初始化标识为计数数组*/
-(void)loadImagesFlag:(NSInteger)count{
self.imagesFlag=[[NSMutableArray alloc] init];
for (int i=0; i<count; i++) {
[self.imagesFlag addObject:[NSNumber numberWithBool:false]];
}
}
/*加载所有的图片对象*/
- (void)loadAllImages
{
self.allImages=[[NSMutableArray alloc] init];
//进行资源处理
for (ALAsset * asset in self.photos)
{
//这里就不要用thumbnail属性了,太模糊
[self.allImages addObject:[UIImage imageWithCGImage:asset.aspectRatioThumbnail]];
}
}
#pragma mark 懒加载
-(UICollectionView *)collectionView{
if (!_collectionView) {
UICollectionViewFlowLayout *layout=[[UICollectionViewFlowLayout alloc] init];
_collectionView= [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout];
_collectionView.translatesAutoresizingMaskIntoConstraints=NO;
_collectionView.dataSource=self;
_collectionView.delegate=self;
//注册单元格使用的类型,必须先注册,否则会报异常
[_collectionView registerClass:[ChoosePhotosCollectionViewCell class] forCellWithReuseIdentifier:NSStringFromClass([ChoosePhotosCollectionViewCell class])];
//注册头
[_collectionView registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"header"];
//注册脚
[_collectionView registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:@"footer"];
}
return _collectionView;
}
-(NSMutableArray<UIImage *> *)choosedImages{
if (!_choosedImages) {
_choosedImages=[[NSMutableArray alloc] init];
}
return _choosedImages;
}
#pragma mark 视图处理
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.rightBarButtonItem=[[UIBarButtonItem alloc] initWithTitle:@"选择" style:UIBarButtonItemStylePlain target:self action:@selector(endChooseReturnArray)];
//初始化数据,适配横屏
CGFloat minLength = MIN(self.view.bounds.size.width, self.view.bounds.size.height);
self.cellLength = (minLength - 3) / 4.0f;
[self.view addSubview:self.collectionView];
[self layoutVFL];
}
/*使用VIF设置界面自动布局*/
-(void)layoutVFL{
/*tableview水平方法距离两边各0距离等于设了x值和宽度*/
NSArray *tableViewHorizontal=[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[_collectionView]-0-|" options:0 metrics:nil views:@{@"_collectionView":_collectionView}];
[self.view addConstraints:tableViewHorizontal];
/*tableview垂直方向距离两边各0距离等于设置了y值和高度*/
NSArray *tableViewVertical=[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[_collectionView]-0-|" options:0 metrics:nil views:@{@"_collectionView":_collectionView}];
[self.view addConstraints:tableViewVertical];
}
#pragma mark UICollectionViewDelegate
/*设置分区*/
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
return 1;
}
/*设置分区内单元格数*/
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return self.photos.count;
}
/*设置每个分区的边距*/
-(UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(nonnull UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{
return UIEdgeInsetsMake(0, 0, 0, 0);
}
/*item垂直间距*/
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section
{
return 1;
}
/*item水平间距*/
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section
{
return 1;
}
/*设置每个item大小*/
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(nonnull UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(nonnull NSIndexPath *)indexPath{
return CGSizeMake(self.cellLength, self.cellLength);
}
/*设置item*/
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(nonnull NSIndexPath *)indexPath{
//设置的单元格要与Identifier注册的一致
ChoosePhotosCollectionViewCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([ChoosePhotosCollectionViewCell class]) forIndexPath:indexPath];
//检查cell是否被选中
[self cellIsSelect:cell flag:self.imagesFlag[indexPath.row].boolValue];
cell.chooseBlock=^(BOOL flag){
//记录选中图片状态
[self.imagesFlag replaceObjectAtIndex:indexPath.row withObject:[NSNumber numberWithBool:flag]];
if (flag) {
NSLog(@"***********选中第%ld张图片",indexPath.row+1);
//添加选中图片
[self.choosedImages addObject:self.allImages[indexPath.item]];
}else{
NSLog(@"***********取消第%ld张图片",indexPath.row+1);
//移除选中图片
[self.choosedImages removeObject:self.allImages[indexPath.item]];
}
};
//这里尽量不用thumbnail属性,因为太模糊了,可以用aspectRatioThumbnail比例缩略图代替
cell.photoImageView.image = [UIImage imageWithCGImage:self.photos[indexPath.row].aspectRatioThumbnail];
return cell;
}
/*点击item*/
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
//获取当前的资源对象
ALAsset * asset = self.photos[indexPath.item];
//创建浏览控制器
BrowseChooseImgViewController * ctr = [[BrowseChooseImgViewController alloc] init];
UIImage *image=[UIImage imageWithCGImage:asset.defaultRepresentation.fullScreenImage];
//设置大图
ctr.tempImgView.image = [UIImage imageWithCGImage:asset.defaultRepresentation.fullScreenImage];
//弹出
[self.navigationController pushViewController:ctr animated:true];
}
#pragma mark 事件处理
/*检查item是否被点击过*/
-(void)cellIsSelect:(ChoosePhotosCollectionViewCell *)cell flag:(BOOL)flag{
if (flag) {
[cell didSelected];
}else{
[cell didUncheck];
}
}
/*选取照片完成*/
-(void)endChooseReturnArray{
_returnImagesArray(self.choosedImages);
//向前返回2个页面,返回到直接选择照片的页面
[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:([self.navigationController.viewControllers count]-3)] animated:YES];
}
@end
//ChoosePhotoGroupViewController.h文件
//
// ChoosePhotoGroupViewController.h
// CustomChoosePhotoDemo
// 相册薄组群展示器
// Created by Vie on 2017/2/15.
// Copyright © 2017年 Vie. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "ChoosePhotosBlock.h"
@interface ChoosePhotoGroupViewController : UIViewController
@property (nonatomic, copy) ReturnImagesArray returnImagesArray;//确认选中照片回调
@end
//ChoosePhotoGroupViewController.m文件
//
// ChoosePhotoGroupViewController.m
// CustomChoosePhotoDemo
// 相册薄组群展示器
// Created by Vie on 2017/2/15.
// Copyright © 2017年 Vie. All rights reserved.
//
#import "ChoosePhotoGroupViewController.h"
#import <AssetsLibrary/AssetsLibrary.h>
#import "ChoosePhotoGroupTableViewCell.h"
#import "ChoosePhotosCollectionViewController.h"
@interface ChoosePhotoGroupViewController ()<UITableViewDelegate,UITableViewDataSource>
@property (nonatomic, strong) ALAssetsLibrary *assetsLibrary;//访问控制的视频和照片的照片实例
@property (nonatomic, strong) NSMutableArray <ALAssetsGroup *> *photoAlbumGroups;//存放相册簿组群的数组对象
@property (nonatomic, strong) UITableView *tableView;//表格视图
@end
@implementation ChoosePhotoGroupViewController
#pragma mark 懒加载
-(ALAssetsLibrary *)assetsLibrary{
if (!_assetsLibrary) {
_assetsLibrary=[[ALAssetsLibrary alloc] init];
}
return _assetsLibrary;
}
-(NSMutableArray<ALAssetsGroup *>*)photoAlbumGroups{
if (!_photoAlbumGroups) {
_photoAlbumGroups=[[NSMutableArray alloc] init];
[self.assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
//如果返回的组群存在,分次返回,所以在这里收到数据时候重载画面
if (group) {
//对group进行过滤只要照片
[group setAssetsFilter:[ALAssetsFilter allPhotos]];
[_photoAlbumGroups addObject:group];
}
/*获得相册簿群组后重载数据*/
[self.tableView reloadData];
} failureBlock:^(NSError *error) {
NSLog(@"获得相册簿组群失败");
}];
}
return _photoAlbumGroups;
}
-(UITableView *)tableView{
if (!_tableView) {
_tableView=[[UITableView alloc] init];
_tableView.delegate=self;
_tableView.dataSource=self;
/*禁用autoresizing*/
_tableView.translatesAutoresizingMaskIntoConstraints=NO;
}
return _tableView;
}
#pragma mark 界面处理
- (void)viewDidLoad {
[super viewDidLoad];
/*要在加载到父视图上后设置VFL才有参照系*/
[self.view addSubview:self.tableView];
[self layoutVFL];
}
/*使用VIF设置界面自动布局*/
-(void)layoutVFL{
/*tableview水平方法距离两边各0距离等于设了x值和宽度*/
NSArray *tableViewHorizontal=[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[_tableView]-0-|" options:0 metrics:nil views:@{@"_tableView":_tableView}];
[self.view addConstraints:tableViewHorizontal];
/*tableview垂直方向距离两边各0距离等于设置了y值和高度*/
NSArray *tableViewVertical=[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[_tableView]-0-|" options:0 metrics:nil views:@{@"_tableView":_tableView}];
[self.view addConstraints:tableViewVertical];
}
#pragma mark UITableViewDelegate
/*设置每个分区多少行*/
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return self.photoAlbumGroups.count;
}
/*设置分区*/
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
/*单元格选中事件*/
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
ChoosePhotosCollectionViewController *collectionCtr=[[ChoosePhotosCollectionViewController alloc] init];
collectionCtr.returnImagesArray=^(NSArray<UIImage *>* choosedImages){
NSLog(@"*******共选中%ld张图片",choosedImages.count);
_returnImagesArray(choosedImages);
};
[self.navigationController pushViewController:collectionCtr animated:YES];
NSMutableArray *photos=[[NSMutableArray alloc] init];
//获取group模型
ALAssetsGroup *group = self.photoAlbumGroups[indexPath.row];
dispatch_async(dispatch_get_main_queue(), ^{
//开始读取
[group enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
//如果不为空或者媒体为图片
if (result != nil && [[result valueForProperty:ALAssetPropertyType] isEqualToString:ALAssetTypePhoto])
{
//添加数据
[photos addObject:result];
//数目达标后统一进行赋值
if (index == group.numberOfAssets - 1)
{
collectionCtr.photos=photos;
}
}
}];
});
}
/*设置单元格*/
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
ChoosePhotoGroupTableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:[NSString stringWithFormat:@"%ld",indexPath.row]];
if (!cell) {
cell=[[ChoosePhotoGroupTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:[NSString stringWithFormat:@"%ld",indexPath.row]];
}
//获得当前的数据
ALAssetsGroup * group = self.photoAlbumGroups[indexPath.row];
cell.group=group;
return cell;
}
/*设置单元格高度*/
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 80;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
//图片资源
//使用
#import "ChoosePhotoGroupViewController.h"
#import "ChoosePhotosBlock.h"
/*加载照片群组控制器*/
ChoosePhotoGroupViewController *photoCtr=[[ChoosePhotoGroupViewController alloc] init];
photoCtr.returnImagesArray=^(NSArray<UIImage *>* choosedImages){
NSLog(@"***********一共选中%ld张图片",choosedImages.count);
};
[self.navigationController pushViewController:photoCtr animated:YES];
//效果展示