24節氣你都知道嗎?

[iOS App Development]運用Page Control、Segmented Control、button來切換畫面

構思這個作業的時候剛好遇到冬至,就想到了一年四季還有許多各種節氣,自己也想複習一下就選了這個主題。

節氣的英文叫做Solar Term,乍聽之下「節氣」跟星空似乎沒有什麼關係,但四季的變化取決於地球繞著太陽公轉的相對位置,而一個季節中由開始到結束也有不同的氣候,故為「節氣」。每個節氣的名稱都很優雅,搭配上美美的照片,完成品還是讓人看著挺舒服的!

本次實作的功能包括:

  1. 點選Segmented Control切換內容。
  2. 點選向左/向右的button切換內容,可以無止盡循環。
  3. 點選向左/向右的button時Page Control會同步更新。

其他:

  1. 圖片加漸層layer。
  2. 從字體簿加入特定繁體中文字體。

畫面說明

這個App可以透過切換來顯示不同的節氣畫面,初始畫面為顯示春季的第一個節氣:

最上面的Segmented Control可以切換到該季節的第一個節氣,而圖片左右邊的箭號button可以切換季節。

前置作業

前置作業包含宣告需要使用的變數和陣列、建立IBOutlet連結、顯示節氣資料函式和漸層背景函式。

  1. 變數和陣列宣告:需要先宣告一個index作為節氣序號,並且收納所有節氣的資料到一個陣列。陣列結構為四個item,一個item代表一個季節,而一個季節又是一個陣列,裡面有六個item,每個item都是一個節氣,各個節氣的資料就儲存在節氣Dictionary裡面。
var index = 0
let solarTerms = [
[[
"picture": "立春.jpg",
"title": "立春",
"date": "國曆2月4、5日",
"description": "春季開始。立是開始的意思,春是蠢動,表示萬物開始有生氣。"],
[
"picture": "雨水.jpg",
"title": "雨水",
"date": "國曆2月19、20日",
"description": "降雨開始增多,春雨綿綿,立春之後,東風解凍,雪水溶化,空氣中水蒸氣增加,容易下雨。"],
[
"picture": "驚蟄.jpg",
"title": "驚蟄",
"date": "國曆3月5、6日",
"description": "天空出現雷聲,萬物逐漸茲生茂盛,蟄伏地下冬眠的蟲類,開始出土活動。"],
[
"picture": "春分.jpg",
"title": "春分",
"date": "國曆3月21、22日",
"description": "春季過了一半,陽光直射赤道上方,地球上南北半球受光相等,晝夜平分。"],
[
"picture": "清明.jpg",
"title": "清明",
"date": "國曆4月5、6日",
"description": "天氣逐漸暖和,花草樹木開始萌發茂盛,大地呈現氣清景明的現象。"],
[
"picture": "穀雨.jpg",
"title": "榖雨",
"date": "國曆4月20、21日",
"description": "農民剛好春耕完,水田內秧苗正需要大量雨水滋潤。"]
],
//夏秋冬節氣省略
]

2. IBOutlet連結

//最上方季節Segmented Control outlet@IBOutlet weak var seasonSegmentedControl: UISegmentedControl!//背景圖片imageView outlet@IBOutlet weak var pictureImageView: UIImageView!//節氣title outlet@IBOutlet weak var headingLabel: UILabel!//日期date outlet@IBOutlet weak var dateLabel: UILabel!//介紹description outlet@IBOutlet weak var descriptionLabel: UILabel!//最下方page control@IBOutlet weak var termPageControl: UIPageControl!

3. 顯示節氣的函式:參數有代表季節序號的seasonIndex和節氣序號的termIndex。

func showTermPage(seasonIndex: Int, termIndex: Int) {     //根據seasonIndex和termIndex將對應節氣圖片轉為UIImage
let pictureImage = UIImage(named: solarTerms[seasonIndex][termIndex]["picture"]!)
//設定背景圖片
pictureImageView.image = pictureImage
//設定page control的頁面與節氣序號一致
termPageControl.currentPage = termIndex
//設定節氣標題名稱
headingLabel.text = "\(solarTerms[seasonIndex][termIndex]["title"]!)。"
//設定節氣日期
dateLabel.text = solarTerms[seasonIndex][termIndex]["date"]
//設定節氣介紹
descriptionLabel.text = solarTerms[seasonIndex][termIndex]["description"]
}

4. 背景圖片加上兩層漸層layer函式:因為希望左右兩邊下面帶有黑色透明效果來凸顯button和底部文字label,所以加上水平方向和垂直方向的漸層layer。

func addGradientLayer(){     let verticalLayer = CAGradientLayer()     let horizontalLayer = CAGradientLayer()     verticalLayer.frame = pictureImageView.bounds     horizontalLayer.frame = pictureImageView.bounds     verticalLayer.colors = [        CGColor(red: 0, green: 0, blue: 0, alpha: 0.3),        CGColor(red: 0, green: 0, blue: 0, alpha: 0),        CGColor(red: 0, green: 0, blue: 0, alpha: 0),        CGColor(red: 0, green: 0, blue: 0, alpha: 0.3)     ]     verticalLayer.startPoint = CGPoint(x: 0, y: 0.5)     verticalLayer.endPoint = CGPoint(x: 1, y: 0.5)     verticalLayer.locations = [0, 0.2, 0.8, 1]     horizontalLayer.colors = [        CGColor(red: 0, green: 0, blue: 0, alpha: 0),        CGColor(red: 0, green: 0, blue: 0, alpha: 1)     ]     horizontalLayer.startPoint = CGPoint(x: 0.5, y: 0.5)     horizontalLayer.endPoint = CGPoint(x: 0.5, y: 1)     pictureImageView.layer.addSublayer(horizontalLayer)}

使用UIControl切換季節

  1. Segmented Control切換季節
@IBAction func seasonChange(_ sender: Any) {    //每次切換時都將目前選取的Segment index取出作為seasonIndex
let seasonIndex = seasonSegmentedControl.selectedSegmentIndex
//切換季節時都預設顯示該季節第一個節氣,所以將index重置為0
index = 0
//使用seasonIndex和index顯示節氣
showTermPage(seasonIndex: seasonIndex, termIndex: index)
}

2. button切換節氣:分為next和previous兩個button,無限循環不會無法點選。

//Next Button Action@IBAction func nextButtonTapped(_ sender: Any) {     //從Segmented Control取得seasonIndex
let seasonIndex = seasonSegmentedControl.selectedSegmentIndex
//遞增循環,取出index
index = (index + 1) % solarTerms[seasonIndex].count
//顯示節氣資料
showTermPage(seasonIndex: seasonIndex, termIndex: index)
}//Previous Button Action@IBAction func previousButtonTapped(_ sender: Any) { //從Segmented Control取得seasonIndex
let seasonIndex = seasonSegmentedControl.selectedSegmentIndex
//遞減循環,取出index
index = (index + solarTerms[seasonIndex].count - 1) % solarTerms[seasonIndex].count
//顯示節氣資料
showTermPage(seasonIndex: seasonIndex, termIndex: index)
}

最後在ViewDidLoad()中呼叫加入漸層,調整節氣介紹的Label行高就完成了。

--

--