開始使用UIScrollView

本文由Snow(博客)翻譯自APPCODA。
原文: A Beginner’s Guide to UIScrollView
作者: joyce echessa

在iOS裏, scroll views 是用來展示視圖內容不能完全適配屏幕。Scroll views 有兩個重要的目的:

  • 讓用戶把內容拖拽到他想展示的區域
  • 讓用戶通過夾得手勢放大或縮小來展示內容

一個在iOS apps中經常用到的控件UITableView是UIScrollView的子類並且提供了很多方法展示超過屏幕的內容。

在這個教程裏,我們將看到UIScrollView的很多方面,尤其是用代碼或者Interface Builder創建scrollView,滾動、縮放、插入或內嵌scrollView。

在閱讀前,先下載初始項目的包含文件,我們會在教程中使用到。

用代碼創建Scroll View

Scroll views的創建和其他視圖一樣,無論代碼還是Interface Builder。在那之後,只需要很少的配置就可以實現滾動的基礎功能。
Scroll view被創建或插入到控制器裏或其他視圖裏,完成Scroll View的配置只需要兩個附加步驟:

  • 你必須爲滾動內容的size設置 contentSize 屬性,這會指定滾動區域的大小。
  • 你必須爲scroll view添加一個或多個視圖來展示或滾動。這些視圖提供展示內容。

你可以爲你的程序隨意的配置任何可視的提示,像水平垂直滾動指示器,拖動彈跳,縮放彈跳,和滾動的方向約束。
我們從用代碼創建滾動視圖開始。從你下載的文件中打開ScrollViewDemo工程,在故事版中它包含了一個視圖控制器連接到在程序中創建的ScrollViewController。我還包括了一個叫做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
    scrollView.autoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight

    scrollView.addSubview(imageView)
    view.addSubview(scrollView)
}

上面我們創建了一個滾動視圖和一個圖片視圖。圖片視圖是滾動視圖的子視圖。contentSize設置滾動範圍的大小。我們把他設置爲等於圖片的大小(2000 x 1500)。爲了讓圖片有黑色的背景我們把滾動視圖的背景色設爲黑色。我們設置滾動視圖的autoresizingMask(自動變換大小)屬性爲.FlexibleWidth 和 .FlexibleHeight以至於當設備旋轉時可以重新調整他的大小。運行app然後你可以滾動並且看到圖片的不同區域。

這裏寫圖片描述

當你運行app時,你可能會發現圖片的初始位置是在左上角。

這裏寫圖片描述

這是因爲滾動視圖的初始點在(0,0),在左上角。如果你想在app啓動時改變內容展示的位置,那你必須改變滾動視圖的範圍起始點。使用滾動視圖時由於經常需要設置這個位置,你可以改變UIScrollView 的contentOffset屬性來實現和改變初始位置同樣的結果。

在設置滾動視圖的autoresizingMask屬性的語句下,粘貼下面的語句。

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

再一次運行程序,你會看到滾動視圖已經被移動到圖片的另一個部分。這樣你就可以決定當視圖加載時展現在用戶面前的是什麼。

這裏寫圖片描述

縮放

我們添加的滾動視圖使用戶能夠滾動對屏幕來說太大的內容的大部分。這很好,但是如果用戶可以縮放視圖的大小它會變得更好用。

爲了支持縮放,你必須爲你的滾動視圖設置一個委託。這個委託必須遵循UIScrollViewDelegate協議。這個協議必須實現viewForZoomingInScrollView()方法並且返回縮放的視圖。

你也應該指定用戶可以縮放的比例。你通過設置滾動視圖的minimumZoomScale和maximumZoomScale屬性來實現。
他們兩個的默認值都是1.0。

像這樣修改ScrollViewController類的定義。

class ScrollViewController: UIViewController, UIScrollViewDelegate {

然後把下面的方法添加到類裏面。

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

然後在viewDidLoad()的底部添加如下代碼。

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

在上面的代碼中我們把zoomScale設爲1.0,並且指定了縮放係數的最小和最大值。運行程序時,它會以預定的比例係數(比例係數是1.0)開始。當你用兩指夾視圖時,你可以在最大和最小比例係數中上下調整。我們爲maximumZoomScale設置了一個大數(4.0),因此你可以調整圖片到4倍它本身的大小。當你把縮放比例調高時,圖片的大小大於原本的大小,圖片就會變得模糊不清。我們在下一步會把它改回爲默認的1.0 。

這裏寫圖片描述

在上面,我們設置了minimumZoomScale爲0.1,結果圖片變得相當小以至於屏幕周圍留下了很多空白。在風景模式,圖片旁邊的空白處更大。我們想讓圖片適配滾動視圖,讓它佔用足夠大的空間來展示圖片。

這裏寫圖片描述

爲了做到這些,我們會通過滾動視圖和圖片的大小來計算最小比例。

先從viewDidLoad()移除以下三個參數。

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

然後爲類添加下面的方法。我們拿到寬和高的比例並且找出較小的一個,把它設置爲最小縮放比例。注意我們移除了maximumZoomScale的設置,讓它可以恢復默認設置1.0 。

func setZoomScale() {
    let imageViewSize = imageView.bounds.size
    let scrollViewSize = scrollView.bounds.size
    let widthScale = scrollViewSize.width / imageViewSize.width
    let heightScale = scrollViewSize.height / imageViewSize.height

    scrollView.minimumZoomScale = min(widthScale, heightScale)
    scrollView.zoomScale = 1.0
}

然後在viewDidLoad()的結尾調用這個方法。

setZoomScale()

Also add the following so that the image scales right after the user tries to zoom in/out after a device orientation change.
也添加下面的方法,以確保設備改變方向後,用戶可以正確的縮放圖片的比例。

override func viewWillLayoutSubviews() {
    setZoomScale()
}

運行app,現在當你縮放圖片時他會佔用屏幕中足夠的空間。

這裏寫圖片描述

從上面的圖片可以看出,滾動視圖的內容-圖片-是在屏幕的左上角的位置。我們想讓它在屏幕的中間。

在類中添加如下方法。

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)
}

每次縮放動作後這個方法被調用。它告訴委託滾動視圖的縮放係數改變了。在上面的代碼中我們計算了把圖片放在中間需要填充或插入的大小,頂部和底部的值,我們檢查圖片的高是否比滾動視圖小,如果是,填充兩個視圖差值的一半,如果不是,我們把設置爲0.我們對水平方向做了同樣的事情。然後我們設置滾動視圖的contentInset。這是內容視圖從閉合的滾動視圖插入的距離。

運行app,現在當縮放到最小時內容會被放在最中間。

這裏寫圖片描述

點擊縮放

The basic UIScrollView class supports the pinch-in and pinch-out gestures with a little amount of additional code. But supporting a richer zooming experience using tap detection will rquire more work.
基礎的UIScrollView類通過很少的代碼實現夾得手勢,但是用點擊來支持更好的縮放體驗需要更多的工作。
The iOS Human Interface Guidlines defines a double-tap to zoom in and out. This however assumes some constraints: that the view has a single level of zoom (such as in the Photos application where a double tap zooms the content up to the maximum zoom scale and another tap zooms it down to the mimimum),
在iOS Human Interface Guidelines 中定義了兩次點擊實現縮放。這當然假定一些約束條件:
視圖只有一種縮放等級(比如在圖片程序中,兩次點擊會把內容縮放到最大比例,再點擊會把它縮放到最小比例)或者有效地兩次點擊會縮放到最大比例,實現後,下一次兩次點擊會返回滿屏狀態。但是一些程序在處理點擊縮放時需要更靈活的表現,地圖程序就是一個這樣的例子。地圖支持兩次點擊縮放,額外的兩次點擊會縮放的更深。爲了縮放更大的比例,地圖用兩個手指觸摸,當兩個手指貼近到一起時,縮放到最小。

爲了讓你的程序支持點擊縮放功能,你需要在類中實現UIScrollView的委託方法手勢處理viewForZoomingInScrollView() ,這個類有責任追蹤手指的數量和點擊的數量。當它發現單擊、雙擊、點擊兩次,它會因此迴應。在點擊兩次並且有兩個手指點擊時,用代碼實現以恰當比例縮放。

對於我們的程序,我們會執行點擊兩次時,如果當前是最小比例,則縮放到最大,反之縮放到最小。這和你在圖片程序中看到的一樣。

在類中添加下面兩個方法。

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()的底部如下調用。

setupGestureRecognizer()

在上面的代碼中,我們爲滾動視圖添加了一個手勢識別器。它識別用戶在屏幕上點擊兩次,我們處理縮放取決於當前的縮放情況。

運行app,你應該可以通過點擊兩次縮放。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章