Part 5 Allowing a tap to set a value | Create the Color Picker with SwiftUI

SwiftUIでカラーピッカーを作るという連載記事です。今回はカラーピッカーのグラデーションビュー上をタップして、RGB値を設定できるようにするためのコードを実装します。

This is a series of articles on creating a color picker in SwiftUI. In this article, we aim to implement the code that enables tapping on the gradient view of the color picker to set RGB values.

TOC

To support tap gestures in SwiftUI

To support tap gestures in SwiftUI, use the onTapGesture modifier. The behavior of the onTapGesture modifier varies based on different arguments. In addition, iOS 16, iPadOS 16, macOS 13, and watchOS 9.0 have added a modifier that passes the tapped coordinates.

For instance, the subsequent code illustrates how to display the tapped coordinates on a label in the red view.

struct ContentView: View {
    @State private var tappedPoint = CGPoint()
    
    var body: some View {
        VStack {
            GeometryReader { geometry in
                Path { path in
                    path.addRect(CGRect(x: 0, y: 0, width: geometry.size.width, height: geometry.size.height))
                }
                .fill(.red)
            }
            .onTapGesture { point in
                tappedPoint = point
            }
            Text("Tapped: \(tappedPoint.x), \(tappedPoint.y)")
        }
        .padding()
    }
}
Display tapped coordinates
Display tapped coordinates

Calculate the current value from the coordinates

We will now formulate the code to calculate the current value based on the coordinates. For example, suppose the left edge of the PickerGradationView is 0.0, and the right edge is 1.0, so dividing the X coordinate of the tapped coordinate by the width of the PickerGradationView will give the current value of the channel as it is.

The code for the Red channel is as follows.

PickerGradationView(startColor: redStartColor, endColor: redEndColor)
	.frame(height: 100)
	.background {
		GeometryReader { geometry in
			Path { path in
				DispatchQueue.main.async {
					if geometry.size != redGradationViewSize {
						redGradationViewSize = geometry.size
					}
				}
			}
		}
	}
	.onTapGesture { point in
		channelValue.red = point.x / redGradationViewSize.width
	}

We have incorporated the onTapGesture modifier, and the same code will apply to the Green and Blue channels.

Running in live preview on Xcode
Running in live preview on Xcode

Download the sample code

You can download the code crafted for this article here.

Authored Books

Let's share this post !

Author of this article

Akira Hayashi (林 晃)のアバター Akira Hayashi (林 晃) Representative(代表), Software Engineer(ソフトウェアエンジニア)

アールケー開発代表。Appleプラットフォーム向けの開発を専門としているソフトウェアエンジニア。ソフトウェアの受託開発、技術書執筆、技術指導・セミナー講師。note, Medium, LinkedIn
-
Representative of RK Kaihatsu. Software Engineer Specializing in Development for the Apple Platform. Specializing in contract software development, technical writing, and serving as a tech workshop lecturer. note, Medium, LinkedIn

TOC