类似微信头像选择裁剪功能 ,设置UIImagePickerController的allowsEditing属性为YES即可实现,但如何自己实现此功能呢?如何实现类似系统联系人圆形头像裁剪选取呢?
如图:
图片要支持缩放和拖拽,首先想到scrollView,具体实现方法如下:
//CropImageController.h
@protocol CropImageDelegate <NSObject>
- (void)cropImageDidFinishedWithImage:(UIImage *)image;
@end
@interface CropImageController : UIViewController
@property (nonatomic, weak) id <CropImageDelegate> delegate;
//圆形裁剪,默认NO;
@property (nonatomic, assign) BOOL ovalClip;
- (instancetype)initWithImage:(UIImage *)originalImage delegate:(id)delegate;
@end
在viewDidLoad初始化scrollView,设置frame为裁剪框大小,若需要超出边界线内容仍然可以显示,设置其layer属性masksToBounds即可
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor blackColor];
self.automaticallyAdjustsScrollViewInsets = NO;
CGFloat height = (ScreenHeight - ScreenWidth)/2.0;
_scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, height ,ScreenWidth,ScreenWidth)];
_scrollView.bouncesZoom = YES;
_scrollView.minimumZoomScale = 1;
_scrollView.maximumZoomScale = 3;
_scrollView.zoomScale = 1;
_scrollView.delegate = self;
_scrollView.layer.masksToBounds = NO;
_scrollView.showsHorizontalScrollIndicator = NO;
_scrollView.showsVerticalScrollIndicator = NO;
_scrollView.layer.borderWidth = 1.5;
_scrollView.layer.borderColor = [UIColor whiteColor].CGColor;
if (_ovalClip) {
_scrollView.layer.cornerRadius = ScreenWidth/2.0;
}
self.view.layer.masksToBounds = YES;
if (_originalImage) {
_imageView = [[UIImageView alloc] initWithImage:_originalImage];
CGFloat img_width = ScreenWidth;
CGFloat img_height = _originalImage.size.height * (img_width/_originalImage.size.width);
CGFloat img_y= (img_height - self.view.bounds.size.width)/2.0;
_imageView.frame = CGRectMake(0,0, img_width, img_height);
_imageView.userInteractionEnabled = YES;
[_scrollView addSubview:_imageView];
_scrollView.contentSize = CGSizeMake(img_width, img_height);
_scrollView.contentOffset = CGPointMake(0, img_y);
[self.view addSubview:_scrollView];
}
[self userInterface];
}
设置self.view中间镂空效果:
- (void)userInterface {
CGRect cropframe = _scrollView.frame;
UIBezierPath * path = [UIBezierPath bezierPathWithRoundedRect:self.view.bounds cornerRadius:0];
UIBezierPath * cropPath = [UIBezierPath bezierPathWithRoundedRect:cropframe cornerRadius:0];
if (_ovalClip) {
cropPath = [UIBezierPath bezierPathWithOvalInRect:cropframe];
}
[path appendPath:cropPath];
CAShapeLayer * layer = [[CAShapeLayer alloc] init];
layer.fillColor = [UIColor colorWithRed:.0 green:.0 blue:.0 alpha:0.5].CGColor;
//填充规则
layer.fillRule=kCAFillRuleEvenOdd;
layer.path = path.CGPath;
[self.view.layer addSublayer:layer];
}
UIScrollViewDelegate,缩放和滑动过程中调整内容视图大小:
#pragma mark -- UIScrollViewDelegate
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return self.imageView;
}
- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
//调整位置
[self centerContent];
}
- (void)centerContent {
CGRect imageViewFrame = _imageView.frame;
CGRect scrollBounds = CGRectMake(0, 0, ScreenWidth, ScreenWidth);
if (imageViewFrame.size.height > scrollBounds.size.height) {
imageViewFrame.origin.y = 0.0f;
}else {
imageViewFrame.origin.y = (scrollBounds.size.height - imageViewFrame.size.height) / 2.0;
}
if (imageViewFrame.size.width < scrollBounds.size.width) {
imageViewFrame.origin.x = (scrollBounds.size.width - imageViewFrame.size.width) /2.0;
}else {
imageViewFrame.origin.x = 0.0f;
}
_imageView.frame = imageViewFrame;
}
调整位置确定选取图片时候,可根据当前ScrollView的contentOffset和缩放倍数确定具体裁剪位置:
- (UIImage *)cropImage {
CGPoint offset = _scrollView.contentOffset;
//图片缩放比例
CGFloat zoom = _imageView.frame.size.width/_originalImage.size.width;
//视网膜屏设备像素相关
zoom = zoom / [UIScreen mainScreen].scale;
CGFloat width = _scrollView.frame.size.width;
CGFloat height = _scrollView.frame.size.height;
if (_imageView.frame.size.height < _scrollView.frame.size.height) {//太胖了,取中间部分
offset = CGPointMake(offset.x + (width - _imageView.frame.size.height)/2.0, 0);
width = height = _imageView.frame.size.height;
}
CGRect rec = CGRectMake(offset.x/zoom, offset.y/zoom,width/zoom,height/zoom);
CGImageRef imageRef =CGImageCreateWithImageInRect([_originalImage CGImage],rec);
UIImage * image = [[UIImage alloc]initWithCGImage:imageRef];
CGImageRelease(imageRef);
if (_ovalClip) {
image = [image ovalClip];
}
return image;
}
UIImage分类(图片指定尺寸缩放和圆形裁剪):
//UIImage+Crop.m
- (UIImage *)resizeImageWithSize:(CGSize)newSize {
CGFloat newWidth = newSize.width;
CGFloat newHeight = newSize.height;
float width = self.size.width;
float height = self.size.height;
if (width != newWidth || height != newHeight) {
UIGraphicsBeginImageContextWithOptions(CGSizeMake(newWidth, newHeight), YES, [UIScreen mainScreen].scale);
[self drawInRect:CGRectMake(0, 0, newWidth, newHeight)];
UIImage *resized = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return resized;
}
return self;
}
- (UIImage *)ovalClip {
CGSize size = self.size;
UIGraphicsBeginImageContextWithOptions(size, NO, [UIScreen mainScreen].scale);
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, self.size.width, self.size.height)];
[path addClip];
[self drawAtPoint:CGPointZero];
UIImage * image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}