用ios SDK寫出一個emoji手機桌布吧

Una
彼得潘的 Swift iOS / Flutter App 開發教室
14 min readJul 18, 2023

ios16出來的時候有一個功能是emoji的桌布,覺得很可愛,可惜不能加上除了emoji的圖片,於是我們就自己來寫一個出來吧

Let’s go!

1/第一個步驟是先把腦中想的畫面拆解出來,以下三個素材事先都先準備好,除了底圖的emoji排列,其餘都事先去背。

先模擬了一下想要的emoji排列,以及準備好素材的圖片

2/生成背景底圖

// 創建背景視圖
var rect = CGRect(x: 0, y: 0, width: 390, height: 844)
let bgView = UIView(frame: rect)
bgView.backgroundColor = UIColor(red: 117/255, green: 135/255, blue: 212/255, alpha: 1)

3/生成emoji

因為需要一個方法來計算一個圓圈的icon位置,所以寫一個共用方法createIcons,讓之後每圈的icon都能利用這個方法計算出位置。

// 創建一個表示icon的座標及符號的結構
struct Icon {
var x: Double
var y: Double
var symbol: String
}

// 函式:計算icon座標
func createIcons(centerX: Double, centerY: Double, radius: Double, numIcons: Int, symbol: String) -> [Icon] {
// 儲存計算出的icon座標的陣列
var icons = [Icon]()
// 迴圈計算每個icon的座標
for i in 0..<numIcons {
// 計算θ(theta)的值,θ表示每個icon在圓上的位置,以弧度為單位
let theta = (2.0 * Double.pi * Double(i)) / Double(numIcons)
// 計算icon的x和y座標
let x = centerX + radius * cos(theta)
let y = centerY + radius * sin(theta)
// 將icon的座標及符號儲存到icons陣列中
icons.append(Icon(x: x, y: y, symbol: symbol))
}
// 回傳儲存所有icon座標的陣列
return icons
}

每一個圈的icon都設置相關的數值,在呼叫上述的方法跑出icon

/**
* @param {Double} bones_radius - 骨頭icon圓圈半徑
* @param {Int} bones_num_icons - 骨頭icon數量
* @param {[Icon]} bones_icon_positions - 骨頭icon座標位置,及圖示
*/
let bones_radius = 300.0
let bones_num_icons = 30
let bones_icon_positions = createIcons(centerX: center_x, centerY: center_y, radius: bones_radius, numIcons: bones_num_icons, symbol: "🦴")
for (index, icon) in bones_icon_positions.enumerated() {
print("Icon \(index + 1): x = \(icon.x), y = \(icon.y)")
// 創建並設定骨頭icon的UILabel
let iconLabel = UILabel(frame: CGRect(x: icon.x, y: icon.y, width: 50, height: 50))
iconLabel.text = icon.symbol
iconLabel.font = UIFont.systemFont(ofSize: 50)
bgView.addSubview(iconLabel)
}

/**
* @param {Double} bear_radius - 熊icon圓圈半徑
* @param {Int} bear_num_icons - 熊icon數量
* @param {[Icon]} bear_icon_positions - 熊icon座標位置,及圖示
*/
let bear_radius = 230.0
let bear_num_icons = 20
let bear_icon_positions = createIcons(centerX: center_x, centerY: center_y, radius: bear_radius, numIcons: bear_num_icons, symbol: "🧸")
for (index, icon) in bear_icon_positions.enumerated() {
print("Icon \(index + 1): x = \(icon.x), y = \(icon.y)")
// 創建並設定熊icon的UILabel
let iconLabel = UILabel(frame: CGRect(x: icon.x, y: icon.y, width: 50, height: 50))
iconLabel.text = icon.symbol
iconLabel.font = UIFont.systemFont(ofSize: 50)
bgView.addSubview(iconLabel)
}

...

5/疊加剩餘的兩張圖,就完成啦

// 增加MGM外框圖片
let MGMImage = UIImage(named: "MGM.png")
let MGMImgaeView = UIImageView(image: MGMImage)
MGMImgaeView.frame = CGRect(x: -50, y: 260, width: 490, height: 300)
MGMImgaeView.contentMode = .scaleAspectFill
bgView.addSubview(MGMImgaeView)

// 增加狗的圖片
let dogImage = UIImage(named: "dog.png")
let dogImgaeView = UIImageView(image: dogImage)
dogImgaeView.frame = CGRect(x: 135, y: 330, width: 100, height: 150)
dogImgaeView.contentMode = .scaleAspectFill
bgView.addSubview(dogImgaeView)

完整程式碼

// 匯入UIKit框架,用於創建UI元素
import UIKit
// 匯入Foundation框架,提供一些基本功能
import Foundation
// 匯入PlaygroundSupport框架,使Playground可以渲染視圖
import PlaygroundSupport

// 創建一個表示icon的座標及符號的結構
struct Icon {
var x: Double
var y: Double
var symbol: String
}

// 函式:計算icon座標
func createIcons(centerX: Double, centerY: Double, radius: Double, numIcons: Int, symbol: String) -> [Icon] {
// 儲存計算出的icon座標的陣列
var icons = [Icon]()
// 迭代計算每個icon的座標
for i in 0..<numIcons {
// 計算θ(theta)的值,θ表示每個icon在圓上的位置,以弧度為單位
let theta = (2.0 * Double.pi * Double(i)) / Double(numIcons)
// 計算icon的x和y座標
let x = centerX + radius * cos(theta)
let y = centerY + radius * sin(theta)
// 將icon的座標及符號儲存到icons陣列中
icons.append(Icon(x: x, y: y, symbol: symbol))
}
// 回傳儲存所有icon座標的陣列
return icons
}

// 創建背景視圖
var rect = CGRect(x: 0, y: 0, width: 390, height: 844)
let bgView = UIView(frame: rect)
// 設定背景視圖的背景顏色
bgView.backgroundColor = UIColor(red: 117/255, green: 135/255, blue: 212/255, alpha: 1)

// 圓心的座標
let center_x = 170.0
let center_y = 400.0

// 處理太陽icon
let sun_radius = 380.0
let sun_num_icons = 25
// 使用createIcons函式計算太陽icon的座標
let sun_icon_positions = createIcons(centerX: center_x, centerY: center_y, radius: sun_radius, numIcons: sun_num_icons, symbol: "🔆")
for (index, icon) in sun_icon_positions.enumerated() {
// 印出太陽icon的座標資訊
print("Icon \(index + 1): x = \(icon.x), y = \(icon.y)")
// 創建並設定太陽icon的UILabel
let iconLabel = UILabel(frame: CGRect(x: icon.x, y: icon.y, width: 50, height: 50))
iconLabel.text = icon.symbol
iconLabel.font = UIFont.systemFont(ofSize: 50)
bgView.addSubview(iconLabel)
}

// 處理骨頭icon
let bones_radius = 300.0
let bones_num_icons = 30
// 使用createIcons函式計算骨頭icon的座標
let bones_icon_positions = createIcons(centerX: center_x, centerY: center_y, radius: bones_radius, numIcons: bones_num_icons, symbol: "🦴")
for (index, icon) in bones_icon_positions.enumerated() {
// 印出骨頭icon的座標資訊
print("Icon \(index + 1): x = \(icon.x), y = \(icon.y)")
// 創建並設定骨頭icon的UILabel
let iconLabel = UILabel(frame: CGRect(x: icon.x, y: icon.y, width: 50, height: 50))
iconLabel.text = icon.symbol
iconLabel.font = UIFont.systemFont(ofSize: 50)
bgView.addSubview(iconLabel)
}

// 處理熊icon
let bear_radius = 230.0
let bear_num_icons = 20
// 使用createIcons函式計算熊icon的座標
let bear_icon_positions = createIcons(centerX: center_x, centerY: center_y, radius: bear_radius, numIcons: bear_num_icons, symbol: "🧸")
for (index, icon) in bear_icon_positions.enumerated() {
// 印出熊icon的座標資訊
print("Icon \(index + 1): x = \(icon.x), y = \(icon.y)")
// 創建並設定熊icon的UILabel
let iconLabel = UILabel(frame: CGRect(x: icon.x, y: icon.y, width: 50, height: 50))
iconLabel.text = icon.symbol
iconLabel.font = UIFont.systemFont(ofSize: 50)
bgView.addSubview(iconLabel)
}

// 處理星星icon
let star_radius = 150.0
let star_num_icons = 15
// 使用createIcons函式計算星星icon的座標
let star_icon_positions = createIcons(centerX: center_x, centerY: center_y, radius: star_radius, numIcons: star_num_icons, symbol: "🌟")
for (index, icon) in star_icon_positions.enumerated() {
// 印出星星icon的座標資訊
print("Icon \(index + 1): x = \(icon.x), y = \(icon.y)")
// 創建並設定星星icon的UILabel
let iconLabel = UILabel(frame: CGRect(x: icon.x, y: icon.y, width: 50, height: 50))
iconLabel.text = icon.symbol
iconLabel.font = UIFont.systemFont(ofSize: 50)
bgView.addSubview(iconLabel)
}

// 增加MGM外框圖片
let MGMImage = UIImage(named: "MGM.png")
let MGMImgaeView = UIImageView(image: MGMImage)
MGMImgaeView.frame = CGRect(x: -50, y: 260, width, height: 490) // 設定MGM外框圖片的位置及大小
MGMImgaeView.contentMode = .scaleAspectFill // 設定圖片填充模式為等比例填充
bgView.addSubview(MGMImgaeView) // 將MGM外誆圖片添加到背景視圖中

// 增加狗的圖片
let dogImage = UIImage(named: "dog.png")
let dogImgaeView = UIImageView(image: dogImage)
dogImgaeView.frame = CGRect(x: 135, y: 330, width: 100, height: 150) // 設定狗的圖片位置及大小
dogImgaeView.contentMode = .scaleAspectFill // 設定圖片填充模式為等比例填充
bgView.addSubview(dogImgaeView) // 將狗的圖片添加到背景視圖中

bgView // 顯示背景視圖
PlaygroundPage.current.liveView = bgView // 將背景視圖設定為Playground的即時預覽視圖

完成圖

換成桌布囉~

--

--