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

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

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

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

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

在本節(jié)課程中,我們將從多方面了解ScrollView,特性,創(chuàng)建一個(gè)ScrollView(通過代碼和通過Interface Builder),滾動(dòng)和縮放,insets和outsets。


開始閱讀之前,請(qǐng)首先下載本屆課程的源代碼。

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

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

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

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

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

現(xiàn)在,我們開始通過代碼創(chuàng)建一個(gè)ScrollView,打開 ScrollViewDemo(剛才下載的項(xiàng)目),僅僅是一個(gè)簡單地Signle View,其中ScollerViewController這個(gè)類與Interface Builder中的UIViewController關(guān)聯(lián),并且此項(xiàng)目還包含了一張圖片image.png (圖片來自u(píng)nsplash.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 這行代碼會(huì)出現(xiàn)問題
   scrollView.autoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight
        
    scrollView.addSubview(imageView)
    view.addSubview(scrollView)
}

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

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

當(dāng)你運(yùn)行的時(shí)候,你可能會(huì)注意到,通常你只能看到圖片左上角的那一部分,就像下面這樣:


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

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

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

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

縮放

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

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

你依舊要做一點(diǎn)點(diǎn)的工作來支持縮放,你可以設(shè)置scrollvierw的 minimumZoomScale 和 maximumZoomScale屬性(如果不設(shè)定這兩個(gè)屬性,他們將會(huì)有一個(gè)默認(rèn)值-->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用于指定最大縮放和最小縮放的縮放因子(默認(rèn)情況下縮放的大小),當(dāng)你運(yùn)行app,你可以滾動(dòng)并且縮放,我們?cè)O(shè)置最大縮放比例4.0,所以你最大可以放大這張圖片到原始尺寸的4倍(最小縮放比例同理),但是當(dāng)我們把圖片放大的時(shí)候,圖片會(huì)變得很很模糊,這并不是用戶想要看到的,下一步中我們將讓圖片返回到1.0初始的狀態(tài)。

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

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

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

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

添加一個(gè)方法到類中,我們得到的寬度和高度的比例,并選擇較小的兩者,并設(shè)置為minimumScale。提示一下,我們刪除了maxinmumZoomScale,所以他會(huì)被默認(rèn)設(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)用這個(gè)方法

setZoomScale()

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

    override func viewWillLayoutSubviews() {
        setZoomScale()
    }


從上面的圖片中,你可能會(huì)注意到,圖片的位置在屏幕左上角,我們想改變他到屏幕的中心。

添加如下方法到類中:

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

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

此時(shí),運(yùn)行app縮放到最小是 將得到如下效果

通過連按縮放

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

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

在我們app中,我們將實(shí)現(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()

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

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

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

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