Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 百思不得姐之圖片處理(保存與下載)

百思不得姐之圖片處理(保存與下載)

編輯:關於Android編程

一 功能圖

這裡寫圖片描述

二 講解思路

1 回顧上一篇內容

2 創建加載圖片類(同時創建xib)

3 點擊圖片查看大圖

4 點擊查看大圖(查看長圖)

5 model出展示圖片的控制器

6 保存圖片

7 封裝根據網絡狀態展示不同的圖片

三 回顧上一篇內容

1 上一篇內容講到對整個cell的分析,通過創建一個類(XIB)來管理cell的頂部和尾部總共九個控件.然後創建三個不同的類(xib),各自負責自己的中間部分,然後根據服務器返回的帖子類型,拼接上對應的cell,展示在用戶眼前.

四 處理圖片

1 處理原因: 由於從服務器中返回的圖片的類型有兩種:小圖和長圖,相對於其他部分,圖片的處理相對來說比較麻煩.所以這裡我先將展示圖片的功能處理下.

2 創建加載圖片類

這裡寫圖片描述

3 處理圖片的xib

這裡寫圖片描述

—-> 3.1 注意一 : 占位文字”百思不得姐”字樣的放置位置,放在UIImageView的下面,有利於在圖片還沒有從服務器中加載的時候,能顯示”百思不得姐”字樣,給用戶比較好的體驗(由於美工沒有提供占位視圖,只提供了一段文字,注意設置文字的樣式為:下圖)

這裡寫圖片描述

—-> 3.2 注意二 : 注意”點擊查看大圖”按鈕中的圖片和文字中間的距離.我們是通過讓圖片向左移動5厘米並且讓文字想右移動5厘米來達到中間的間隙,並且能讓圖片和文字總體處於中間位置.(設置地方)
—> 圖一 :

這裡寫圖片描述

—> 圖二 :

這裡寫圖片描述

4 圖片類中需要用到的屬性(通過拖線的方式拿到xib中需要的屬性)

/**
 *  背景圖片
 */
@property (weak, nonatomic) IBOutlet UIImageView *pictureBackImageView;
/**
 *  點擊查看大圖
 */
@property (weak, nonatomic) IBOutlet UIButton *seeBigPictureImageView;
/**
 *  動圖
 */
@property (weak, nonatomic) IBOutlet UIImageView *gifImageView;

5 定義模型屬性(用於重寫模型屬性的set方法)

/**
 *  導入模型
 */
@property (nonatomic, strong) XFJItem *topicesPicture;

6 模型的set方法

—-> 6.1 開啟上下文(如果圖片為長圖)
—-> 6.2 繪圖(如果圖片為長圖)
—-> 6.3 關閉上下文 (如果圖片為長圖)

總體代碼:

#pragma mark - 模型屬性的set方法
- (void)setTopicesPicture:(XFJItem *)topicesPicture
{
    _topicesPicture = topicesPicture;

    [self.pictureBackImageView XFJ_originalImageURL:topicesPicture.image1 thumbnailImageURL:topicesPicture.image0 completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {

        //判斷如果圖片下載失敗就返回
        if (image == nil) return ;
        //如果不是長圖就返回
        if (!topicesPicture.isBigPicture) return;

        //長圖來到下面
        CGFloat pictureW = topicesPicture.middleFrame.size.width;
        CGFloat pictureH = topicesPicture.middleFrame.size.height;
        //開啟上下文
        UIGraphicsBeginImageContext(CGSizeMake(pictureW, pictureH));
        /*
          上下文的寬度             上下文的高度
         ------------    =     ---------------
         服務器返回圖片的寬度    服務器返回圖片的高度
         */
        //繪圖
        [image drawInRect:CGRectMake(0, 0, pictureW, pictureW * topicesPicture.height / topicesPicture.width)];

        //獲得圖片
        self.pictureBackImageView.image = UIGraphicsGetImageFromCurrentImageContext();

        //圖形上下文
        UIGraphicsEndImageContext();

    }];

    //如果是短圖就隱藏點擊查看大圖按鈕
    self.seeBigPictureImageView.hidden = !topicesPicture.isBigPicture;

    //如果不是動圖就隱藏動圖圖標
    self.gifImageView.hidden = !topicesPicture.is_gif;


}

五 處理點擊圖片和查看大圖業務邏輯

1 點擊查看大圖(通過拖線的方式我們進行對按鈕的監聽)

- (IBAction)seeBigPictureClick
{
    [self seeBigPicture];
}

2 調用的方法

#pragma mark - 實現輕按事件
- (void)seeBigPicture
{
    //創建控制器
    XFJSeeBigPicture *seePicture = [[XFJSeeBigPicture alloc] init];
    //如果不寫這一句的話,會出現NaN的情況
    seePicture.topicesItem = self.topicesPicture;
    //model出該控制器
    [self.window.rootViewController presentViewController:seePicture animated:YES completion:nil];
}

3 由於當用戶不管點擊圖片還是點擊查看大圖都會使得圖片上展示出來,所以,我們給圖片添加一個點按手勢,其中點按要實現的方法恰好是查看大圖的方法.

#pragma mark - 加載xib的時候回來到這個方法
- (void)awakeFromNib
{
    //允許圖片接收事件
    self.pictureBackImageView.userInteractionEnabled = YES;
    //創建請按手勢
    UITapGestureRecognizer *gest = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(seeBigPicture)];
    //給圖片添加手勢
    [self.pictureBackImageView addGestureRecognizer:gest];
}

六 展示圖片的控制器(處理)

1 通過點擊圖片或者查看圖片的按鈕,可以看得出控制器是直接model出來的.

2 通過整體的圖片在該控制器中的展示,我們不難看出,當圖片為長圖的時候用戶需要往上滑動才能查看下面的圖片,所以在dodel出來的控制器中層次結構為: UIScrollView–>UIImageView–>返回和保存按鈕.

3 展示的xib效果圖

這裡寫圖片描述

4 需要用到的屬性

/**
 *  保存按鈕
 */
@property (weak, nonatomic) IBOutlet UIButton *saveButton;

@property (nonatomic, weak) UIImageView *imageView;

5 通過直接拖線的方式,處理返回按鈕(將model出來的控制器dissmiss)

- (IBAction)backClick
{
    [self dismissViewControllerAnimated:YES completion:nil];
}

6 添加UIScrollView

#pragma mark - 添加scrollerView
- (void)setUpContentView
{
    //創建UIScrollView
    UIScrollView *scrollView = [[UIScrollView alloc] init];
    //設置尺寸
    scrollView.frame = CGRectMake(0, 0, XFJ_screenW, XFJ_screenH);
    //添加手勢
    [scrollView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(backClick)]];
    //設置顏色
    scrollView.backgroundColor = [UIColor blackColor];
    //添加插入到view中
    [self.view insertSubview:scrollView atIndex:0];
    //調用方法
    [self setUpcontentImageView:scrollView];
}
—-> 6.1 注意 :創建的UIScrollView一定要選擇插入到model出來的控制器中,否則會出錯.不能直接添加.

7 添加UIScrollView上的UIImageView

—-> 7.1 計算圖片的高度
—-> 7.2 給圖片添加一個縮放功能

總體的代碼:

#pragma mark - 在contentView中添加UIImageView
- (void)setUpcontentImageView:(UIScrollView *)scrollView
{
    UIImageView *imageView = [[UIImageView alloc] init];
    //添加圖片
    [imageView sd_setImageWithURL:[NSURL URLWithString:self.topicesItem.image1] placeholderImage:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
       //如果下載的圖片為空
        if (image == nil) return ;
        self.saveButton.enabled = YES;
    }];
    //設置尺寸
    imageView.XFJ_X = 0;
    imageView.XFJ_Width = scrollView.XFJ_Width;
    [scrollView addSubview:imageView];
    //賦值
    self.imageView = imageView;
    //圖片的高度
    imageView.XFJ_Height = imageView.XFJ_Width * self.topicesItem.height / self.topicesItem.width;
    //判斷
    if (imageView.XFJ_Height >= XFJ_screenH) {
        imageView.XFJ_Y = 0;
        scrollView.contentSize = CGSizeMake(0, imageView.XFJ_Height);
    }else{
        imageView.XFJ_centerY = scrollView.XFJ_Height * 0.5;
    }

    CGFloat maxScale = self.topicesItem.width / self.imageView.XFJ_Width;
    //判斷
    if (maxScale >= 1.0) {
        scrollView.maximumZoomScale = maxScale;
        scrollView.delegate = self;
    }
}

8 代理方法處理縮放圖片

#pragma mark - 代理方法
//return a view that will be scaled. if delegate returns nil, nothing happens
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
    return self.imageView;
}

9 保存圖片

—-> 9.1 點擊保存按鈕,保存圖片
- (IBAction)savePicture
{
    UIImageWriteToSavedPhotosAlbum(self.imageView.image, self, @selector(image: didFinishSavingWithError: contextInfo:), nil);
}
—-> 9.2 提示用戶是否保存成功
#pragma mark - 是否保存成功
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
    if (error) {
        [SVProgressHUD showErrorWithStatus:@"保存失敗"];
    }else{
        [SVProgressHUD showSuccessWithStatus:@"保存成功"];
    }
}
—-> 9.3 注意 :UIImageWriteToSavedPhotosAlbum對該方法,蘋果官方文檔中有說明,@selector中調用的方法,必須是(下面)方法,否則就會報錯.
//  - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo;

七 建立聯系

1 怎麼樣將各部分負責的UIView插入到自定義的cell中呢?

—-> 解答:通過下面的判斷(self.topicesPicture.topicesPicture = topices;)主要作用
//通過貼模型中定義的屬性帖子的類型
    switch (self.topices.type) {
        case XFJTopicTypeWord://段子
            //將聲音;圖片;視頻圖片都隱藏
            self.topicesPicture.hidden = YES;
            self.topicesVideo.hidden = YES;
            self.topicesVoice.hidden = YES;
            break;
        case XFJTopicTypePicture://圖片
            //圖片出現;聲音;視頻隱藏
            self.topicesVideo.hidden = YES;
            self.topicesVoice.hidden = YES;
            self.topicesPicture.topicesPicture = topices;
            self.topicesPicture.hidden = NO;
            break;
        case XFJTopicTypeVideo://視頻
            //視頻出現;聲音和圖片隱藏
            self.topicesPicture.hidden = YES;
            self.topicesVoice.hidden = YES;
            self.topicesVideo.topicesVideo = topices;
            self.topicesVideo.hidden = NO;
            break;
        case XFJTopicTypeVoice://聲音
            //聲音出現;圖片和視頻隱藏
            self.topicesPicture.hidden =YES;
            self.topicesVoice.topicesVoice = topices;
            self.topicesVoice.hidden = NO;
            self.topicesVideo.hidden = YES;
            break;
        default:
            break;
    }

2 通過(self.topicesPicture.topicesPicture = topices;)需要加載對應的xib

#pragma mark - 圖片xib懶加載
- (XFJTopicesPictureView *)topicesPicture
{
    if (_topicesPicture == nil) {
        //創建xib
        XFJTopicesPictureView *picture = [XFJTopicesPictureView XFJ_middleXib];
        //添加到tableView中的contentView中
        [self.contentView addSubview:picture];
        //賦值
        _topicesPicture = picture;
    }
    return _topicesPicture;
}

3 調用下面的方法來加載對應的xib(self:誰調用就代表加載誰的xib)

#pragma mark - 實現快速創建xib的方法
+ (instancetype)XFJ_middleXib
{
    return [[NSBundle mainBundle] loadNibNamed:NSStringFromClass(self) owner:nil options:nil].firstObject;
}

八 根據用戶網絡狀態來下載不同規格的圖片大小(封裝)

1 思路:見下面偽代碼

/*
    if (緩存中有原圖) {
        self.imageView.image = 原圖;
    } else {
        if (Wifi環境) {
            下載顯示原圖
        } else if (手機自帶網絡) {
            if (用戶設置3G\4G環境下仍然下載原圖) {
                下載顯示原圖
            } else {
                下載顯示小圖
            }
        } else {
            if (緩存中有小圖) {
                self.imageView.image = 小圖;
            } else {
                self.imageView.image = 占位圖片;
            }
        }
    }*/

2 封裝

—-> 2.1 .h文件
/**
 *  設置下載的圖片類型(原圖或縮略圖)
 *
 *  @param originalImageURL  原圖的URL
 *  @param thumbnailImageURL 縮略圖的URL
 *  @param placeholderImage  占位視圖
 *  @param completedBlock    設置完圖片回調
 */
- (void)XFJ_originalImageURL:(NSString *)originalImageURL thumbnailImageURL:(NSString *)thumbnailImageURL placeholderImage:(UIImage *)placeholderImage completed:(SDWebImageCompletionBlock)completedBlock;
/**
 *  設置下載的圖片類型(原圖或縮略圖)
 *
 *  @param originalImageURL  原圖的URL
 *  @param thumbnailImageURL 縮略圖的URL
 */
- (void)XFJ_originalImageURL:(NSString *)originalImageURL thumbnailImageURL:(NSString *)thumbnailImageURL;
/**
 *  設置下載的圖片類型(原圖或縮略圖)
 *
 *  @param originalImageURL  原圖的URL
 *  @param thumbnailImageURL 縮略圖的URL
 *  @param placeholderImage  占位視圖
 */
- (void)XFJ_originalImageURL:(NSString *)originalImageURL thumbnailImageURL:(NSString *)thumbnailImageURL placeholderImage:(UIImage *)placeholderImage;
/**
 *  設置下載的圖片類型(原圖或縮略圖)
 *
 *  @param originalImageURL  原圖的URL
 *  @param thumbnailImageURL 縮略圖的URL
 *  @param completedBlock    設置完圖片回調
 */
- (void)XFJ_originalImageURL:(NSString *)originalImageURL thumbnailImageURL:(NSString *)thumbnailImageURL completed:(SDWebImageCompletionBlock)completedBlock;
—-> 2.2 .m文件(需要導入的框架AFN)
#pragma mark - 不需要傳占位視圖和完成需要做的事
- (void)XFJ_originalImageURL:(NSString *)originalImageURL thumbnailImageURL:(NSString *)thumbnailImageURL
{
    [self XFJ_originalImageURL:originalImageURL thumbnailImageURL:thumbnailImageURL placeholderImage:nil completed:nil];
}

#pragma mark - 需要傳入占位視圖
- (void)XFJ_originalImageURL:(NSString *)originalImageURL thumbnailImageURL:(NSString *)thumbnailImageURL placeholderImage:(UIImage *)placeholderImage
{
    [self XFJ_originalImageURL:originalImageURL thumbnailImageURL:thumbnailImageURL placeholderImage:placeholderImage completed:nil];
}
#pragma mark - 需要設置完圖片回調
- (void)XFJ_originalImageURL:(NSString *)originalImageURL thumbnailImageURL:(NSString *)thumbnailImageURL completed:(SDWebImageCompletionBlock)completedBlock
{
    [self XFJ_originalImageURL:originalImageURL thumbnailImageURL:thumbnailImageURL placeholderImage:nil completed:completedBlock];
}
#pragma mark - 需要設置占位視圖和完成回調
- (void)XFJ_originalImageURL:(NSString *)originalImageURL thumbnailImageURL:(NSString *)thumbnailImageURL placeholderImage:(UIImage *)placeholderImage completed:(SDWebImageCompletionBlock)completedBlock
{
    //先去緩存池中或者沙盒中尋找原圖
    UIImage *originalImageView = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:originalImageURL];
    //判斷如果有原圖的話
    if (originalImageView) {
        //設置圖片(有原圖)
        [self sd_setImageWithURL:[NSURL URLWithString:originalImageURL] placeholderImage:placeholderImage completed:completedBlock];
    }else{
        //        內存或者沙盒中沒有原圖-->下載
        AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager sharedManager];
        //判斷網絡情況
        if (manager.isReachableViaWiFi) {//如果是wifi
            [self sd_setImageWithURL:[NSURL URLWithString:originalImageURL] placeholderImage:placeholderImage completed:completedBlock];
        }else if(manager.isReachableViaWWAN){//如果是3G或4G的話就看用戶選擇
            //從沙盒中讀取用戶對是否下載原圖的配置
            BOOL alwaysDownloadOriginalImage = [[NSUserDefaults standardUserDefaults] boolForKey:@"alwaysDownloadOriginalImage"];
            //如果是下載原圖就直接下載
            if (alwaysDownloadOriginalImage) {
                [self sd_setImageWithURL:[NSURL URLWithString:originalImageURL] placeholderImage:placeholderImage completed:completedBlock];
            }else{
                //否則就下載小圖
                [self sd_setImageWithURL:[NSURL URLWithString:thumbnailImageURL] placeholderImage:placeholderImage completed:completedBlock];
            }

        }else{
            //沒有網絡,讀取緩存\沙盒中小圖
            UIImage *thumbnailImage = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:thumbnailImageURL];
            //如果有緩存\沙盒中有小圖
            if (thumbnailImage) {
                [self sd_setImageWithURL:[NSURL URLWithString:thumbnailImageURL] placeholderImage:placeholderImage completed:completedBlock];
            }else{
                [self sd_setImageWithURL:nil placeholderImage:placeholderImage completed:completedBlock];
            }
        }
    }
}

九 總結

1 該部分著重的講解了對圖片處理和對用戶網絡狀態顯示多大規格的圖片進行處理.代碼內部的業務邏輯相對來說比較難(需要考慮到多方面的因素),但總的來說還是可以解決的,可能裡面有一些還沒有想到,後期想到會完善的.

2 後面我會繼續完善百思不得姐,希望帶給大家更多的不一樣的想法,最後大家如果覺得我寫的博客還滿意的話,麻煩大家多多建議,多多關注我的官方博客,謝謝!!!!

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved