前回は、SwiftUIでQRコードを生成するアプリケーションを開発する記事を紹介しました。
QRコードを生成する関数では、SwiftUIでは直接、CIImage を表示する事が出来ないので、
CIImage → CGImage → UIImage → Image と変換が必要でした。
SwiftUIで最初に開発するアプリケーションにしては、難易度が高かったかもしれませんね。
今回は少し難易度を落として、SwiftUIで色(Color)を選択するアプリケーションを
開発する記事を紹介しようと思います。
UI(ユーザーインタフェース)開発やブログ記事の作成、デザインの作業を行っていると、
文字に色付けしたり、画面やボタンの色を変更することも多いかと思います。
色を選ぶ時に、色の基本となる三原色や輝度(明暗)を指定しますが、ツールや色のサイトを
利用して、色のコードや数値を指定する方も多いと思います。
他の開発言語で、色を選択する部品は有りますが、SwiftUIやUIKitでも、ColorPicker という
色を選択出来る部品が提供されていますので、こちらを利用してみましょう。
習得内容
今回、SwiftUIで色(Color)を選択するアプリケーションを生成する事で、下記の内容を
習得する事が出来ます。
- 光の三原色(RGB)と色の三属性(HSB)
- モーダル表示:sheet()
- カラー:SwiftUIで色(Color)の使い方
- カラーピッカー:SwiftUIで色(Color)の選択(ColorPicker)
- フォーマット:数値を文字列(String)に変更する方法(format)
- extension:Colorの拡張
動作環境
今回も、アプリが動作する環境は下記になります。
- mac OS:Sequoia 15.6.1
- iOS:26.0
- Xcode:26.0.1
- Swift:6.2.1
光の三原色と色の三属性
色を利用する時は、光の三原色と色の三要素が頻繁に利用されますので、簡単に紹介します。
光の三原色:RGB
光の三原色(RGB)は、下記で構成されています。
- 赤(red):0~255の値で表現します。
- 緑(green):0~255の値で表現します。
- 青(blue):0~255の値で表現します。
ちなみに、絵の具やインクなどの色料に利用される色の三原色(CMY)は、
下記で構成されています。
- シアン(Cyan)
- マゼンタ(Magenta)
- イエロー(Yellow)
色の三属性:HSB
色の三属性(HSB)は、下記で構成されています。
- 色相(hue):赤、緑、青などの色合いの事。0~360度の角度で表現します。
- 彩度(saturation):色の鮮やかさの度合いの事。0~100%で表現します。
- 明度・輝度(brightness):色の明るさの度合いの事。0~100%で表現します。
光や色の三原色と色の三要素の詳細については、下記を参照してみて下さい。
色(Color)選択アプリ
では、色(Color)選択アプリを作成していきます。
Xcode の上部タブメニューより、File → New → File from Template を選択します。
SwiftUI View を選択します。
名称は、ColorPickerView を入力してみます。
Create ボタンを押して、ColorPickerView.swift を作成します。
ContentView:メインメニュー(ランチャー)
前回の記事で作成したメインメニュー(ランチャー):ContentView を確認します。
import SwiftUI
struct ContentView: View {
@State var isPopupView_1 = false
var body: some View {
VStack{
Button {
self.isPopupView_1.toggle()
} label: {
Text("QRCodeView")
.font(.title2)
}
.fullScreenCover(isPresented: $isPopupView_1, content: {
QRCodeView(isPopupView_1: $isPopupView_1)
})
.padding()
}
}
}
#Preview {
ContentView()
}
モーダル表示:sheet()
先程、作成した ColorPickerView を ContentView のメニューに追加します。
import SwiftUI
struct ContentView: View {
@State var isPopupView_1 = false
@State var isPopupView_2 = false
var body: some View {
VStack{
Button {
self.isPopupView_1.toggle()
} label: {
Text("QRCodeView")
.font(.title2)
}
.fullScreenCover(isPresented: $isPopupView_1, content: {
QRCodeView(isPopupView_1: $isPopupView_1)
})
.padding()
Button {
self.isPopupView_2.toggle()
} label: {
Text("ColorPickerView")
.font(.title2)
}
.sheet(isPresented: $isPopupView_2, content: {
ColorPickerView(isPopupView_2: $isPopupView_2)
})
.padding()
}
}
}
#Preview {
ContentView()
}
QRCodeView を呼び出す際は、フルモーダル表示をさせる為、fullScreenCover() を
指定しましたが、ColorPickerView を呼び出す際は、モーダル表示をさせる sheet() を
指定してみます。
ColorPickerView:色選択アプリ
ソース例:ColorPickerView
次に、ContentView(親画面)から呼び出される ColorPickerView(子画面)の
ソースを紹介します。
import SwiftUI
struct ColorPickerView: View {
@Binding var isPopupView_2: Bool
@State private var color: Color = .white
var body: some View {
ZStack {
Color(red: 1.0, green: 1.0, blue: 0.05, opacity: 0.3)
.edgesIgnoringSafeArea(.all)
VStack {
ColorPicker(selection: $color) {
Text("ColorPicker")
.font(.title2)
.foregroundColor(.black)
}
HStack {
Image(systemName: "cloud.sun.rain.fill")
.font(.system(size: 100))
.foregroundColor(color)
.scaledToFill()
.padding()
Image(systemName: "figure.outdoor.cycle.circle.fill")
.font(.system(size: 100))
.foregroundColor(color)
.scaledToFill()
.padding()
}
HStack(alignment: .top){
VStack(alignment: .leading){
Text("RGB")
.font(.title2)
.foregroundColor(.purple)
.padding()
Text("red : \(String(format: "%.1f",color.rgb.red * 255))")
.font(.system(size: 19))
.foregroundColor(.red)
Text("green : \(String(format: "%.1f",color.rgb.green * 255))")
.font(.system(size: 19))
.foregroundColor(.green)
Text("blue : \(String(format: "%.1f",color.rgb.blue * 255))")
.font(.system(size: 19))
.foregroundColor(.blue)
Text("HEX : #\(color.hex)")
.font(.system(size: 19))
.foregroundColor(.pink)
}
.padding()
VStack(alignment: .leading){
Text("HSB")
.font(.title2)
.foregroundColor(.blue)
.padding()
Text("hue : \(String(format: "%.1f", color.hsb.hue * 360))" + " 度")
.font(.system(size: 19))
.foregroundColor(.green)
Text("saturation : \(String(format: "%.1f", color.hsb.saturation * 100))" + " %")
.font(.system(size: 19))
.foregroundColor(.mint)
Text("brightness : \(String(format: "%.1f", color.hsb.brightness * 100))" + " %")
.font(.system(size: 19))
.foregroundColor(.orange)
}
.padding()
}
.padding()
Button(action: {
withAnimation {
self.isPopupView_2.toggle()
}
}, label: {
Text("Close")
.font(.title2)
.foregroundColor(.black)
})
.padding()
}
}
}
}
#Preview {
ColorPickerView(isPopupView_2: .constant(false))
}
ColorPicker
SwiftUIやUIKitでも、ColorPicker という色を選択出来る部品が提供されていますので、
こちらを利用してみましょう。
var body: some View {
ZStack {
Color(red: 1.0, green: 1.0, blue: 0.05, opacity: 0.3)
.edgesIgnoringSafeArea(.all)
VStack {
ColorPicker(selection: $color) {
Text("ColorPicker")
.font(.title2)
.foregroundColor(.black)
}
- ZStack {Color(red: 1.0, green: 1.0, blue: 0.05, opacity: 0.3):メインメニューから呼び出されて、覆い被さるので、メインメニューと区別する為、画面の土台となる部分にクリーム色を設定しています。
- ColorPicker(selection: $color) {Text(“ColorPicker”):ColorPicker の部品を配置しています。名称をTextにする事で、フォントのサイズや色の設定が出来ます。選んだ色は、$color に渡しています。
ColorPicker の設定に、Library pane(パーツ選択画面)を利用してみましょう。
ColorPicker を設定したい位置にカーソルを移動した後、shift + command + L を
同時に押してみて下さい。
上記の画面のように、パーツを選択するボタンが無い場合が有ります。
この場合は、Xcode の上部タブメニューより、Editor → Canvas を確認してみて下さい。
Canvas に、チェックが入っていないと考えられます。
Editor → Canvas を選択してみて下さい。
Canvas に、チェックが入った事を確認出来ました。
再度、ColorPicker を設定したい位置にカーソルを移動した後、shift + command + L を
同時に押してみて下さい。
今度は、パーツを選択するボタンが左端に有りますので、ボタンを押して、
ColorPicker を選択して下さい。
Library pane(パーツ選択画面)を利用せず、直接、ColorPi… をタイピングして
設定する方が早い方は、そちらを選んで下さい、
HStack {
Image(systemName: "cloud.sun.rain.fill")
.font(.system(size: 100))
.foregroundColor(color)
.scaledToFill()
.padding()
Image(systemName: "figure.outdoor.cycle.circle.fill")
.font(.system(size: 100))
.foregroundColor(color)
.scaledToFill()
.padding()
}
- Image(systemName: “cloud.sun.rain.fill“):システムシンボル(SF Symbols)より、晴れのち曇り時々雨のアイコンを設定しています。
- Image(systemName: “figure.outdoor.cycle.circle.fill“):システムシンボル(SF Symbols)より、自転車レースのアイコンを設定しています。
- .foregroundColor(color):アイコンの色が変わるように、設定しています。
こちらは、SF Symbols で、cloud.sun.rain.fill のアイコンを表示した画面です。
こちらは、SF Symbols で、figure.outdoor.cycle.circle.fill のアイコンを表示した画面です。
フォーマット(format)
VStack(alignment: .leading){
Text("RGB")
.font(.title2)
.foregroundColor(.purple)
.padding()
Text("red : \(String(format: "%.1f",color.rgb.red * 255))")
.font(.system(size: 19))
.foregroundColor(.red)
Text("green : \(String(format: "%.1f",color.rgb.green * 255))")
.font(.system(size: 19))
.foregroundColor(.green)
Text("blue : \(String(format: "%.1f",color.rgb.blue * 255))")
.font(.system(size: 19))
.foregroundColor(.blue)
Text("HEX : #\(color.hex)")
.font(.system(size: 19))
.foregroundColor(.pink)
}
.padding()
- Text(“red : \(String(format: “%.1f“,color.rgb.red * 255))”):ColorExtensions から、color.rgb.red を取得して、format: “%.1f” で、小数点第1位までの数値を文字列に整形しています。
- Text(“green : \(String(format: “%.1f“,color.rgb.green * 255))”):ColorExtensions から、color.rgb.greenを取得して、format: “%.1f“で、小数点第1位までの数値を文字列に整形しています。
- Text(“blue : \(String(format: “%.1f“,color.rgb.blue * 255))”):ColorExtensions から、color.rgb.blueを取得して、format: “%.1f“で、小数点第1位までの数値を文字列に整形しています。
- Text(“HEX : #\(color.hex)”):ColorExtensions から、color.hex を取得しています。
VStack(alignment: .leading){
Text("HSB")
.font(.title2)
.foregroundColor(.blue)
.padding()
Text("hue : \(String(format: "%.1f", color.hsb.hue * 360))" + " 度")
.font(.system(size: 19))
.foregroundColor(.green)
Text("saturation : \(String(format: "%.1f", color.hsb.saturation * 100))" + " %")
.font(.system(size: 19))
.foregroundColor(.mint)
Text("brightness : \(String(format: "%.1f", color.hsb.brightness * 100))" + " %")
.font(.system(size: 19))
.foregroundColor(.orange)
}
.padding()
- Text(“hue : \(String(format: “%.1f”, color.hsb.hue * 360))” + ” 度“):ColorExtensions から、color.hsb.hue を取得して、format: “%.1f” で、小数点第1位までの数値を文字列に整形しています。
- Text(“saturation : \(String(format: “%.1f“, color.hsb.saturation * 100))” + ” %“):ColorExtensions から、color.hsb.saturation を取得して、format: “%.1f” で、小数点第1位までの数値を文字列に整形しています。
- Text(“brightness : \(String(format: “%.1f“, color.hsb.brightness * 100))” + ” %“):ColorExtensions から、color.hsb.brightnessを取得して、format: “%.1f” で、小数点第1位までの数値を文字列に整形しています。
ColorExtensions
Color で、RGBや16進数(HEX)表現、HSBの値を返すメソッドを拡張していきます。
extension:Colorの拡張
Color を拡張していきます。
Xcode の上部タブメニューより、File → New → File from Template を選択します。
Swift File を選択します。
名称は、ColorExtensions を入力してみます。
Create ボタンを押して、ColorExtensions.swift を作成します。
上記のように、白紙コードが生成されたと思います。
ここに、Color で、RGBや16進数(HEX)表現や、HSBの値を返すメソッドソースを
追記していきます。
ソース例:ColorExtensions
ColorExtensions.swift のソースを紹介します。
import SwiftUI
struct HSB {
var hue: CGFloat // 色相:0~360度
var saturation: CGFloat // 彩度:0~100%
var brightness: CGFloat // 輝度:0~100%
}
struct RGB {
var red: CGFloat // Red
var green: CGFloat // Green
var blue: CGFloat // Blue
}
extension Color {
var rgb: RGB {
let uiColor = UIColor(self)
var rgb_red: CGFloat = 0
var rgb_green: CGFloat = 0
var rgb_blue: CGFloat = 0
var rgb_alpha: CGFloat = 0
uiColor.getRed(&rgb_red, green: &rgb_green, blue: &rgb_blue, alpha: &rgb_alpha)
return RGB(red: rgb_red, green: rgb_green, blue: rgb_blue)
}
var hex: String {
let hex_red = Int(round(self.rgb.red * 255))
let hex_green = Int(round(self.rgb.green * 255))
let hex_blue = Int(round(self.rgb.blue * 255))
return String(format: "%02X%02X%02X", hex_red, hex_green, hex_blue)
}
var hsb: HSB {
let uiColor = UIColor(self)
var hsb_hue: CGFloat = 0
var hsb_saturation: CGFloat = 0
var hsb_brightness: CGFloat = 0
var hsb_alpha: CGFloat = 0
uiColor.getHue(&hsb_hue, saturation: &hsb_saturation, brightness: &hsb_brightness, alpha: &hsb_alpha)
return HSB(hue: hsb_hue, saturation: hsb_saturation, brightness: hsb_brightness)
}
}
ソースを説明します。
struct HSB {
var hue: CGFloat // 色相:0~360度
var saturation: CGFloat // 彩度:0~100%
var brightness: CGFloat // 輝度:0~100%
}
struct RGB {
var red: CGFloat // Red
var green: CGFloat // Green
var blue: CGFloat // Blue
}
- struct HSB {:HSBの構造体を宣言しています。変数には、CGFloat:浮動小数点を設定しています。
- struct RGB {:RGBの構造体を宣言しています。変数には、CGFloat:浮動小数点を設定しています。
extension Color {
var rgb: RGB {
let uiColor = UIColor(self)
var rgb_red: CGFloat = 0
var rgb_green: CGFloat = 0
var rgb_blue: CGFloat = 0
var rgb_alpha: CGFloat = 0
uiColor.getRed(&rgb_red, green: &rgb_green, blue: &rgb_blue, alpha: &rgb_alpha)
return RGB(red: rgb_red, green: rgb_green, blue: rgb_blue)
}
- extension Color {var rgb: RGB {:Color の拡張を宣言しています。
- let uiColor = UIColor(self): UIColor(self) を定数に代入しsています。
- var rgb_red: CGFloat = 0:変数の rgb_red に、初期値:0を代入しています。
- var rgb_green: CGFloat = 0:変数の rgb_green に、初期値:0を代入しています。
- var rgb_blue: CGFloat = 0:変数の rgb_blue に、初期値:0を代入しています。
- var rgb_alpha: CGFloat = 0:変数の rgb_alpha に、初期値:0を代入しています。
- uiColor.getRed(…):uiColor.getRed() で、RGB の色を取得しています。
- return RGB(…):取得した色を、呼び出し元に返却しています。
var hex: String {
let hex_red = Int(round(self.rgb.red * 255))
let hex_green = Int(round(self.rgb.green * 255))
let hex_blue = Int(round(self.rgb.blue * 255))
return String(format: "%02X%02X%02X", hex_red, hex_green, hex_blue)
}
- let hex_red = Int(round(self.rgb.red * 255)):定数 hex_red に、self.rgb.red で取得した値に255倍した整数(四捨五入)を代入しています。
- let hex_green = Int(round(self.rgb.green * 255)):定数 hex_green に、self.rgb.green で取得した値に255倍した整数(四捨五入)を代入しています。
- let hex_blue = Int(round(self.rgb.blue * 255)):定数 hex_blue に、self.rgb.blue で取得した値に255倍した整数(四捨五入)を代入しています。
- return String(format: “%02X%02X%02X“, hex_red, hex_green, hex_blue):hex_red, hex_green, hex_blue の並びで、8桁の16進数(英数大文字)に整形して、呼び出し元に返却しています。
var hsb: HSB {:は、var rgb: RGB { に類似しているので、説明は省略します。
ColorExtensions については、下記を参考にしています。
アプリ実行:シミュレータの起動
では、実際にアプリを実行してみます。
Xcode の上部タブメニューより、Product → Run を選択します。
エラーが無ければ、iPhoneシミュレータが起動します。
ContentView(メインメニュー)に追加した、ColorPickerViewボタンが表示されている事が
確認出来ました。
ColorPickerView:起動画面
では、ColorPickerViewボタンを押してみます(タップします)。
ContentView(メインメニュー)の上に、ColorPickerView(色選択アプリ)が
重なって、表示された事が確認出来たと思います。
モーダル表示:sheet()
ContentView(メインメニュー)から、ColorPickerView(色選択アプリ)を
呼び出しましたが、画面の上部(赤枠)にContentView(メインメニュー)の
一部が見えている事が分かると思います。
QRCodeView(QRコード生成アプリ)のフルモーダル表示とは異なりますね。
struct ColorPickerView: View {
@Binding var isPopupView_2: Bool
@State private var color: Color = .white
var body: some View {
ZStack {
Color(red: 1.0, green: 1.0, blue: 0.05, opacity: 0.3)
.edgesIgnoringSafeArea(.all)
VStack {
ColorPicker(selection: $color) {
Text("ColorPicker")
.font(.title2)
.foregroundColor(.black)
}
上記のソースで、@State private var color: Color = .white と color の初期値に白を
設定していましたので、ColorPicker や数値に白が反映されている状態が分かります。
<RGB>
red:255.0 green:255.0 blue:255.0 HEX:#FFFFFF
<HSB>
hue:0.0度 saturation:0.0% brightness:100.0%
ColorPicker:グリッド機能
ColorPickerView(色選択アプリ)の左上に、ColorPicker の文字が見えると思います。
ColorPicker の文字の右端に、白〇印が見えますが、こちらを押す(タップする)と、
ColorPicker が開きます。
では、グリッド機能で、別の色を選択してみます。(ColorPicker の左側のタブ)
こちらは、紫色を選択した例です。
ColorPicker の右上の×印を押して、ColorPickerView(色選択アプリ)に
戻ってみます。
ColorPicker の〇印、アイコンの色と数値が、紫色に変更された事が確認出来ます。
<RGB>
red:190.0 green:56.0 blue:243.0 HEX:#BE38F3
<HSB>
hue:283.0度 saturation:77.0% brightness:95.3%
ColorPicker:スペクトラム機能
今度は、スペクトラム機能を利用してみます。(ColorPicker の中央のタブ)
次に、スペクトラム機能で、別の色を選択してみます。
こちらは、黄緑色を選択した例です。
ColorPicker の右上の×印を押して、ColorPickerView(色選択アプリ)に
戻ってみます。
ColorPicker の〇印、アイコンの色と数値が、黄緑色に変更された事が確認出来ます。
<RGB>
red:0.0 green:254.3 blue:1.5 HEX:#00FE02
<HSB>
hue:120.4度 saturation:100.0% brightness:99.7%
ColorPicker:スライダ機能
最後に、スライダ機能を利用してみます。(ColorPicker の右側のタブ)
スライダ機能で、別の色を調整してみます。
こちらは、薄紅色を選択した例です。
ColorPicker の右上の×印を押して、ColorPickerView(色選択アプリ)に
戻ってみます。
ColorPicker の〇印、アイコンの色と数値が、薄紅色に変更された事が確認出来ます。
<RGB>
red:235.1 green:26.8 blue:71.3 HEX:#EB1B47
<HSB>
hue:347.2度 saturation:88.6% brightness:92.2%
まとめ
今回は、SwiftUIで、ColorPicker を利用して、色(カラー)を選択するアプリケーションを
開発する記事を紹介しました。
次回は、SwiftUIで、Slider を利用して、色(カラー)を選択するアプリケーションを開発する
記事を紹介しようと思います。
- イラスト:いらすとや より引用
































コメント