iOS小技能: 图片的平铺和拉伸、图片的加载方式、内容模式

4,256 阅读4分钟

这是我参与11月更文挑战的第28天,活动详情查看:2021最后一次更文挑战

引言

例子:按照比例显示图片全部内容,并自动适应高度

I 图片的平铺和拉伸


#import "UIImage+ResizableImage.h"

@implementation UIImage (ResizableImage)


+ (UIImage*)resizableImageWithName:(NSString *)name {
    NSLog(@"%s--%@",__func__,name);
    UIImage *image = [UIImage imageNamed:name];
    //裁剪图片方式一:
    //Creates and returns a new image object with the specified cap values.
    /*right cap is calculated as width - leftCapWidth - 1
     bottom cap is calculated as height - topCapWidth - 1
     */
    return [image stretchableImageWithLeftCapWidth:image.size.width*0.5 topCapHeight:image.size.height*0.5];
    //方式二:
    //    CGFloat top = image.size.width*0.5f-1;
    //    CGFloat left = image.size.height*0.5f-1;
    //    UIEdgeInsets insets = UIEdgeInsetsMake(top, left, top, left);
    //    UIImage *capImage = [image resizableImageWithCapInsets:insets resizingMode:UIImageResizingModeTile];
    //
}




/**
 CGFloat top = 0; // 顶端盖高度
 CGFloat bottom = 0 ; // 底端盖高度
 CGFloat left = 0; // 左端盖宽度
 CGFloat right = 0; // 右端盖宽度
 
 //    UIImageResizingModeStretch:拉伸模式,通过拉伸UIEdgeInsets指定的矩形区域来填充图片
 //    UIImageResizingModeTile:平铺模式,通过重复显示UIEdgeInsets指定的矩形区域来填充图片
 

 @param img <#img description#>
 @param top <#top description#>
 @param left <#left description#>
 @param bottom <#bottom description#>
 @param right <#right description#>
 @return <#return value description#>
 */
- (UIImage *) resizeImage:(UIImage *) img WithTop:(CGFloat) top WithLeft:(CGFloat) left WithBottom:(CGFloat) bottom WithRight:(CGFloat) right
{
    UIImage * resizeImg = [img resizableImageWithCapInsets:UIEdgeInsetsMake(self.size.height * top, self.size.width * left, self.size.height * bottom, self.size.width * right) resizingMode:UIImageResizingModeStretch];
    
    return resizeImg;
}



//返回一个可拉伸的图片
- (UIImage *)resizeWithImageName:(NSString *)name
{
    UIImage *normal = [UIImage imageNamed:name];
    
    //    CGFloat w = normal.size.width * 0.5f ;
    //    CGFloat h = normal.size.height *0.5f ;
    
    CGFloat w = normal.size.width*0.8;
    CGFloat h = normal.size.height*0.8;
    //传入上下左右不需要拉升的编剧,只拉伸中间部分
    return [normal resizableImageWithCapInsets:UIEdgeInsetsMake(h, w, h, w)];
    
    //    [normal resizableImageWithCapInsets:UIEdgeInsetsMake(<#CGFloat top#>, <#CGFloat left#>, <#CGFloat bottom#>, <#CGFloat right#>)]
    
    // 1 = width - leftCapWidth  - right
    // 1 = height - topCapHeight  - bottom
    
    //传入上下左右不需要拉升的编剧,只拉伸中间部分,并且传入模式(平铺/拉伸)
    //    [normal :<#(UIEdgeInsets)#> resizingMode:<#(UIImageResizingMode)#>]
    
    //只用传入左边和顶部不需要拉伸的位置,系统会算出右边和底部不需要拉升的位置。并且中间有1X1的点用于拉伸或者平铺
    // 1 = width - leftCapWidth  - right
    // 1 = height - topCapHeight  - bottom
    //    return [normal stretchableImageWithLeftCapWidth:w topCapHeight:h];
}




@end

II 图片的加载方式

优先选择3x图像,而不是2x图像时使用initWithContentsOfFile

 NSString *path = [[NSBundle mainBundle] pathForResource:@"smallcat" ofType:@"png"];
 UIImage *image = [[UIImage alloc]initWithContentsOfFile:path];
 // 在ipone5 s、iphone6和iphone6 plus都是优先加载@3x的图片,如果没有@3x的图片,就优先加载@2x的图片


  • 优先加载@2x的图片
  • [UIImage imageNamed:@"smallcat"]

iphone5s和iphone6优先加载@2x的图片,iphone6 plus是加载@3x的图片。

加载图片注意点:如果图片比较小,并且使用非常频繁,可以使用imageName:(eg icon),如果图片比较大,并且使用比较少,可以使用imageWithContentsOfFile:(eg 引导页 相册)。 imageName:

  • 1、当对象销毁的时候,图片占用的内存不会随着一起销毁,内存由系统来管理,程序员不可控制
  • 2、加载的图片,占用的内存非常大
  • 3、相同的图片不会被重复加载到内存

imageWithContentsOfFile:

  • 1、当对象销毁的时候,图片占用的内存会随着一起销毁
  • 2、加载的图片占用的内存较小 3、相同的图片如果被多次加载就会占据多个内存空间

III 内容模式

首先了解下图片的内容模式

3.1 内容模式

  • UIViewContentModeScaleToFill

拉伸图片至填充整个UIImageView,图片的显示尺寸会和imageVew的尺寸一样 。 This will scale the image inside the image view to fill the entire boundaries of the image view.

  • UIViewContentModeScaleAspectFit

图片的显示尺寸不能超过imageView尺寸大小 This will make sure the image inside the image view will have the right aspect ratio and fits inside the image view’s boundaries.

  • UIViewContentModeScaleAspectFill

按照图片的原来宽高比进行缩放(展示图片最中间的内容),配合使用 tmpView.layer.masksToBounds = YES;

This will makes sure the image inside the image view will have the right aspect ratio and fills the entire boundaries of the image view. For this value to work properly, make sure that you have set the clipsToBounds property of the image view to YES.

  • UIViewContentModeScaleToFill : 直接拉伸图片至填充整个imageView

划重点:

  1. UIViewContentModeScaleAspectFit : 按照图片的原来宽高比进行缩放(一定要看到整张图片)

使用场景:信用卡图片的展示 在这里插入图片描述

  1. UIViewContentModeScaleAspectFill : 按照图片的原来宽高比进行缩放(只能图片最中间的内容)

引导页通常采用UIViewContentModeScaleAspectFill


 // 内容模式
 self.contentMode = UIViewContentModeScaleAspectFill;
 // 超出边框的内容都剪掉
 self.clipsToBounds = YES;
 
 

3.2 例子:商品详情页的实现

- (void)awakeFromNib
 {
 [super awakeFromNib];
 // 拉伸
 //    self.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"bg_dealcell"]];
 // 平铺
 //    self.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"bg_dealcell"]];
 
 
 [self setAutoresizingMask:UIViewAutoresizingNone];
 
 
 
 }
 
 
 
 
 - (void)drawRect:(CGRect)rect
 {
 // 平铺
 //    [[UIImage imageNamed:@"bg_dealcell"] drawAsPatternInRect:rect];
 // 拉伸
 [[UIImage imageNamed:@"bg_dealcell"] drawInRect:rect];
 }
 

 
 背景图片的拉伸(中间空白的小矩形设置为可拉伸,保证有形状的地方不进行缩放)
 UIImage *resizableImage = [image resizableImageWithCapInsets:UIEdgeInsetsMake(heightForLeftORRight, widthForTopORBottom, heightForLeftORRight, widthForTopORBottom)];

see also

只为你呈现有价值的信息,专注于移动端技术研究领域;更多服务和咨询请关注#公众号:iOS逆向