iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 30
1
自我挑戰組

Hey! UIKit, 做個朋友吧~系列 第 30

Day 30: 終於結束的起點-UIScrollView

今天是UIScrollView的完結篇,同時也是鐵人賽的完結篇。
沒想到竟然能在這3天把UIScrollView給寫完,在最後一天收尾。
喜歡這種剛剛好的小確幸,有點感動QQ

Indicator

indicatorStyle指定了scroll bar的顏色,有白跟黑和default三種(看起來像半透明的黑色)。

showsHorizontalScrollIndicator和showsVerticalScrollIndicator決定了水平和垂直的scroll bar要不要顯示,預設值都是true。

而flashScrollIndicators()會讓scroll bar閃一下,apple建議當你讓scroll view成為first responder的當下都應該要呼叫這個function。

@objc func changeBackgroundAction(_ sender: UIButton) {
    if backgroundView.backgroundColor == UIColor.white {
        backgroundView.backgroundColor = UIColor.black
        newScrollView.indicatorStyle = .white
        newScrollView.flashScrollIndicators()
    } else {
        backgroundView.backgroundColor = UIColor.white
        newScrollView.indicatorStyle = .black
        newScrollView.flashScrollIndicators()
    }
}

Refresh

refreshControl是一個property,讓scroll view連結一個UIRefreshControl。
不過什麼是UIRefreshControl呢?有時當使用者將scroll view往最上端拉爆,就會出現如下圖的loading小圈圈,並且在圈圈結束後更新頁面。

(圖片來源:UIRefreshControl)

而這個東西94UIRefreshControl,他是UIControl的子類別...太太我不認識你啊O__O
為什麼我寫完了UIControl一家卻還有未知成員的存在?

後來才發現,網路上能找到的UIKit Class Hierarchy Chart都舊到一個不行,包括我Day 01貼的那張。
為了不要讓其他人也有打完boss還不知道有漏網之魚的情況發生,也為了前後呼應,我整理了一張新的繼承圖。

UIKit Class Hierarchy Chart

是說這張表被大學長嗆了,因為就只是一張把繼承關係全部串在一起的表,哈哈哈,所以鐵人賽之後(也就是今天O__O)會再對這張表進行分類處理,還請各位大神們手下留情理性勿戰啊~

Scrolling to a Specific Location

使用scrollRectToVisible(_:animated:)指定一個CGRect,並捲動scroll view使指定的範圍是可視的。
這個function的效果跟之前的捲動scroll view很像,只不過之前是指定原點的offset,而這個function是指定一個矩形區塊。另外如果指定的區塊已經是可視的,則此function不會作用。

@objc func changeBackgroundAction(_ sender: UIButton) {
    newScrollView.scrollRectToVisible(CGRect(x: 1000, y: 0, width: 300, height: 700), animated: true)
}

Touches

Begin

當使用者點擊螢幕時,scroll view會傳送UITouch(點擊的位置、力道等資訊)、UIEvent以及被點選的UIView給touchesShouldBegin(_:with:in:)並呼叫該function,回傳值為Bool。
可以在子類別覆寫這個function以客製點擊後的響應行為,如果你不希望scroll view傳送任何event給被點擊的view可以回傳false,預設值為true。

delay / cancel

先前有提到scroll view有一個機制,去追蹤使用者到底是想要捲動還是點擊。當使用者觸碰螢幕之後,scroll view會先攔截touchDown的UIEvent並且啟動一個nonrepeating timer,timer失效後scroll view會去偵測點擊位置是否有顯著的移動。
而delaysContentTouches及canCancelContentTouches決定了這個機制是否生效。

如果delaysContentTouches為true,則在使用者點擊螢幕之後就會開始攔截touchDown,預設值為true。你同樣也可以呼叫這個方法攔截event,直到使用者有顯著的移動手勢為止。

如果canCancelContentTouches是true,則在使用者點擊並拖曳一小段距離後會呼叫touchesShouldCancel(in:),如果touchesShouldCancel(in:)的回傳值是true的話就會取消touch event並開始拖拉。預設UIControl的子類別回傳true,其餘是false。
而如果canCancelContentTouches是false的話只要使用者在點擊的當下沒有滾動螢幕,scroll view就會馬上發出tracking event給被點擊的物件,只要tracking一開始,使用者再怎麼移動手指畫面也不會捲動。

Panning / Zooming

Pan And Pinch

當使用者對scroll view做出拖曳手勢的時候,scroll view為了更精準控制會呼叫panGestureRecognizer這個property,取得UIPanGestureRecognizer。而做出縮放手勢的時候會呼叫pinchGestureRecognizer,取得UIPinchGestureRecognizer。
兩者都是get-only property。

Zoom

當使用者作出縮放手勢之後,isZooming會變為true(平時為false),scroll view的content view會被傳送給viewForZooming(in:)等待縮放,並傳送content view的CGRect給zoom(to:animated:)來處理縮放的行為。
需同時定義zoom scale。

Zoom Scale

zoomScale是個顯示目前縮放比例的浮點數,預設值為1.0。而setZoomScale(_:animated:)可以為content view設置一個新的縮放比例,此值要介於maximumZoomScale及minimumZoomScale之間,而這2個property的預設值也是1.0。

bounce

scroll view在default的情況下拖拉到邊界時會出現反彈的動畫,而這個動畫在縮放到maximum/minimum zoom scale的同時也會出現。
可以用bouncesZoom這個property來決定是否有反彈的動畫,預設值為true。
在bouncesZoom的值為true的時候,反彈動畫發生時isZoomBouncing的值會轉為true,平時為false。

Keyboard

keyboardDismissMode決定鍵盤會不會因捲動手勢收起。為property指定一個UIScrollView.keyboardDismissMode的enum來實現,預設是none。
onDrag是scroll view一捲動就收起,而interactive則是當使用者觸碰到鍵盤後,鍵盤會隨使用者的手勢移動:

newScrollView.keyboardDismissMode = .interactive

Index

indexDisplayMode決定了index在scroll view捲動時顯示的方式。為property指定一個UIScrollView.IndexDisplayMode的enum來實現,預設是automatic,也就是index會自動顯示或隱藏,另外還有alwaysHidden可以選擇。

那UIScrollView跟鐵人賽就在這裡告一個段落了。
雖然鐵人賽結束了,不過這只是前往下一個目標的起點。
明天的我,也會繼續前進的吧!

p.s. 想感性的話比看文件還難。


上一篇
Day 29: 來玩拉和服腰帶轉圈圈吧UIScrollView
系列文
Hey! UIKit, 做個朋友吧~30

2 則留言

0
Howard
iT邦新手 5 級 ‧ 2019-10-16 21:59:03

賀完賽/images/emoticon/emoticon64.gif

0
阿展展展
iT邦好手 1 級 ‧ 2020-01-03 05:41:20

恭喜完賽/images/emoticon/emoticon42.gif 示範的 git 都好精美/images/emoticon/emoticon24.gif

我要留言

立即登入留言