Open8
【SwiftUI】light/darkモードそれぞれの色を表示してくれるViewを作る
こんな感じの
ここの部分
まず直角三角形の要素を作る。
UIKitならCALayerでpathとmaskを駆使するような実装をすると思う。
SwiftUIではShape
というものを使って、形を定義できそう
じゃあShape
で直角三角形を作る。
直角部分の位置を変えられるように実装した。
struct RightTriangle: Shape {
enum RightAngle: CaseIterable {
case topLeft, topRight, bottomLeft, bottomRight
var transform: CGAffineTransform {
switch self {
case .topLeft: return .identity
case .topRight: return .init(scaleX: -1, y: 1)
case .bottomLeft: return .init(scaleX: 1, y: -1)
case .bottomRight: return .init(scaleX: -1, y: -1)
}
}
func offset(from rect: CGRect) -> CGPoint {
let size = rect.size
switch self {
case .topLeft: return .zero
case .topRight: return .init(x: -size.width, y: 0)
case .bottomLeft: return .init(x: 0, y: -size.height)
case .bottomRight: return .init(x: -size.width, y: -size.height)
}
}
}
var rightAngle: RightAngle = .topLeft
func path(in rect: CGRect) -> Path {
var path = CGMutablePath()
path.move(to: .zero)
path.addLine(to: .init(x: rect.maxX, y: 0))
path.addLine(to: .init(x: 0, y: rect.maxY))
path.addLine(to: .zero)
let offset = rightAngle.offset(from: rect)
var transform = rightAngle.transform
.translatedBy(x: offset.x, y: offset.y)
if let flippedPath = path.mutableCopy(using: &transform) {
path = flippedPath
}
return Path(path)
}
}
transformで反転する処理をしているが、これはSwiftUIのPath
では出来なさそうだったので、CGPathを経由して定義している。
これを利用して目的の色表示部分を作る。
ZStack {
colors
.clipShape(RightTriangle(rightAngle: .topLeft))
.colorScheme(.light)
colors
.clipShape(RightTriangle(rightAngle: .bottomRight))
.colorScheme(.dark)
}
.frame(width: 140)
clipShape
で直角三角形の形を適用している。
colorScheme
で、light/darkモードのどちらの色を使用するか指定している。
これはdeprecatedになっていて、新しくpreferredColorScheme
というAPIが用意されているのだが、こちらを使用すると、全体に指定したlight/darkモードが適用されてしまい、うまく動かなかった.
(Bugかも?)
SwiftUIのデフォルトで定義されているColorって、少なすぎるよね。
かといってUIColor/NSColorからの変換をしてると、せっかくマルチプラットフォームで使えるSwiftUIなのになんか嫌。
そんなあなたに
UIColor/NSColorに定義されている色をSwiftUI.Colorでも使用できるようにしました。
OSは関係なくmacOSからiOSの色を参照することもできます。
今回の記事は、↑の作成中に生まれました。
スター好きです。