1. 程式人生 > >iOS學習之圖片放大,滑動瀏覽

iOS學習之圖片放大,滑動瀏覽

iOS許多APP中都使用到了圖片放大瀏覽的功能,如淘寶、微信等。最近也琢磨了一些方法,基本可以實現點選圖片放大,並且可以左右滑動瀏覽上一張下一張圖片,也可以通過手勢撐開放大縮小,可以加上長按儲存到相簿的功能。具體的做法是子類化UIImageView,新增點選手勢,監聽手勢建立UIScrollView瀏覽檢視,實現左右滑動,每張圖片用獨自的UIScrollView盛放便可以實現放大縮小旋轉等功能

一、效果

瀏覽效果和放大效果

            

二、實現流程

1、子類化UIImageView,取名為ZoomImageView

#import <UIKit/UIKit.h>

@class ZoomImageView;
@protocol ZoomImageViewDelegate <NSObject>
@optional
//圖片將要放大
- (void)imageWillZoomIn:(ZoomImageView *)imageView;
//圖片已經放大
- (void)imageDidZoomIn:(ZoomImageView *)imageView;
//圖片將要隱藏
- (void)imageWillZoomOut:(ZoomImageView *)imageView;
//圖片已經隱藏
- (void)imageDidZoomOut:(ZoomImageView *)imageView;
@end

@interface ZoomImageView : UIImageView {
    UIImageView *_fullImageView;
}
@property (nonatomic, weak)id<ZoomImageViewDelegate> delegate;
//繫結資料用於瀏覽
@property (nonatomic,strong)NSMutableArray *imageArray;
//描述
@property (nonatomic,strong)NSMutableArray *desArray;
//當前圖片
@property (nonatomic,strong)NSString *nowImage;
- (instancetype)initWithFrame:(CGRect)frame withImage:(NSString *)imageStr;
2、給ZoomImageView新增點選事件,實現放大動畫
//是否處於點選狀態   
 _isTap = NO;
//新增點選手勢
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(zoomAction)];
[self addGestureRecognizer:tap];
self.userInteractionEnabled = YES;
//等比例放大縮小
self.contentMode = UIViewContentModeScaleAspectFit;

實現ZoomAction圖片放大方法,當zoomImageView 被點選,用[self _createViews]建立放大所需的檢視。然後顯示_maskView,_maskView的背景設定為黑色,這樣原來的圖片就將被黑色覆蓋,接著獲取被點選的圖片的frame,將_fullImageView的的座標設定為被點選圖片的座標,用_fullImageView實現放大動畫,放大完成後_fullImageView再次隱藏並移除,這樣就實現了放大功能。最後顯示用於圖片滑動瀏覽的_photoListView檢視。

- (void)zoomAction{
    if (_isTap == YES) {
        return;
    }else{
        _isTap = YES;
    }
    NSLog(@"開始放大");
    //呼叫代理物件將要放大的協議方法
    if ([self.delegate respondsToSelector:@selector(imageWillZoomIn:)]) {
        [self.delegate imageWillZoomIn:self];
    }
    [self _createView];
    //座標系由當前檢視轉化為window的座標
    CGRect frame = [self convertRect:self.bounds toView:self.window];
  
    _fullImageView.frame = frame;
    _maskView.alpha = 1;
    _maskView.hidden = NO;
    
    //設定動畫效果實現放大
    [UIView animateWithDuration:0.3 animations:^{
        //放大到整個螢幕
        _fullImageView.frame = [UIScreen mainScreen].bounds;
        
    } completion:^(BOOL finished) {
        
        _photoListView.hidden = NO;
        _maskView.hidden = NO;
        _fullImageView.hidden = YES;
        
        //呼叫代理物件已經放大的協議方法
        if ([self.delegate respondsToSelector:@selector(imageDidZoomIn:)]) {
            [self.delegate imageDidZoomIn:self];
        }
    }];
}
當圖片被點選的時候,建立放大所需的檢視,_maskView為黑色背景檢視,_photoListView繼承UIView,用於放置瀏覽圖片的檢視,_fullImageView繼承自UIImageView,用於實現圖片放大動畫
//建立大圖顯示時需要的子檢視
- (void)_createView {
    
    if (_photoListView == nil) {
       
        //蒙砂檢視
        _maskView = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];
        _maskView.backgroundColor = [UIColor blackColor];
        _maskView.alpha = 1;
        _maskView.hidden = YES;
        [self.window addSubview:_maskView];
        
        //圖片瀏覽檢視
        _photoListView = [[PhotoListView alloc] initWithFrame:[UIScreen mainScreen].bounds];
        _photoListView.hidden = YES;
        _photoListView.desArray = _desArray;
        _photoListView.images = _imageArray;
        
        //計算當前檢視為第幾張
        for(NSInteger i = 0; i < _imageArray.count;i++){
            NSString *urlNow = _imageArray[i];
            if([_nowImage isEqualToString:urlNow] ){
                _photoListView.indexPath = i;
            }
        }
        [self.window addSubview:_photoListView];
        
        //建立大圖顯示檢視
        _fullImageView = [[UIImageView alloc] initWithFrame:CGRectZero];
        _fullImageView.image = self.image;
        _fullImageView.contentMode = UIViewContentModeScaleAspectFit;
        [self.window addSubview:_fullImageView];

    }
}
3、PhotoListView的建立,實現滑動圖片瀏覽

在PhotoListView上建立UIcollectionView,每個cell的大小設定為螢幕大小,每個cell盛放一張圖片,滑動方向設定為左右滑動

UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.itemSize = CGSizeMake(kScreenWidth, kScreenHeight);
layout.minimumInteritemSpacing = 0;
layout.minimumLineSpacing = 30;
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
_collectionView =[[PhotoCollectionView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth + 30,kScreenHeight) collectionViewLayout:layout];
_collectionView.backgroundColor = [UIColor clearColor];
[self addSubview:_collectionView];
此處需要在檢視底部建立每張圖片的頁碼和文字提示
//文字顯示
_desBg = [[UIView alloc] initWithFrame:CGRectMake(0, kScreenHeight -  85, kScreenWidth, 35)];
_desBg.backgroundColor = [UIColor colorWithWhite:0 alpha:0.4];
[self addSubview:_desBg];
    
_desLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 0, kScreenWidth - 20, 35)];
_desLabel.backgroundColor = [UIColor clearColor];
_desLabel.textColor = [UIColor whiteColor];
_desLabel.font = [UIFont systemFontOfSize:13];
_desLabel.textAlignment = NSTextAlignmentLeft;
_desLabel.numberOfLines = 2;
_desLabel.userInteractionEnabled = NO;
[_desBg addSubview:_desLabel];
     
//建立頁碼顯示
_pageCountLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, kScreenHeight -  50, kScreenWidth, 50)];
_pageCountLabel.backgroundColor = [UIColor colorWithWhite:0 alpha:0.4];
_pageCountLabel.textColor = [UIColor whiteColor];
_pageCountLabel.font = [UIFont systemFontOfSize:15];
_pageCountLabel.textAlignment = NSTextAlignmentCenter;
_pageCountLabel.userInteractionEnabled = NO;
[self addSubview:_pageCountLabel];
滑動時每張圖片的頁碼變化此處我用通知來實現
//接受通知方法
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(PageChangeAction:) name:@"PageChangeAction" object:nil];
- (void)PageChangeAction:(NSNotification *)text {
    NSString *str = text.userInfo[@"nowPage"];
   _pageCountLabel.text = [NSString stringWithFormat:@"%li/%lu",[str integerValue] + 1,(unsigned long)_images.count];
    if (_descriptionArr.count > 0) {
        NSString *desStr = _descriptionArr[[str integerValue]];
        if ((NSNull *)desStr != [NSNull null] && desStr != nil) {
            _desLabel.text = desStr;
            _desBg.hidden = NO;
        }else{
            _desBg.hidden = YES;
        }
    }else{
        _desBg.hidden = YES;
    }
}
4、子類化UICollectionViewCell,在cell上新增滑動檢視UIScollView,用UIScollview盛放圖片,用於實現圖片的拉伸放大,旋轉,儲存等功能。

在UICollecionViewCell中新增 PhotoScollView,PhotoScollView繼承自UIScolloview,用於放置圖片。

//子類化滑動檢視
scrollView = [[PhotoScrollView alloc] initWithFrame:self.bounds];    
[self.contentView addSubview:scrollView];

5、PhotoScollView的實現

此處我只添加了單擊手勢和雙擊手勢,單擊是傳送通知隱藏滑動檢視,雙擊是放大圖片或者縮小圖片。因為同時涉及單擊和雙擊,所以要處理單擊和雙擊的衝突。這裡的處理方法是雙擊手勢觸發時,讓單擊手勢暫時失效 [singleTap requireGestureRecognizerToFail:doubleTap];

- (id)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if (self) {
        self.showsVerticalScrollIndicator = NO;
        self.showsHorizontalScrollIndicator = NO;
        //子檢視
        imageView = [[UIImageView alloc] initWithFrame:self.bounds];
        //等比例放大
        imageView.contentMode = UIViewContentModeScaleAspectFit;
        [self addSubview:imageView];

        //指定代理
        self.delegate = self;
        
        //縮放倍數
        self.maximumZoomScale = 3;
        self.minimumZoomScale = .5;

        //雙擊手勢
        UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTapAction:)];
        
        //設定手指的數量
        doubleTap.numberOfTouchesRequired = 1;
        //點選的數量
        doubleTap.numberOfTapsRequired = 2;
        //將手勢新增到滑動檢視上
        [self addGestureRecognizer:doubleTap];
        
        //單擊手勢
        UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapAction)];
        [self addGestureRecognizer:singleTap];
        
        //雙擊手勢觸發時,讓單擊手勢暫時失效
        [singleTap requireGestureRecognizerToFail:doubleTap];
    }
    return self;
}

- (void)setImageUrl:(NSString *)imageUrl{
    
    //填充資料
    //[imageView sd_setImageWithURL:[NSURL URLWithString:imageUrl]];
    imageView.image = [UIImage imageNamed:imageUrl];
}

#pragma mark UITapGestureRecognizer

//單擊手勢
- (void)singleTapAction{
    
    //傳送通知結束瀏覽
    [[NSNotificationCenter defaultCenter] postNotificationName:@"HideShowViewNotification" object:nil];
    
}

//雙擊呼叫的方法
- (void)doubleTapAction:(UITapGestureRecognizer *)tap{
    
    if (self.zoomScale != 1) { //不是正常倍數
        
//        self.zoomScale = 1; //還原
        [self setZoomScale:1 animated:YES];
    }else{
    
//        self.zoomScale = 3;
        [self setZoomScale:3 animated:YES];
    
    }
}

#pragma mark UIScrollViewDelegate
//返回放大的檢視
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
    return imageView;
}
6、有待完善的地方

放大後的圖片和放大前的圖片不應該是同一張,放大前應該用縮圖,節約流量,提高顯示速度,放大後應該用大圖,展示清晰圖片。並且真實專案中應該考慮圖片快取等問題。

三、demo連結

相關推薦

iOS學習圖片放大滑動瀏覽

iOS許多APP中都使用到了圖片放大瀏覽的功能,如淘寶、微信等。最近也琢磨了一些方法,基本可以實現點選圖片放大,並且可以左右滑動瀏覽上一張下一張圖片,也可以通過手勢撐開放大縮小,可以加上長按儲存到相簿的功能。具體的做法是子類化UIImageView,新增點選手勢,監聽手勢

IOS自定義圖片瀏覽器支援瀏覽多張圖片點選雙擊兩手指縮放操作並顯示載入進度條

圖片瀏覽器Controller的主要思路是:新建一個 JZAlbumViewController,在這個controller裡主要顯示一個UIScrollView,這個UIScrollView用來顯

IOS學習常見問題】蘋果開發者協議更新後【Edit Phone Number】跳不出同意按鈕(紅色的警告)

█ 問題:  ● 蘋果開發者協議更新後,跳不出同意按鈕  ● 有提示需要編輯手機號碼(以前沒填寫),修改後還是一樣  ● 部分人換了好幾張手機卡測試(和運營商沒關係),結果還是一樣  ● 部分人反應,在4月21號操作,可以成功,之後操作的就沒成功 

IOS學習UiTableView仿個人中心頁面據說學會這個控制元件就能裝逼了(二)

蘋果電腦真心不習慣啊,一邊開發使windows一邊是Mac 都不知道按鍵盤哪個鍵了。這UiTableView根android ListView一樣重要,等學會這個以後我就出去裝逼,但願裝逼不要被大神鄙視,哎,沒辦法,半路出家,誰讓我大學學的機械專業,還這麼笨的!如果人生能出

ios學習旅---指針也不難

ror 邏輯 初始化 維數 賦值運算 等價 格式 沒有 本質 1、認識指針#include <stdio.h> //基本數據類型作為函數參數傳遞是值傳遞 //void moveFront(int x ,int y) //{ // x = x + 2;

ios學習旅--oc對象的關系

pos 其它 對象 found self 面向對象設計原則 ipa 匿名 nsstring 1.匿名對象:就是沒有名字對象 1、匿名對象僅用一次 使用場景: 1、當我們僅僅要調用一個對象的某個方法一次的時候能夠使用匿名對象 2

java mybatis學習$和#區別mapper代理接口動態SQL在日誌中輸出mybatis的sql語句

except 控制臺 處理方式 ron target 技術分享 需要 prefix job 1.在mybatis中,$和#的區別: #{}:表示一個預處理參數,參數類型不定,是根據傳入的參數類型來設定的。類似於JDBC中的? 特例使用,模糊查詢:(針對oracle): an

深度學習圖片壓縮算法

深度學習、圖片壓縮近年來,深度學習在計算機視覺領域已經占據主導地位,不論是在圖像識別還是超分辨重現上,深度學習已成為圖片研究的重要技術;現在深度學習技術已進入圖片壓縮領域。以圖鴨科技最新研發的圖片壓縮——Tiny Network Graphics (TNG) 為例,其以深度學習卷積神經網絡為內核,在保持相同圖

springmvc學習jdk版本tomcat版本spring版本

使用的軟體是myeclipse2018,jdk8,tomcat9.0,spring3.2.0 以上為我的軟體及各種配置 1.建立了web工程,build path 使用的是預設的j2EE1.8(只有配置了jdk8之後才能使用) 2.執行工程的時候jdk的版本只能     

Python學習圖片對比和識別小記

因工作中需要對視訊圖片做處理,於是就把應用得到的幾個需求功能在網上solo了一波。 一、圖片對比 主要應用的庫Image,函式Image.size(),resize(),convert(),getpixel(), 1、根據R-G -B三原色原理: 只要使R=G=B,三者的值相等就可以

點選圖片放大再點選縮小的程式碼段

這段js還挺常用,特此記錄。 1 <form> 2   <div> 3 <div class="form-group left"> 4 <label for="imgs" class="col-sm-3 cont

React-Native學習 圖片做背景 modal 點選其他區域消失

1.modal點選其他區域消失 <TouchableWithoutFeedback onPress={()=>this.setState({showTopMenu:false})}> <View style={{position:

opengl學習路七攝像機

前面的教程中我們討論了觀察矩陣以及如何使用觀察矩陣移動場景(我們向後移動了一點)。OpenGL本身沒有攝像機(Camera)的概念,但我們可以通過把場景中的所有物體往相反方向移動的方式來模擬出攝像機,產生一種我們在移動的感覺,而不是場景在移動。 本節我們將會討

opengl學習路二你好三角形

譯註 在學習此節之前,建議將這三個單詞先記下來: •頂點陣列物件:Vertex Array Object,VAO •頂點緩衝物件:Vertex Buffer Object,VBO •索引緩衝物件:Element Buffer Object,EBO或Index

opengl學習路一你好視窗

QQ:609162385 連結:https://blog.csdn.net/cqltbe131421 讓我們試試能不能讓GLFW正常工作。首先,新建一個.cpp檔案,然後把下面的程式碼貼上到該檔案的最前面。 #include <glad/glad.h>

opengl學習路九基礎光照

QQ:609162385 連結:https://blog.csdn.net/cqltbe131421 現實世界的光照是極其複雜的,而且會受到諸多因素的影響,這是我們有限的計算能力所無法模擬的。因此OpenGL的光照使用的是簡化的模型,對現實的情況進行近似,這樣處

opengl學習路三著色器

QQ:609162385 連結:https://blog.csdn.net/cqltbe131421 在Hello Triangle教程中提到,著色器(Shader)是執行在GPU上的小程式。這些小程式為圖形渲染管線的某個特定部分而執行。從基本意義上來說,著色器

opengl學習路六座標系統

QQ:609162385 下載連結:https://download.csdn.net/download/cqltbe131421/10703034 在上一個教程中,我們學習瞭如何有效地利用矩陣的變換來對所有頂點進行變換。OpenGL希望在每次頂點著色器執行後

HTML5-從0開始學習HTML5標籤屬性與元素之間的關係

上次我介紹了HTML5的結構,如下圖所示 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewpo

2018年11月13日Java學習包裝類裝箱與拆箱

1.將八種基本資料型別定義相應的引用型別—包裝類 這樣做的好處就是可以呼叫類的方法了。 2.裝箱與拆箱 裝箱 int i = 500; Integer t = new Integer(i); 拆箱 boolean b = bObj.booleanValue