IOS UISCrollView 新手指引 (一個照片的操作)

原文: appcoda.com (IOS Beginner's Guide to UIScrollView 由joyce echessa發(fā)布
翻譯: 安明哲
說明: 轉(zhuǎn)載時請注明出處

在IOS中框杜,scroll view 本用作顯示屏幕上不能完全裝下的內(nèi)容。它主要有兩個作用:

  • 用戶可以通過拖動的方式顯示更多內(nèi)容
  • 用戶可以通過手勢縮放現(xiàn)實的內(nèi)容

IOS的公共控件UITbaleView就是繼承與UIScrollView并提供了一種不錯的方式去呈現(xiàn)內(nèi)容(當(dāng)這個內(nèi)容大于屏幕尺寸)

在本節(jié)課程中蛔添,我們將從多方面了解ScrollView茫藏,特性尤勋,創(chuàng)建一個ScrollView(通過代碼和通過Interface Builder)凑懂,滾動和縮放盒齿,insets和outsets成福。


開始閱讀之前芳肌,請首先下載本屆課程的源代碼灵再。

譯者注:
這里的下載需要自帶梯子肋层,如果沒有梯子,可以從我的服務(wù)器獲取

通過編碼方式創(chuàng)建ScrollView

不管是通過代碼或者Interface builder都可以在一個view中創(chuàng)建一個Scroll View翎迁,然后做一點點必要的配置就實現(xiàn)一個基本的ScrollView的功能了栋猖。

  • 你必須設(shè)置 ContentSize 屬性,此屬性用于指定你要展現(xiàn)的內(nèi)容的Size鸳兽,IOS由此確認滾動區(qū)域掂铐。
  • 你還必須添加一個或者多個View以供顯示。

當(dāng)然揍异,還有許多可選的配置全陨,垂直或是水平滾動,滑動衷掷、縮放的效果辱姨,滾動條的路徑(滾動的方向)等等。

現(xiàn)在戚嗅,我們開始通過代碼創(chuàng)建一個ScrollView雨涛,打開 ScrollViewDemo(剛才下載的項目),僅僅是一個簡單地Signle View懦胞,其中ScollerViewController這個類與Interface Builder中的UIViewController關(guān)聯(lián)替久,并且此項目還包含了一張圖片image.png (圖片來自unsplash.com)

打開ScrollViewController.swift 并且添加如下代碼:

var scrollView: UIScrollView!
var imageView: UIImageView!

修改 viewDidLoad() 如下:

override func viewDidLoad() {
    super.viewDidLoad()
       
    imageView = UIImageView(image: UIImage(named: "image.png"))
        
    scrollView = UIScrollView(frame: view.bounds)
    scrollView.backgroundColor = UIColor.blackColor()
    scrollView.contentSize = imageView.bounds.size
   //譯者注:如果你是用的是swift2.x 這行代碼會出現(xiàn)問題
   scrollView.autoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight
        
    scrollView.addSubview(imageView)
    view.addSubview(scrollView)
}

譯者注
上面的代碼中帶注釋的一行會在swift2下報錯,在swift2.0中同時取得兩個枚舉值不再支持使用 | 運算符躏尉,而改用數(shù)組 蚯根,所以swift2中正確的代碼應(yīng)該是這個樣子
scrollView.autoresizingMask = [UIViewAutoresizing.FlexibleHeight,UIViewAutoresizing.FlexibleWidth]

上面的代碼創(chuàng)建了一個scroll view和一張圖片。其中ImageView是ScrollView的子view(有點繞)胀糜;contentSize指定了可滾動的地帶為圖片的大新埂(2000 x 1500);scrollView的背景為黑色教藻,設(shè)置autoresizeMask為.FlexibleWidth和 .FlexibleHeight以便于在屏幕旋轉(zhuǎn)的時候scrollview與parsentView維持正確位置關(guān)系距帅。運行這個app的時候你應(yīng)該能夠圖片的沒一部分。

當(dāng)你運行的時候括堤,你可能會注意到碌秸,通常你只能看到圖片左上角的那一部分,就像下面這樣:


這是因為scrollview的bound(默認)被設(shè)置為(0痊臭,0)哮肚,也就是圖片的左上角。如果你希望重新定位第打開app時圖片的顯示位置广匙,你需要改變scrollview的bound,SrollerView有一個contentOffset屬性可以幫助你實現(xiàn)這個需求恼策。

添加如下代碼到你的代碼中鸦致,(注意這段代碼應(yīng)該在autoresizingMask之后):

scrollView.contentOffset = CGPoint(x: 1000, y: 450)

這個時候再次運行app你將看到scrollview已經(jīng)移動到圖皮的另一部分潮剪,這樣當(dāng)view被加載的時候,你就可以確定你要給用戶呈現(xiàn)什么分唾。

縮放

我們已經(jīng)創(chuàng)建了一個scrollview并且允許用戶通過滾動來控制一個較大尺寸的view抗碰,但是如果視圖可以縮放,將進一步增強用戶體驗绽乔。

要支持縮放弧蝇,你必須為view添加一個delegate,這個delegate必須遵從IScrollViewDelegate這個協(xié)議折砸,并且必須要實現(xiàn)viewForZoomingInScrollView()看疗,該方法返回一個view,這個view將可以在scrollview內(nèi)縮放睦授。

你依舊要做一點點的工作來支持縮放两芳,你可以設(shè)置scrollvierw的 minimumZoomScale 和 maximumZoomScale屬性(如果不設(shè)定這兩個屬性,他們將會有一個默認值-->1.0)

修改ScrollerView的定義如下:

class ScrollViewController: UIViewController, UIScrollViewDelegate

然后添加如下方法到類中:

func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
        return imageView
    }

最后去枷,添加如下代碼到viewDidLoad()的底部:
譯者注:主要就是綁定delegate,設(shè)置縮放的范圍和步長

scrollView.delegate = self
scrollView.minimumZoomScale = 0.1
scrollView.maximumZoomScale = 4.0
scrollView.zoomScale = 1.0

上面的代碼中設(shè)置了zoomScale為1.0用于指定最大縮放和最小縮放的縮放因子(默認情況下縮放的大胁懒尽),當(dāng)你運行app删顶,你可以滾動并且縮放竖螃,我們設(shè)置最大縮放比例4.0,所以你最大可以放大這張圖片到原始尺寸的4倍(最小縮放比例同理)逗余,但是當(dāng)我們把圖片放大的時候特咆,圖片會變得很很模糊,這并不是用戶想要看到的猎荠,下一步中我們將讓圖片返回到1.0初始的狀態(tài)坚弱。

在上邊,我們設(shè)置minimumZoomScale為0.1以至于縮小之后返回一個很小的圖片并且屏幕中出現(xiàn)了很多空白关摇。我們想讓圖片自適應(yīng)

要實現(xiàn)這個功能荒叶,我們需要根據(jù)scrollview的size和imageview的size計算最小縮放比例。

首先刪除viewDidLoad里面的幾行代碼:

scrollView.minimumZoomScale = 0.1
scrollView.maximumZoomScale = 4.0
scrollView.zoomScale = 1.0

添加一個方法到類中输虱,我們得到的寬度和高度的比例些楣,并選擇較小的兩者,并設(shè)置為minimumScale宪睹。提示一下愁茁,我們刪除了maxinmumZoomScale,所以他會被默認設(shè)置為1.0.

func setZoomScale(){
        let imageViewSize = imageView.bounds.size
        let scrollViewSize = scrollView.bounds.size
        let widthSacle = scrollViewSize.width / imageViewSize.width
        let heightSacle = scrollViewSize.height / imageViewSize.height
        
        scrollView.minimumZoomScale = min(widthSacle, heightSacle)
        scrollView.zoomScale = 1.0
    }

然后再viewDidLoad()中調(diào)用這個方法

setZoomScale()

同時添加以下代碼亭病,以便在設(shè)備方向改變后圖像依舊鋪滿屏幕鹅很。

    override func viewWillLayoutSubviews() {
        setZoomScale()
    }


從上面的圖片中,你可能會注意到罪帖,圖片的位置在屏幕左上角促煮,我們想改變他到屏幕的中心邮屁。

添加如下方法到類中:

func scrollViewDidZoom(scrollView: UIScrollView) {
    let imageViewSize = imageView.frame.size
    let scrollViewSize = scrollView.bounds.size
        
    let verticalPadding = imageViewSize.height < scrollViewSize.height ? (scrollViewSize.height - imageViewSize.height) / 2 : 0
    let horizontalPadding = imageViewSize.width < scrollViewSize.width ? (scrollViewSize.width - imageViewSize.width) / 2 : 0
        
    scrollView.contentInset = UIEdgeInsets(top: verticalPadding, left: horizontalPadding, bottom: verticalPadding, right: horizontalPadding)
}

這個方法會在每次一縮放操作后執(zhí)行,它告訴delegate菠齿,scrllowView的縮放比例發(fā)生了改變佑吝,上面的代碼計算了padding并且根據(jù)padding重新設(shè)置了scrollview 內(nèi)容的padding

此時,運行app縮放到最小是 將得到如下效果

通過連按縮放

默認情況下ScrollView通過少量的代碼即可實現(xiàn)支持縮放(捏和撐)手勢绳匀,但是支持更多的手勢我們則需要再做一些工作芋忿。

IOS人機交互的借口定義了一種通過雙擊(連按)來進行縮放的方法。但是這個方法認為view的縮放級別是單一的(翻譯起來有點繞)總之就是雙擊一次執(zhí)行了放大操作后下一次會默認執(zhí)行縮小操作疾棵。但是很多程序的交互行為是需要更靈活的雙擊縮放的戈钢,比如地圖應(yīng)用,需要不停地雙擊放大陋桂,而不是放大后再雙擊變成縮小逆趣。

在我們app中,我們將實現(xiàn)double-tap 把圖片放到最大嗜历,而后雙擊再縮小

添加如下代碼到類中:

func setupGestureRecognizer() {
    let doubleTap = UITapGestureRecognizer(target: self, action: "handleDoubleTap:")
    doubleTap.numberOfTapsRequired = 2
    scrollView.addGestureRecognizer(doubleTap)
}
    
func handleDoubleTap(recognizer: UITapGestureRecognizer) {
        
    if (scrollView.zoomScale > scrollView.minimumZoomScale) {
        scrollView.setZoomScale(scrollView.minimumZoomScale, animated: true)
    } else {
        scrollView.setZoomScale(scrollView.maximumZoomScale, animated: true)
    }
}

然后再viewDidLoad底部調(diào)用他們:

setupGestureRecognizer()

在上面的代碼中宣渗,我們添加了一個gesture recognize(手勢識別器),當(dāng)用戶雙擊之后梨州,我們可以根據(jù)當(dāng)前的縮放級別來進行放大和縮小痕囱。
這樣,我們就可以通過雙擊放大和縮小圖片了暴匠。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鞍恢,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子每窖,更是在濱河造成了極大的恐慌帮掉,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件窒典,死亡現(xiàn)場離奇詭異蟆炊,居然都是意外死亡,警方通過查閱死者的電腦和手機瀑志,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進店門涩搓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人劈猪,你說我怎么就攤上這事昧甘。” “怎么了战得?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵充边,是天一觀的道長。 經(jīng)常有香客問我常侦,道長痛黎,這世上最難降的妖魔是什么予弧? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任刮吧,我火速辦了婚禮湖饱,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘杀捻。我一直安慰自己井厌,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布致讥。 她就那樣靜靜地躺著仅仆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪垢袱。 梳的紋絲不亂的頭發(fā)上墓拜,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天,我揣著相機與錄音请契,去河邊找鬼咳榜。 笑死,一個胖子當(dāng)著我的面吹牛爽锥,可吹牛的內(nèi)容都是我干的涌韩。 我是一名探鬼主播,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼氯夷,長吁一口氣:“原來是場噩夢啊……” “哼臣樱!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起腮考,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤雇毫,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后踩蔚,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體棚放,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年寂纪,在試婚紗的時候發(fā)現(xiàn)自己被綠了席吴。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡捞蛋,死狀恐怖孝冒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情拟杉,我是刑警寧澤庄涡,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站搬设,受9級特大地震影響穴店,放射性物質(zhì)發(fā)生泄漏撕捍。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一泣洞、第九天 我趴在偏房一處隱蔽的房頂上張望忧风。 院中可真熱鬧,春花似錦球凰、人聲如沸狮腿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽缘厢。三九已至,卻和暖如春甩挫,著一層夾襖步出監(jiān)牢的瞬間贴硫,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工伊者, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留英遭,地道東北人。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓删壮,卻偏偏與公主長得像贪绘,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子央碟,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,440評論 2 348

推薦閱讀更多精彩內(nèi)容