【SwiftUI】UIColorPickerViewControllerをカスタムしてARViewから色を取得してみた

2022.03.02

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

本来のUIColorPickerViewControllerが望んでいた使い方ではなさそうですが、UIColorPickerViewControllerをカスタムして自家製のColorPickerを作るチュートリアルがあり、とても面白そうだったので試してみることにしました。

今回は、色を取得するColorPickingButtonを作成し、ARViewと組み合わせることでカメラ映像から色を取得するViewを作っていきます。

作ったもの

ARColorPickerView

ARViewを使ってはいますが、今回はサクッとカメラ映像を取得したかっただけで特にAR的な演出はありません。

環境

  • Xcode 13.2.1
  • iOS 15.2.1

ColorPickingButtonを作る

UIColorPickerViewControllerをカスタムして色を簡単に取得出来るボタンを作っていきます。

UIColorPickerViewController

SwiftUIではColorPickerというものがありますが、今回はUIColorPickerViewControllerを使っていきます。

プレビュー

UIColorPickerViewControllerはこちらです。

コード

UIColorPickerViewControllerSwiftUIで使用するためにUIViewControllerRepresentableに準拠しています。

UIViewControllerRepresentableについての説明は今回は割愛させていただきますが、UIColorPickerViewControllerが色を選択した場合、取得したUIColorColorに変換して、Binding型のプロパティ colorに渡されるようになっています。

struct ColorPickerView: UIViewControllerRepresentable {

    @Binding var color: Color

    func makeCoordinator() -> Coodinator {
        return Coodinator(parent: self)
    }

    func makeUIViewController(context: Context) -> UIColorPickerViewController {
        let picker = UIColorPickerViewController()
        picker.supportsAlpha = false
        picker.selectedColor = UIColor(color)

        picker.delegate = context.coordinator

        return picker
    }

    func updateUIViewController(_ uiViewController: UIColorPickerViewController, context: Context) {
    }

    class Coodinator: NSObject, UIColorPickerViewControllerDelegate {

        var parent: ColorPickerView

        init(parent: ColorPickerView) {
            self.parent = parent
        }

        func colorPickerViewControllerDidFinish(_ viewController: UIColorPickerViewController) {
            parent.color = Color(viewController.selectedColor)
        }

        func colorPickerViewController(_ viewController: UIColorPickerViewController, didSelect color: UIColor, continuously: Bool) {
            parent.color = Color(color)
        }
    }
}

ColorPickerViewができたので、これからボタンに変更していきます。

ColorPickerViewをColorPickingButtonにする

ColorPickerViewframeに値を設定して整形していきます。

widthを100にする

struct ColorPickingButton: View {

    @Binding var color: Color

    var body: some View {
        ColorPickerView(color: $color)
            .frame(width: 100)
    }
}

おや、ColorPickerViewの様子が、、?

heightを50にする

ColorPickerView(color: $color)
    .frame(width: 100, height: 50)

色を取得するスポイドのボタンだけになりました。

offsetを調節する

スポイドのシンボルがセンターにきていないのでoffsetを調節します。

ColorPickerView(color: $color)
    .frame(width: 100, height: 50)
    .offset(x: 20)

ColorPickingButtonは完成したのでARViewと組み合わせていきます。

ARViewを作る

ARViewといっても今回はカメラ入力を取得したいだけなので、AR的な機能は特に使いません。

import SwiftUI
import RealityKit

struct ARViewContainer: UIViewRepresentable {

    func makeUIView(context: Context) -> ARView {
        return ARView(frame: .zero)
    }

    func updateUIView(_ uiView: ARView, context: Context) {}
}

info.plistPrivacy - Camera Usage Descriptionの設定を忘れずに。

ARViewとColorPickingButtonを組み合わせる

今回は取得した色をただ背景色として反映しているだけですが、取得した色を使って何かできそうですね!

import SwiftUI

struct ARColorPickerView: View {

    @State private var color: Color = .white

    var body: some View {
        ZStack {
            Rectangle()
                .fill(color)
                .ignoresSafeArea()

            VStack {
                ARViewContainer()
                ColorPickingButton(color: $color)
            }
        }
    }
}

以上で完成です。これで身の回りの物の色を取得出来ます!

おわりに

このARColorPickerViewを使ったアプリをきっかけに子どもが外に出て沢山の色に触れる機会が作れないかなぁ〜とか考えてますが、まだ面白そうなアイデアは思いつかず。

何はともあれUIColorPickerViewControllerのおかげで簡単に画像から色を抽出できるようになりました。

Thank you so much!

参考