
如上圖所示,完成如上功能。下面主要介紹下功能的實(shí)現(xiàn):
一: 編輯頁面
1: UI布局
布局較為簡單,就不詳細(xì)闡述了,只說下注意點(diǎn)。因?yàn)閳D片需要滑動,所以圖片是加在UIScrollView上的。例如九宮格的布局,scrollView寬高是屏幕的寬度,例如在iphone7中,寬高都是375,那么Imageview的寬高是否也和scrollView一樣等于375呢,看起來是相等的,實(shí)則不然,因?yàn)镮mageview是需要滑動的,如果相等,scrollView的contentSize如果大于Imageview的寬高,scrollView滑動過后,就會出現(xiàn)空白的區(qū)域。所以Imageview的寬高應(yīng)該等于scrollView的contentSize的大小,至于contentSize的大小怎么計(jì)算,在下面的操作邏輯中會寫到!
2: 操作邏輯
(1 ) 用戶可向上下左右四個(gè)方向滑動圖片,來調(diào)整圖片位置
注意:圖片上下左右需要滑動多少,由圖片的原始寬度和原始高度決定,根據(jù)圖片的原始寬高算出scrollView的contentSize,contentSize就是圖片能夠滑動的范圍,也是ImageView.frame 的 width 和height 。
計(jì)算ImageView的寬度 (img_Width) :
原始圖片的高度除以scrollView的Frame高度,得到圖片的高度比例
原始圖片的寬度除以圖片的高度比例,得到ImageView需要顯示的圖片寬度
計(jì)算ImageView的高度(img_Height) :
原始圖片的寬度除以scrollView的Frame寬度,得到圖片的寬度比例
原始圖片的高度除以圖片的寬度比例,得到ImageView需要顯示的圖片高度
圖片滑動范圍: self.scrollView.contentSize = CGSizeMake(img_Width, img_Height);
代碼如下:
//計(jì)算圖片滑動范圍
-(void)setScrollviewContentOffset{
/*
橫向的寬度等于:
原始圖片的高度除以ImageView的Frame高度,得到圖片的高度比例
原始圖片的寬度除以圖片的高度比例,得到ImageView需要顯示的圖片寬度
*/
//_img_Width: imageview的寬度
_img_Width = self.imageSize.width / (self.imageSize.height / self.scrollView.frame.size.height);
/*
縱向的高度等于:
原始圖片的寬度除以ImageView的Frame寬度,得到圖片的寬度比例
原始圖片的高度除以圖片的寬度比例,得到ImageView需要顯示的圖片高度
*/
//_img_Height: imageview的高度
_img_Height = self.imageSize.height / (self.imageSize.width /self.scrollView.frame.size.width);
if (_img_Width < self.frame.size.width) {
_img_Width = self.frame.size.width;
}
if (_img_Height < self.frame.size.height) {
_img_Height = self.frame.size.height;
}
NSLog(@"_img_Width ==%ld, _img_Height == %ld",_img_Width,_img_Height);
NSLog(@"imageSize.Width ==%f, imageSize.height == %f",self.imageSize.width,self.imageSize.height);
//設(shè)置圖片滑動范圍
self.scrollView.contentSize = CGSizeMake(_img_Width, _img_Height);
}
(2) 用戶可通過雙指縮放來調(diào)整圖片大小
需求中放大縮小的比例是2和1,也就是原始圖片不能再縮小,最小比例是1.0
功能實(shí)現(xiàn):這里直接采用 scrollView 的 maximumZoomScale 和 minimumZoomScale 屬性,設(shè)置縮放倍數(shù)。
代碼如下:
//設(shè)置縮放倍數(shù)
_scrollView.maximumZoomScale = 2.0;
_scrollView.minimumZoomScale = 1.0;
_scrollView.delegate = self;
#pragma mark ============ UIScrollViewDelegate ============
//設(shè)置需要縮放的view
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return self.imageView;
}
//在這個(gè)代理方法里面設(shè)置滾動范圍、調(diào)整放大圖片的位置,固定imageView始終在整個(gè)content的居中位置:(如果不設(shè)置,放大后圖片按照原來比例frame的X,Y值也會跟隨比例變化,圖片就跑偏了)
- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
CGRect frame = self.imageView.frame;
frame.origin.y = (self.scrollView.frame.size.height - self.imageView.frame.size.height) > 0 ? (self.scrollView.frame.size.height - self.imageView.frame.size.height) * 0.5 : 0;
frame.origin.x = (self.scrollView.frame.size.width - self.imageView.frame.size.width) > 0 ? (self.scrollView.frame.size.width - self.imageView.frame.size.width) * 0.5 : 0;
self.imageView.frame = frame;
self.scrollView.contentSize = CGSizeMake(self.imageView.frame.size.width, self.imageView.frame.size.height);
}
(3) 完成圖片操作后,點(diǎn)擊下一步,截取圖片
剛開始做這個(gè)功能,截圖一直比較模糊,是因?yàn)槭褂昧耍篣IGraphicsBeginImageContext(size),
UIGraphicsBeginImageContext(size) 等價(jià)于 UIGraphicsBeginImageContextWithOptions(size,NO,1.0)
圖片再切的時(shí)候它的scale,即縮放比率這里默認(rèn)不縮放處理,那么剪切出來的圖片用UI開發(fā)那邊的說法即為1倍圖,而我們iOS的手機(jī)現(xiàn)在市面上的一般都是retain屏幕,像素用一 倍圖處理處理的圖片當(dāng)然顯示出來會比較模糊。那么。我們就可以將需要切的圖片的scale設(shè)置為 [UIScreen mainScreen].scale
使用 UIGraphicsBeginImageContextWithOptions(size, YES, [UIScreen mainScreen].scale)
代碼如下:
// 使用上下文截圖,并使用指定的區(qū)域裁剪
- (UIImage *)screenShot
{
// 將要被截圖的view
CGSize size = self.sudokuView.frame.size;
// 開啟上下文,使用參數(shù)之后,截出來的是原圖(YES 0.0 質(zhì)量高)
UIGraphicsBeginImageContextWithOptions(size, YES, [UIScreen mainScreen].scale);
// 裁剪的矩形范圍
CGRect rect = CGRectMake(0, 0, size.width, size.height);
//注:iOS7以后renderInContext:由drawViewHierarchyInRect:afterScreenUpdates:替代
[self.sudokuView drawViewHierarchyInRect:rect afterScreenUpdates:NO];
// 從上下文中,取出UIImage
UIImage *snapshot = UIGraphicsGetImageFromCurrentImageContext();
//結(jié)束上下文(移除棧頂上下文)
UIGraphicsEndImageContext();
return snapshot;
}
二: 保存頁面
1: UI布局
一張圖片要切割成多張,切割后的每一張大小相等,每一張都能點(diǎn)擊保存,所以布局用 UICollectionView
切割的劃分白線顯示,設(shè)置UICollectionViewFlowLayout 的.minimumInteritemSpacing 和 minimumLineSpacing即可
//相鄰兩個(gè)cell的最小間距
layout.minimumInteritemSpacing = iPad ? 2.0 : 1.0;
//兩行之間的間距
layout.minimumLineSpacing = iPad ? 2.0 : 1.0;
設(shè)置背景色: self.collectionView.backgroundColor = [UIColor whiteColor];
計(jì)算cell大小,要減去分割線的間距
//定義每一個(gè)cell的大小
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
return CGSizeMake((self.imageView.frame.size.width - (iPad ? 4:2)) / 3, (self.imageView.frame.size.width - (iPad ? 4:2)) / 3);
}
2: 圖片切割功能
圖片切割,要根據(jù)三、六、九、十二宮格的類型進(jìn)行切割,例如十二宮格,是3行4列,切割后的圖片是12張;三宮格是1行1列,切割后的圖片是3張。
切割完成后,將圖片保存在數(shù)組中,圖片數(shù)組就是UICollectionView的數(shù)據(jù)源。
代碼如下:
//對大圖進(jìn)行切割,切割完成得到圖片數(shù)組
- (void)captureImage {
//切割成正方形,寬高一樣
CGFloat imgView_width = (self.imageView.frame.size.width / 3);
CGFloat imgView_height = (self.imageView.frame.size.width / 3);
if (self.imgCount == 3) {
// 把圖片切成三宮格,就是豎著切3段
for (int i = 0; i < 3; i++) {
UIImage *theImage = [self captureView:self.imageView frame:CGRectMake(i*imgView_width, 0, imgView_width,imgView_height)];
[self.imageArr addObject:theImage];
}
}else if (self.imgCount == 6){
// 把圖片切成六宮格,就是橫著切2段,豎著切3段,2個(gè)for循環(huán),對已知image進(jìn)行切割
for (int i = 0; i < 2; i++) {
for (int j = 0; j<3; j++) {
UIImage *theImage = [self captureView:self.imageView frame:CGRectMake(j*imgView_width,i*imgView_height, imgView_width, imgView_height)];
[self.imageArr addObject:theImage];
}
}
}else if (self.imgCount == 9){
// 把圖片切成九宮格,就是橫著切3段,豎著切3段,2個(gè)for循環(huán),對已知image進(jìn)行切割
for (int i = 0; i < 3; i++) {
for (int j = 0; j<3; j++) {
UIImage *theImage = [self captureView:self.imageView frame:CGRectMake(j*imgView_width, i*imgView_height, imgView_width, imgView_height)];
[self.imageArr addObject:theImage];
}
}
}else if (self.imgCount == 12){
// 把圖片切成十二宮格,就是橫著切4段,豎著切3段,2個(gè)for循環(huán),對已知image進(jìn)行切割
for (int i = 0; i < 4; i++) {
for (int j = 0; j<3; j++) {
NSLog(@"i===== %d j===== %d",i,j);
UIImage *theImage = [self captureView:self.imageView frame:CGRectMake(j*imgView_width, i*imgView_height, imgView_width, imgView_height)];
[self.imageArr addObject:theImage];
}
}
}
}
編輯頁講到了圖片裁剪適應(yīng)屏幕比例([UIScreen mainScreen].scale)的問題,這里也要考慮這個(gè)問題,那么我們的剪切位置frame.orgain.x與y都應(yīng)該乘以scale的倍數(shù)。圖片的剪切frame.size.width與height也應(yīng)該乘以scale,而且在繪制好之后的壓縮處理的時(shí)候也要除以[UIScreen mainScreen].scale,以達(dá)到選擇區(qū)域的寬度和高度的圖片范圍)
代碼如下:
//切割圖片
- (UIImage *)captureView:(UIView *)theView frame:(CGRect)fra {
//屏幕比例
NSInteger multiple = [UIScreen mainScreen].scale;
// 開啟位圖上下文
UIGraphicsBeginImageContextWithOptions(theView.frame.size, NO, multiple);
// 裁剪區(qū)域
CGRect rect = CGRectMake(fra.origin.x * multiple, fra.origin.y * multiple, fra.size.width *multiple, fra.size.height * multiple);
// 進(jìn)行渲染
CGContextRef ctx = UIGraphicsGetCurrentContext();
[self.imageView.layer renderInContext:ctx];
// 生成圖片
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
//關(guān)閉上下文
UIGraphicsEndImageContext();
newImage = [UIImage imageWithCGImage:CGImageCreateWithImageInRect(self.imageView.image.CGImage, rect)];
newImage = [self harfWithImage:newImage toSize:CGSizeMake(newImage.size.width /multiple, newImage.size.height / multiple)] ;
return newImage;
}
然后對照片進(jìn)行“縮”處理,這個(gè)時(shí)候,獲取的圖片大小是我們想要的2倍大小。然后就需要進(jìn)一步的“縮”1/2處理。
再一次的縮處理,我們還是要縮放選擇2.0.即目前的倍率(不然選擇1倍或者不縮放處理,結(jié)果一樣是模糊的圖片)。然后將我們的圖片繪制到一個(gè)寬度和高度都是目前一般的image就可以了。
代碼如下(將傳入的size大小直接定為傳入image的寬和高的一半就好了):
-(UIImage *)harfWithImage:(UIImage *)image toSize:(CGSize)size{
UIGraphicsBeginImageContextWithOptions(size, YES, [UIScreen mainScreen].scale);
[image drawInRect:CGRectMake(0, 0, size.width, size.height)];
UIImage *resultImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return resultImg;
}
3: 圖片保存功能
一次性保存多張圖片,有時(shí)候會出現(xiàn)保存不全(例如保存12張圖,實(shí)際只保存了6張)或保存的圖片順序錯亂的問題,使用如下方法解決:
//保存全部圖片
-(void)saveAllBtn:(UIButton *)sender{
for (UIImage *image in self.sudokuSaveView.imageArr){
[self loadImageFinished:image];
}
}
// 存儲圖片到相冊
- (void)loadImageFinished:(UIImage *)image{
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
//寫入圖片到相冊
[PHAssetChangeRequest creationRequestForAssetFromImage:image];
} completionHandler:^(BOOL success, NSError * _Nullable error) {
NSLog(@"success = %d, error = %@", success, error);
if(success){
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"保存成功,可以在這里做保存完成的操作");
});
} else {
NSLog(@"保存失敗");
}
}];
}
結(jié)語:
以上就是九宮格的核心功能實(shí)現(xiàn)
如有問題請下方留言指正
如有幫助請??支持一下 ??