2011~2020全球電影票房冠軍

[iOS App Development]運用UIDatePicker和UISlider來切換顯示內容

10-year challenge,我想我個人絕對會因為不堪回首憤而燒毀這個作業,所以還是改成以10年的全球電影票房冠軍作為主題好了。

這個練習要實作的功能很單純,就是隨著切換Date Picker或Slider上的年份來顯示該年度全球最賣座的電影。資料來源為:

與此次作業相關的細節功能如下:

  1. Slider的thumb以1年(即整數)來移動,不是連續的。
  2. Slider滑到的年份會另外顯示出來。
  3. 在Slider選擇年份會顯示該年的票房冠軍電影。
  4. Date Picker和Slider相互連動,亦即Slider選擇哪一年Date Picker就跳到相同年份但月日不變,反之亦然。
  5. 在Date Picker選擇年份會顯示該年度的票房冠軍電影。

其他調整:

  1. 漸層背景
  2. 加入自訂字體
  3. 使用Navigation bar作為標題列
  4. 調整Slider樣式

前置作業

App啟動的初始畫面為2011年的票房冠軍:

前置作業包括把IBOutlet拉好、資料整理成Dictionary型態、顯示電影資料函式、漸層背景函式、Storyboard調整Date Picker和Slider初始值和範圍。

  1. 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:

--

--