iOS 九宮格切圖功能實(shí)現(xiàn)

image.png

如上圖所示,完成如上功能。下面主要介紹下功能的實(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)

如有問題請下方留言指正

如有幫助請??支持一下 ??

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、項(xiàng)目管理的基本概念 項(xiàng)目是為創(chuàng)造獨(dú)特的產(chǎn)品、服務(wù)或成果而進(jìn)行的臨時(shí)性工作。故項(xiàng)目具有臨時(shí)性、獨(dú)特性、漸進(jìn)明細(xì)性...
    小小明PM閱讀 232評論 0 3
  • R語言的強(qiáng)大無需多言,它是世界上最廣泛使用的統(tǒng)計(jì)編程語言,最初是由Ross Ihaka和Robert Gentle...
    暴走小天使閱讀 505評論 0 1
  • 讀完本文約需50分鐘 書友你好,歡迎來到非凡精讀館!我是劉蔚濤。 今天給大家介紹一本比較有意思的書,這本書的名字叫...
    綠葉zll閱讀 631評論 0 0
  • Nat Biomed Eng | PD-L1和CD3ε雙特異性抗體重新活化腫瘤特異性CD8 T細(xì)胞 原創(chuàng)huaci...
    圖靈基因閱讀 774評論 0 0
  • 辟谷減肥與養(yǎng)生 辟谷亦稱卻谷、斷食、修糧,即不食五谷之意,是我國傳統(tǒng)道家養(yǎng)生中一種高層次修煉方法,對于養(yǎng)生祛病,提...
    半辟谷減肥訓(xùn)練營閱讀 398評論 0 0

友情鏈接更多精彩內(nèi)容