UIImageView

UIImageView 文檔,https://developer.apple.com/reference/uikit/uiimageview?language=objc

An object that displays a single image or a sequence of animated images in your interface.

ContentMode影響圖片的縮放

scale表示會縮放圖片,aspect表示按圖片比例縮放,fill表示填滿imageView,fit表示不大于imageView。

typedef NS_ENUM(NSInteger, UIViewContentMode) {
    UIViewContentModeScaleToFill,
    UIViewContentModeScaleAspectFit,      // contents scaled to fit with fixed aspect. remainder is transparent
    UIViewContentModeScaleAspectFill,     // contents scaled to fill with fixed aspect. some portion of content may be clipped.
   
    UIViewContentModeRedraw,              // redraw on bounds change (calls -setNeedsDisplay)
    UIViewContentModeCenter,              // contents remain same size. positioned adjusted.
    UIViewContentModeTop,
    UIViewContentModeBottom,
    UIViewContentModeLeft,
    UIViewContentModeRight,
    UIViewContentModeTopLeft,
    UIViewContentModeTopRight,
    UIViewContentModeBottomLeft,
    UIViewContentModeBottomRight,
};
ImageView_ContentMode.png

對于沒有設(shè)置capInsets的圖片,縮放完全由contentMode決定。capInsets可以決定圖片縮放的區(qū)域和方向。伸縮圖片用resizableImageWithCapInsets:resizingMode: 方法創(chuàng)建。
使用伸縮圖片的話,一般把imageView的contentMode設(shè)置為UIViewContentModeScaleToFill。

圖片拉伸

UIImageView *iv1 = [self.view viewWithTag:11];
UIImageView *iv2 = [self.view viewWithTag:12];
UIImageView *iv3 = [self.view viewWithTag:13];

// 設(shè)置保護區(qū)域,上左下右。這里是距離底部58之間的區(qū)域在垂直方向上不被拉伸
UIEdgeInsets capInsets2 = UIEdgeInsetsMake(0, 0, 58, 0);
UIEdgeInsets capInsets3 = UIEdgeInsetsMake(58, 0, 0, 0);

//    UIImage *image = [UIImage imageNamed:@"藍綠"]; // 44, 116
//    UIImage *image2 = [image resizableImageWithCapInsets:capInsets2]; // 默認平鋪,不是拉伸,所以不用這個方法
//    UIImage *image3 = [image resizableImageWithCapInsets:capInsets3];

UIImage *image = iv1.image; // 圖片大?。?4, 116
UIImage *image2 = [image resizableImageWithCapInsets:capInsets2 resizingMode:UIImageResizingModeStretch];
UIImage *image3 = [image resizableImageWithCapInsets:capInsets3 resizingMode:UIImageResizingModeStretch];

iv2.image = image2;
iv3.image = image3;

圖片拉伸.png

<p>

圖片透明度

官方文檔:
Similarly, any further transparency in the background of the image is dependent on the transparency of the image view and the transparency of the UIImage object it displays. When the image view and its image both have transparency, the image view uses alpha blending to combine the two.

如果image view的opaque屬性是YES,the image’s pixels are composited on top of the image view’s background color and the alpha property of the image view is ignored.

如果image view的opaque屬性是NO,the alpha value of each pixel is multiplied by the image view’s alpha value, with the resulting value becoming the actual transparency value for that pixel. If the image does not have an alpha channel, the alpha value of each pixel is assumed to be 1.0.

需要注意的是,結(jié)合透明圖片和透明image view的alpha channel的代價是昂貴的。如果使用Core Animation shadows,性能會進一步受影響,因為需要動態(tài)計算。如果不需要透明效果,設(shè)置opaque為NO可以提高性能。

Responding to Touch Events

image view 默認忽略用戶事件,可以設(shè)置userInteractionEnabled = YES接收事件,然后添加手勢來處理。更多事件相關(guān)信息,查看 Event Handling Guide for UIKit Apps.

Tips for Improving Performance

  • Cache scaled versions of frequently used images. 如果圖片很大,視圖較小,可以預(yù)先創(chuàng)建縮略圖并緩存,避免每個image view都要縮放圖片。

  • Use images whose size is close to the size of the image view. 創(chuàng)建和視圖大小匹配的圖片,而不是直接使用大圖片。也可以創(chuàng)建resizable image,使用平鋪來代替縮放,平鋪使用的選項是UIImageResizingModeTile。

  • Make your image view opaque whenever possible. 如果不使用透明圖片,可以設(shè)置opaque屬性為YES使其不透明,默認為YES。

<p>

Debugging Issues with Your Image View

如果圖片不能正常顯示:

  • **Load images using the correct method. ** 使用 imageNamed:imageNamed:inBundle:compatibleWithTraitCollection: 方法加載 asset catalogs 或者 app’s bundle 的圖片。app’s bundle 之外的圖片,使用 imageWithContentsOfFile: 方法。

  • Do not use image views for custom drawing. TheUIImageView class does not draw its content using the drawRect: method. Use image views only to present images. To do custom drawing involving images, subclass UIView directly and draw your image there.

<p>

State Preservation

給 image view的 restorationIdentifier 賦值,它會嘗試保存 frame、bounds、center、transform和 layer屬性的 anchorPoint。
For more information about how state preservation and restoration works, see App Programming Guide for iOS.

Animating a Sequence of Images

創(chuàng)建一個圖片數(shù)組,然后賦值給imageView的animationImages屬性?;蛘咄ㄟ^animatedImageWithImages:duration:方法創(chuàng)建一個image對象,然后賦值給imageView的image屬性。兩個要求:

  • All images in the sequence should have the same size.
  • All images in the sequence should use the same content scale factor.

雖然UIImageView顯示gif是靜止的,但是可以播放一組圖片作為動畫效果。先講一下如何獲取動態(tài)圖。靜態(tài)圖片用imageName:方法創(chuàng)建。動態(tài)圖不能直接加載gif生成,而是用animatedImageNamed: duration:方法創(chuàng)建,該方法會加載基本名字相同的圖片(比如imageName0,imageName1,imageName1024,等等),然后返回一個UIImage的對象image,image有個數(shù)組屬性images表示所有的圖片。

// 加載基本名字相同的圖片:name0,name1,… 數(shù)字要連續(xù),如果少了name4,那么name5和之后的圖片不會加載。名字可以是中文。
// duration表示播放周期,不是時間間隔哦!
// read sequence of files with suffix starting at 0 or 1. 
+ (nullable UIImage *)animatedImageNamed:(NSString *)name duration:(NSTimeInterval)duration NS_AVAILABLE_IOS(5_0);  

有兩種方法可以播放動畫。第一種是設(shè)置image屬性,第二種是設(shè)置animationImages屬性。第一種會自動播放動畫,不能設(shè)置循環(huán)次數(shù)、循環(huán)周期,不能結(jié)束動畫,第二種則相反。也可以設(shè)置高亮狀態(tài)的動畫 highlightedAnimationImages。

// The array must contain UIImages. Setting hides the single image. default is nil
@property (nullable, nonatomic, copy) NSArray<UIImage *> *animationImages; 
// 獲取UIImageView
UIImageView *iv = [self.view viewWithTag:100];

// 加載圖片Gundam0,Gundam1.png,… 循環(huán)周期2秒??梢允侵形摹?shù)字要連續(xù),從0或1開始。貌似不能加載tiff圖片。
UIImage *animatedImage = [UIImage animatedImageNamed:@"Gundam" duration:2];

// 第一種,直接設(shè)置image。動畫自動開始,不能通過stopAnimating方法暫停動畫,設(shè)置動畫時間和重復次數(shù)無效。
iv.image = animatedImage;

// 第二種,設(shè)置animationImages屬性
iv.image = animatedImage.images.firstObject; // 動畫開始前和結(jié)束后顯示的圖片
iv.animationImages = animatedImage.images; // 設(shè)置圖片數(shù)組
iv.animationRepeatCount = -1; // 設(shè)置次數(shù)小于等于0依然會動
iv.animationDuration = 5; // 設(shè)置動畫周期
[iv startAnimating]; // 這句要在最后調(diào)用

注意了,修改動畫周期和次數(shù)會停止動畫??梢酝ㄟ^animating屬性判斷動畫狀態(tài)。

// 兩秒后執(zhí)行代碼
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    UIImageView *iv = [self.view viewWithTag:100];
    NSLog(@"%d", iv.animating); // 輸出1
    iv.animationRepeatCount = 600;
    NSLog(@"%d", iv.animating); // 輸出0

    [iv stopAnimating]; // 停止動畫
});

顯示GIF圖片

UIImageView的image屬性只能顯示gif的第一幀圖片,想使用animationImages屬性但是獲取gif的所有圖片又很麻煩。

UIImage *animatedImage = [UIImage imageNamed:@"demo.gif"];
UIImage *animatedImage = [UIImage animatedImageNamed:@"demo.gif" duration:2]; // 加載失敗,animatedImage為nil
UIImageView *iv = [self.view viewWithTag:100];
iv.image = animatedImage; // 顯示的圖片靜止
iv.animationImages = animatedImage.images; // 嘗試獲取gif的所有圖片,但是animatedImage.images是nil

UIWebView可以正確顯示gif圖片但是效果不好,還是使用第三方庫吧。顯示本地的gif可以使用YYImage和FLAnimatedImage ,顯示網(wǎng)絡(luò)的gif可以使用YYWebImage和SDWebImage。sd實際用的FLAnimatedImage,只不過給它加了一個category。YYImage比FLAnimatedImage使用的內(nèi)存更少,使用webView是最占內(nèi)存的。測試一個5.6MB的gif圖片,yy占內(nèi)存6.4,sd占11.8,webView占33.8MB。播放速度,yy和sd一樣,webView最快。webView加載gif最慢。

YYKit、YYImage、YYWebImageSDWebImage、FLAnimatedImage,
使用SDWebImage和YYImage下載高分辨率圖,導致內(nèi)存暴增的解決辦法

使用SDWebImage播放gif,不管本地還是網(wǎng)絡(luò)的,都要使用FLAnimatedImage。sd的sd_animatedGIFWithData方法返回的image只包含第一幀。FLAnimatedImage要另外添加到項目中。

使用SDWebImage顯示gif:

// 該文件擴展了FLAnimatedImageView的sd_setImageWithURL:方法
#import "FLAnimatedImageView+WebCache.h"

// 測試網(wǎng)絡(luò)gif
NSString *urlStr = @"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1488309254574&di=62e28c0d91d1711546ff9344d4570af6&imgtype=0&src=http%3A%2F%2Fmat1.gtimg.com%2Fcomic%2Fbaba%2Fguzhang.gif";
NSURL *url = [NSURL URLWithString:urlStr];

// 測試本地gif
NSString *urlStr = [[NSBundle mainBundle]pathForResource:@"demo" ofType:@"gif"];
NSURL *url = [NSURL fileURLWithPath:urlStr];

FLAnimatedImageView *iv = [FLAnimatedImageView new]; 
[iv sd_setImageWithURL:url];

使用YYWebImage顯示gif:

#import "YYImage.h"
#import "UIImageView+YYWebImage.h"

// 測試網(wǎng)絡(luò)gif
NSString *urlStr = @"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1488309254574&di=62e28c0d91d1711546ff9344d4570af6&imgtype=0&src=http%3A%2F%2Fmat1.gtimg.com%2Fcomic%2Fbaba%2Fguzhang.gif";
NSURL *url = [NSURL URLWithString:urlStr];

// 測試本地gif
NSString *urlStr = [[NSBundle mainBundle]pathForResource:@"demo" ofType:@"gif"];
NSURL *url = [NSURL fileURLWithPath:urlStr];

UIImageView *iv = [YYAnimatedImageView new];

iv.yy_imageURL = url;
// 或者
[iv yy_setImageWithURL:url options:0];

使用YYImage加載本地的gif還可以這樣寫:

#import "YYImage.h"

UIImage *image = [YYImage imageNamed:@"demo.gif"];
UIImageView *imageView = [[YYAnimatedImageView alloc] initWithImage:image];

使用FLAnimatedImage顯示本地的gif:

NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"https://upload.wikimedia.org/wikipedia/commons/2/2c/Rotating_earth_%28large%29.gif"]];
FLAnimatedImage *image = [FLAnimatedImage animatedImageWithGIFData:data];
FLAnimatedImageView *imageView = [[FLAnimatedImageView alloc] init];
imageView.animatedImage = image;

總結(jié)一下,顯示gif有兩種方法。一種是把gif分解成多張png,然后通過UIImageView的animationImages屬性顯示。另一種是使用第三方或者UIWebView顯示gif。通過代碼提取gif的所有圖片再用UIimageView顯示比較復雜,不推薦使用。使用SDWebImage顯示gif,記得是調(diào)用sd給FLAnimatedImage添加的category方法。使用YYimage顯示gif占用的內(nèi)存最少。

<p>
未完待續(xù)。

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

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

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,161評論 4 61
  • Swift版本點擊這里歡迎加入QQ群交流: 594119878最新更新日期:18-09-17 About A cu...
    ylgwhyh閱讀 26,005評論 7 249
  • UIImageView 用UIImageView來顯示圖片,其contentMode屬性控制圖片如何顯示,默認值是...
    ilaoke閱讀 916評論 1 2
  • 好人是個什么概念?善良,沒脾氣,愛奉獻,講道德,守信用,樂于助人,等等這些詞匯無不和好人掛鉤。每個人都想和好人...
    三腳貓WW閱讀 1,560評論 0 0
  • 今夜不眠 我在雨后的寂靜里讀你 黑暗是你的眸光 流淌著熱情的呼喚 別忘記那一眼如月的彎 深情處,蓄滿力量 大山是你...
    藍朵世界閱讀 629評論 45 47

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