2011~2020全球電影票房冠軍
[iOS App Development]運用UIDatePicker和UISlider來切換顯示內容
10-year challenge,我想我個人絕對會因為不堪回首憤而燒毀這個作業,所以還是改成以10年的全球電影票房冠軍作為主題好了。
這個練習要實作的功能很單純,就是隨著切換Date Picker或Slider上的年份來顯示該年度全球最賣座的電影。資料來源為:
與此次作業相關的細節功能如下:
- Slider的thumb以1年(即整數)來移動,不是連續的。
- Slider滑到的年份會另外顯示出來。
- 在Slider選擇年份會顯示該年的票房冠軍電影。
- Date Picker和Slider相互連動,亦即Slider選擇哪一年Date Picker就跳到相同年份但月日不變,反之亦然。
- 在Date Picker選擇年份會顯示該年度的票房冠軍電影。
其他調整:
- 漸層背景
- 加入自訂字體
- 使用Navigation bar作為標題列
- 調整Slider樣式
前置作業
App啟動的初始畫面為2011年的票房冠軍:
前置作業包括把IBOutlet拉好、資料整理成Dictionary型態、顯示電影資料函式、漸層背景函式、Storyboard調整Date Picker和Slider初始值和範圍。
- IBOutlet如下:
@IBOutlet weak var selectedYearSlider: UISlider!
@IBOutlet weak var selectedYearLabel: UILabel!
@IBOutlet weak var selectedYearDatePicker: UIDatePicker!
@IBOutlet weak var moviePosterImageView: UIImageView!
@IBOutlet weak var chineseTitleLabel: UILabel!
@IBOutlet weak var englishTitleLabel: UILabel!
2. 電影資料Dictionary,以年份作為最上層的key:
let movieInfos = [
"2011":[
"poster": "2011.jpeg",
"chineseTitle": "哈利波特:死神的聖物2",
"englishTitle": "Harry Potter and the Deathly Hallows: Part 2"
],
"2012":[
"poster": "2012.jpeg",
"chineseTitle": "復仇者聯盟",
"englishTitle": "The Avengers"
],
"2013":[
"poster": "2013.jpeg",
"chineseTitle": "冰雪奇緣",
"englishTitle": "Frozen"
],
//2014~2020省略
]
3. 顯示電影資料函式:參數為字串型態的年份,參數year作為key值選取特定年份的電影資料(movieInfo),然後再以不同的key來擷取電影的圖片或中英文電影名稱。由於Dictionary回傳的值都是Optionals型別,故採用if let綁定來處理。
func showMovie(year: String){
if let movieInfo = movieInfos[year]{
if let posterFileName = movieInfo["poster"]{
moviePosterImageView.image = UIImage(named: posterFileName)
}
if let chineseTitle = movieInfo["chineseTitle"]{
chineseTitleLabel.text = chineseTitle
}
if let englishTitle = movieInfo["englishTitle"]{
englishTitleLabel.text = englishTitle
}
}
}
4. 漸層背景函式:
func addGradientLayer(){
let layer = CAGradientLayer()
layer.frame = view.bounds
layer.colors = [
CGColor(red: 4/255, green: 3/255, blue: 3/255, alpha: 1),
CGColor(red: 70/255, green: 17/255, blue: 17/255, alpha: 1),
CGColor(red: 161/255, green: 51/255, blue: 51/255, alpha: 1),
CGColor(red: 236/255, green: 219/255, blue: 186/255 , alpha: 1)
]
layer.locations = [0, 0.5, 0.7, 1]
view.layer.insertSublayer(layer, at: 0)
}
5. Storyboard調整Date Picker和Slider初始值:
Date Picker設定:
Slider設定:
Slider的功能實作
Action connection程式碼,每段說明都在註解中:
@IBAction func changeYearSlider(_ sender: UISlider) {
//將slider的value四捨五入到整數
//因為是改變slider.value本身所以會以整數來變動thumb位置
sender.value.round() //將slider選取的年度改以整數型態儲存起來
let selectedYear = Int(sender.value) //下面的年度label再將selectedYear以字串方式賦值
selectedYearLabel.text = selectedYear.description //與date picker連動
//因為slider變動只會改變date picker的year,所以要先將原本date picker的月日取出
//取出後先存到originalDateComponents
let originalDateComponents = Calendar.current.dateComponents(in: TimeZone.current, from: selectedYearDatePicker.date) //建立格式器來用來創造新的date
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy/MM/dd" //先用字串宣告新的日期,只有年份會更新,月日都代入原本date picker的月日
let newDateString = "\(selectedYear)/\(originalDateComponents.month!)/\(originalDateComponents.day!)"
//將新日期轉換成date物件
let newDate = dateFormatter.date(from: newDateString)
//將date picker的date設定為newDate
selectedYearDatePicker.date = newDate!
//顯示電影資訊
showMovie(year: "\(selectedYear)")
}
Date Picker功能實作
Action connection程式碼:
@IBAction func changeYearDatePicker(_ sender: UIDatePicker) {
//先將date picker的日期轉換為dateComponents物件
let dateComponents = Calendar.current.dateComponents(in: TimeZone.current, from: sender.date) //擷取dateComponents物件的年份後設定到slider的value
//將slider value轉換成整數、字串後再設定到year label的text
if let selectedYear = dateComponents.year {
selectedYearSlider.value = Float(selectedYear)
selectedYearLabel.text = Int(selectedYearSlider.value).description
//顯示電影資訊
showMovie(year: "\(selectedYear)")
}
}
最後在viewDidLoad()中呼叫漸層背景函式,並且embed Navigation Controller、調整元件樣式後就完成了。
Github: