底辺SE奮闘記

年収300万SEブログ

【SwiftUI・ColorPicker】カラーホイールをカスタマイズ(非表示)するアイデア

環境

  • Xcode 13
  • Swift 5
  • SwiftUI
  • iOS14, 15

解決する問題

  • カラーホイールが邪魔(オリジナルデザインにしたい)
  • UIColorPickerViewControllerの出し入れを自分でコントロールしたい

作戦

現在(2021/10/07)のiOSデフォルトのカラーピッカーはラベル横のカラーホイールは非表示にできません。ラベルは非表示にできるのに...。

なのでUIColorPickerViewControllerをSwiftUIで使用することを考えます。

実装

UIViewControllerRepresentableプロトコルを実装したクラスを作成します。

import Foundation
import SwiftUI
import UIKit

/// カラーピッカーコンテナ
struct ColorPickerContainer : UIViewControllerRepresentable
{
    //新しい色が設定されたら呼ぶ
    let changedColor : (Color) -> Void
    
    //イベントを受け取るコーディネータ
    class Coordinator: NSObject, UIColorPickerViewControllerDelegate{
        // カラーピッカーコンテナ
        private let parent: ColorPickerContainer
        
        init(parent: ColorPickerContainer) {
            self.parent = parent
        }
        
        // 新しい色が設定されたら呼ばれる
        func colorPickerViewController(_ viewController: UIColorPickerViewController, didSelect color: UIColor, continuously: Bool) {
             changedColor(Color(color))
        }
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(parent: self)
    }
    
    // UIColorPickerViewControllerを表示しようとしたらよばれる
    func makeUIViewController(context: Context) -> UIColorPickerViewController {
        let controller = UIColorPickerViewController()
        controller.delegate = context.coordinator
        controller.title  = "タイトル"// カラーピッカーのタイトル
        controller.supportsAlpha = false// 色の透明度を設定できるか否か
        return controller
    }
    
    func updateUIViewController(_ uiViewController: UIColorPickerViewController, context: Context) {
        //
    }
}

使い方例 Example

import SwiftUI

struct TestView: View {

    ///カラーピッカーを表示するか
    @State private var isShow = false
    
    var body: some View {
        VStack{
            Button(action : {
                isShow = true// 押下でカラーピッカーを開く
            }) {
                Text("カラーピッカーを開く")
            }    
        }
        .sheet(
            isPresented: $isShow,
            onDismiss: {}) {
            ZStack(alignment: .top){
                ColorPickerContainer (){ color in
                    // ここのcolorを好きなように使う
                }
                // 閉じるボタンがなかったので下記のように設定すると良い
                HStack{
                    Spacer()
                    Button(action: {
                        isShow = false
                    }) {
                        Text("閉じる")
                            .foregroundColor(Color("text_main"))
                            .padding(.top, 20)
                            .padding(.trailing, 20)
                    }
                }
            }
        }
    }
}

struct TestView_Previews: PreviewProvider {
    static var previews: some View {
        TestView()
    }
}