今天看书中介绍了从图片库中调用图片的例子,一时性起打算做一个简单的图片浏览器。

功能很简单,从图片库中载入图片,然后放到view下,并支持放大,缩小,平移。

 

由于对控件库不了解,一开始的方案是这样的:

前面的框架都一样:

用toolbar做按钮条,里面有个按键,触发从按键。

按键action调用图片库,之后图片库发消息到delegate(我这里协议挂在了主UIViewController上面,后面其他的delegate也一样)。

如果正确得到了图片 UIImagePickerControllerDelegate的imagePickerController:didFinishPickingMediaWithInfo:的第二个参数可以得到一个包含选定图片的Dictionary。

 

OK,演出开始了。后面的方案是这样。

1.  搞了个UIImageView作为图片载体,扑满整个屏幕,然后将Mode设置为Center,图片设置后可以居中显示。

注意,这个函数由于用到了UIGraphicsXXXX函数,要求只能再主线程中调用)

    

// 
   
 
   // 
     UIImage_Extra.h
 
   // 
     Camera
 
   // 
   
 
   // 
     Created by 李 择一 on 11-4-22.
 
   // 
     Copyright 2011 __MyCompanyName__. All rights reserved.
 
   //
 
   
#import  
   < 
   Foundation 
   / 
   Foundation.h 
   > 
   


@interface UIImage (Extra)

 
   - 
    (UIImage 
   * 
   ) imageByScalingAndCroppingForSize: (CGSize)targetSize;

@end

 
   // 
   
 
   // 
     UIImage_Extra.m
 
   // 
     Camera
 
   // 
   
 
   // 
     Created by 李 择一 on 11-4-22.
 
   // 
     Copyright 2011 __MyCompanyName__. All rights reserved.
 
   //
 
   
#import  
   " 
   UIImage_Extra.h 
   " 
   


@implementation UIImage (Extra)

 
   - 
    (UIImage 
   * 
   )imageByScalingAndCroppingForSize: (CGSize)targetSize
{
    UIImage  
   * 
   sourceImage  
   = 
    self;
    UIImage  
   * 
   newImage  
   = 
    nil;        
    CGSize imageSize  
   = 
    sourceImage.size;
    CGFloat width  
   = 
    imageSize.width;
    CGFloat height  
   = 
    imageSize.height;
    CGFloat targetWidth  
   = 
    targetSize.width;
    CGFloat targetHeight  
   = 
    targetSize.height;
    CGFloat scaleFactor  
   = 
     
   0.0 
   ;
    CGFloat scaledWidth  
   = 
    targetWidth;
    CGFloat scaledHeight  
   = 
    targetHeight;
    CGPoint thumbnailPoint  
   = 
    CGPointMake( 
   0.0 
   , 
   0.0 
   );
    
     
   if 
    (CGSizeEqualToSize(imageSize, targetSize)  
   == 
    NO) 
    {
        CGFloat widthFactor  
   = 
    targetWidth  
   / 
    width;
        CGFloat heightFactor  
   = 
    targetHeight  
   / 
    height;
        
         
   if 
    (widthFactor  
   > 
    heightFactor) 
            scaleFactor  
   = 
    widthFactor;  
   // 
    scale to fit height 
   
 
            
   else 
   
            scaleFactor  
   = 
    heightFactor;  
   // 
    scale to fit width 
   
 
           scaledWidth   
   = 
    width  
   * 
    scaleFactor;
        scaledHeight  
   = 
    height  
   * 
    scaleFactor;
        
         
   // 
    center the image 
   
 
            
   if 
    (widthFactor  
   > 
    heightFactor)
        {
            thumbnailPoint.y  
   = 
    (targetHeight  
   - 
    scaledHeight)  
   * 
     
   0.5 
   ; 
        }
         
   else 
    
             
   if 
    (widthFactor  
   < 
    heightFactor)
            {
                thumbnailPoint.x  
   = 
    (targetWidth  
   - 
    scaledWidth)  
   * 
     
   0.5 
   ;
            }
    }       
    
    UIGraphicsBeginImageContext(targetSize);  
   // 
    this will crop 
   
 
       
    CGRect thumbnailRect  
   = 
    CGRectZero;
    thumbnailRect.origin  
   = 
    thumbnailPoint;
    thumbnailRect.size.width   
   = 
    scaledWidth;
    thumbnailRect.size.height  
   = 
    scaledHeight;
    
    [sourceImage drawInRect:thumbnailRect];
    
    newImage  
   = 
    UIGraphicsGetImageFromCurrentImageContext();
     
   if 
   (newImage  
   == 
    nil) 
        NSLog( 
   @" 
   could not scale image 
   " 
   );
    
     
   // 
   pop the context to get back to the default 
   
 
       UIGraphicsEndImageContext();
     
   return 
    newImage;
}


@end


   再往下做平移的时候出现了问题,虽然可以重载touchesBegan和touchesMove移动UIImageView,可是就失去了iOS特效了,并且当图片移到屏幕边缘再进行放大,缩小,UIImageView就不一定飞到那里去了,还需要继续增加判断条件。所以此方法不可取。

 ------------------------------2011-04-25 更新------------------------------

现在发现了新的api可以解决拉伸的问题。在UIImage 中有个函数叫stretchableImageWithLeftCapWidth:topCapHeight:的,可以返回一个新的UIImage,这个UIImage是可以拉伸的。具体用法请参阅apple的Sample Code.

-------------------------------------------------------------------------------

 

2.  到网上查了可以利用UIScrollView做平移处理,在其中嵌入一个UIImageView,手势用来管理图片放大缩小,这样就可以一边吃火锅,一边唱歌了。

   这个方案要考虑的事情有几个,一个是UIScrollView的contentSize的要考虑UIImageView的大小,在放大或者缩小图片以后要调整contentSize的大小。

    还有一个就是在缩放的时候要考虑到,缩放的中心位置问题。比如,现在图片上有个人脸,然后手势是以人脸鼻子为中心放大的,在放大结束后,可能手势的中心就跑偏了,因此要在缩放时修改UIImageView的center,这个计算还是挺复杂的。

 

3.  为了解决这个问题继续搜索文档,发现在UIScrollView里面有zoom这个东东,可以通过delegate的viewForZoomingInScrollView:方法指定UIScrollView中的某个view放大,还可以设定放大的最大倍数和最小倍数。这个nb了,一个UIScrollView类全都搞定了平移缩放。酷啊!!

   但是这个也有要注意的问题。由于UIScrollView里面可能要主动调用他所包含subView的属性,因此在缩放过程中,不要修改subview的属性。

        另外,缩放平移全都人家搞了,在给UIImageView中换图片之前一定要注意先将UIScrollView的zoomScale,contentSize,contentOffset全都设置成初始值。设想这样一个情况,在UIScrollView里面将图片放大,contentSize,contentOffset,zoomScale全变了,而你这时候找了个特小的图片放进来,如果不设置那三个属性的初值,或者只设置了一个,这样必然会造成混乱。

 

三种方法里还是第三种最简单啊。

总结:我忘了那本书里面说过,Apple公司为在Mac上面的工作做了20年,如果你需要用很多代码实现一个很简单的功能,肯定是方法不对。

今天的探索印证了这句话。还有,现在市面上所有的iOS开发书籍里都没有原理层面的讲解开发的。所以搜索引擎,加上浏览各种网站论坛成为解决问题的快捷途径。