UISegmentedControl: 可以不要污名化我嗎+_+?
邊緣人:怕豹.jpg
segmented control(分段控制器),可以使title或image甚至是其他view在不同的分段中有不同的顯示。對應的UIEvent為valueChange。
早期如果segmented只有2個的話會變得跟switch一樣,只要輕觸被選取的segmented就會切換到另一segmented,而這在iOS 3.0之後被改掉了。
首先先初始化一個UISegmentedControl實體...都講幾百次了啊~
不過比較特別的是UISegmentedControl是可以客製化的,可以在初始化時指定一個[Any]作為Segmented的內容,例如我們先建立一個UIImage的陣列
let segmentedContent = [UIImage(named: "finn"), UIImage(named: "jack"), UIImage(named: "beemo"), UIImage(named: "princessBubblegum"), UIImage(named: "marceline"), UIImage(named: "iceKing")]
再把這個陣列於初始化時指定給segmentedControl:
let newSegmentedControl = UISegmentedControl(items: segmentedContent as [Any])
我的segmentedControl就會變成...
啊咧@__@我的活寶照片怎麼變成剪影了
點擊的時候還會反白耶哈哈哈
segmented的內容可以是字串也可以是圖片,除了剛剛用陣列的方式指定以外,也可以利用以下方法設定:
newSegmentedControl.setTitle("A", forSegmentAt: 0)
newSegmentedControl.setImage(UIImage(named: "finn"), forSegmentAt: 1)
newSegmentedControl.setTitle("B", forSegmentAt: 2)
newSegmentedControl.setImage(UIImage(named: "jack"), forSegmentAt: 3)
newSegmentedControl.setTitle("C", forSegmentAt: 4)
newSegmentedControl.setImage(UIImage(named: "princessBubblegum"), forSegmentAt: 5)
順帶一提,segmented的index是zero base。
segment可以設定文字跟圖片,也可以把他們叫出來:
segmentedImageView.image = newSegmentedControl.imageForSegment(at: 1)
segmentedTitle.text = newSegmentedControl.titleForSegment(at: 4)
原來第2張圖片是阿寶啊~
另外也可以使用numberOfSegments回傳segment的個數。
綜合以上所學,我們就可以寫個簡單的action,在不同的segment下指定相對應的圖片,印出最一開始初始化的segmentedControl的圖案。
@objc func segmentChange(_ sender: UISegmentedControl) {
switch newSegmentedControl.selectedSegmentIndex {
case 0...newSegmentedControl.numberOfSegments-1:
segmentedImageView.image = newSegmentedControl.imageForSegment(at: newSegmentedControl.selectedSegmentIndex)
default:
break
}
}
segment可以在指定的索引位置裡增加分段:
newSegmentedControl.insertSegment(with: UIImage(named: "marceline"), at: 0, animated: true)
如圖所示,我們在索引位置0的部分加入了艾薇兒的圖片。
而imageView跟label是在插入前指定的,所以還是顯示C跟阿寶的圖片,並沒有被插入segment的動作所影響。
順帶一提,如果要插入文字的話,要用insertSegment(withTitle: at: animated:)這個function。
也可以移除指定索引值的segment:
newSegmentedControl.removeSegment(at: 3, animated: true)
或是用removeAllSegments()移除整個segmentedControl
如果segmentedControl的isMomentary為true的話,被選取的segmented就不會一直反白,而只在被選取的當下閃一下:
如果不清楚當前選取的segment為哪一個的話,可以使用selectSegmentIndex回傳當前的索引值(剛剛為了範例好像已經不小心劇透了)。
segmentedControl還可以讓某個segment失效,方法如下:
newSegmentedControl.setEnabled(false, forSegmentAt: 3)
如圖所示,索引值為3的segment變成灰色且無法被選取。
同樣的也可以用isEnabledForSegment(at:)回傳指定索引segment的布林值。
為什麼要對segment的content做offset?我真的快笑死
阿寶回來啊~~~~
實作的程式碼如下:
newSegmentedControl.setContentOffset(CGSize(width: 10, height: 10), forSegmentAt: 1)
同樣可以用contentOffsetForSegment(at:)回傳當前索引值offset的CGSize。
一般segment的寬度都是由segment均分segmentedControl的總寬,如果要對其中一個segment做調整的話做法如下:
newSegmentedControl.setWidth(30, forSegmentAt: 3)
如此一來只有被指定的segment寬度不一樣,其他segment均分剩下的寬度。同樣可以用widthForSegment(at:)來回傳指定索引segment的寬度。
而如果apportionsSegmentWidthsByContent是true的話,segment的寬度就會依內容調整。
如下圖字串的寬度依內容調整,剩下的寬度被圖片segment均分之後再拉長圖片就成了這副鬼樣子,實在是太好笑了XD
customize裡有4組function,跟之前一樣有分set跟get。
可以設定整條segmentedControl的背景圖片。
要注意的是如果設定了selected的的背景圖片,一定要同時設定normal狀態下的,不然他如果沒有圖片可以切換的話就會無法顯示。
newSegmentedControl.setBackgroundImage(UIImage(named: "finn"), for: .normal, barMetrics: .default)
newSegmentedControl.setBackgroundImage(UIImage(named: "jack"), for: .selected, barMetrics: .default)
如圖我設定整段segmentedControl的背景圖片為阿寶,但被我點選的segment會切換成selected state,就會顯示老皮的圖片。
一樣可以使用backgroundImage(for:barMetrics:)取出不同state的背景圖片。
這個function顧名思義就是調整segment內容的位置,一樣可以用contentPositionAdjustment(forSegmentType:barMetrics:)回傳一個UIOffset
newSegmentedControl.setContentPositionAdjustment(UIOffset(horizontal: 10, vertical: 10), forSegmentType: UISegmentedControl.Segment(rawValue: 0)!, barMetrics: .default)
有個搞不太清楚的新發現是:rawValue決定了offset的segment,但不知道為何這樣定義。
0:全部segment內容offset
1:只有第一個會offset
2:除第一個和最後一個之外,其他offset
3:只有最後一個offset
4之後這個function對segment都沒有影響,沒有segment會offset。
divider設定了一個image來取代分隔線,用dividerImage(forLeftSegmentState:rightSegmentState:barMetrics:)取出image。
newSegmentedControl.setDividerImage(UIImage(named: "dot"), forLeftSegmentState: .selected, rightSegmentState: .selected, barMetrics: .default)
不過神奇的是,我state不管怎麼改,segment怎麼選都不會有變化QQstate到底是幹嘛用的啊
text attributes客製化了在特定狀態下的title text,
範例設定了在selected的狀態下,title text會變成italic字體並且大小變成50。
newSegmentedControl.setTitleTextAttributes([NSAttributedString.Key.font: UIFont.italicSystemFont(ofSize: 50)], for: .selected)
NSAttributedString.Key裡還有非常多的屬性可以設定,超好玩的!鼓勵大家可以自己試試看。
那UISegmentedControl就到此告一段落了~
下一回即將進入重頭戲UITextField。
看著他洋溢幸福的暖暖文字們,不知道我撐不撐得住啊...