Swift CAGradientLayer显示的颜色不准确。

huangapple go评论74阅读模式
英文:

Swift CAGradientLayer showing inaccurate color

问题

我正在使用CAGradientLayer为我的UIView添加渐变效果。我将渐变设置为红色,并进行了颜色测试,但当我检查显示的颜色时,它显示的RGB值与我指定的不同。有没有办法确保渐变显示我设置的颜色。

let gradientLayer2 = CAGradientLayer()
gradientLayer2.frame.size = colourPickerView.frame.size
gradientLayer2.colors = [
    UIColor(red: 1.00, green: 0.00, blue: 0.00, alpha: 1.00).cgColor,
    UIColor(red: 1.00, green: 0.00, blue: 0.00, alpha: 1.00).cgColor
]

gradientLayer2.startPoint = CGPoint(x: 0.0, y: 0.0)
gradientLayer2.endPoint = CGPoint(x: 1, y: 0)
gradientLayer2.cornerRadius = 20
colourPickerView.layer.insertSublayer(gradientLayer2, at: 0)

这显示红色的颜色为:<CGColor 0x283c8e400> [<CGColorSpace 0x283c989c0> (kCGColorSpaceICCBased; kCGColorSpaceModelRGB; sRGB IEC61966-2.1; extended range)] ( 1 0.14902 0 1 )
(请注意,它显示绿色值为'0.14902')

当我为图层添加纯色背景而不是渐变时,它确实显示了正确的RGB值。

let layer = CALayer()
layer.frame.size = colourPickerView.frame.size
layer.backgroundColor = UIColor(red: 1.00, green: 0.00, blue: 0.00, alpha: 1.00).cgColor
colourPickerView.layer.insertSublayer(layer, at: 0)

以下是我用来获取特定像素颜色的代码:

extension UIView {
    func colorOfPointView(point: CGPoint) -> UIColor {
        let colorSpace: CGColorSpace = CGColorSpaceCreateDeviceRGB()
        let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue)

        var pixelData: [UInt8] = [0, 0, 0, 0]

        let context = CGContext(data: &pixelData, width: 1, height: 1, bitsPerComponent: 8, bytesPerRow: 4, space: colorSpace, bitmapInfo: bitmapInfo.rawValue)

        context!.translateBy(x: -point.x, y: -point.y)

        self.layer.render(in: context!)

        let red: CGFloat = CGFloat(pixelData[0]) / CGFloat(255.0)
        let green: CGFloat = CGFloat(pixelData[1]) / CGFloat(255.0)
        let blue: CGFloat = CGFloat(pixelData[2]) / CGFloat(255.0)
        let alpha: CGFloat = CGFloat(pixelData[3]) / CGFloat(255.0)

        let color: UIColor = UIColor(red: red, green: green, blue: blue, alpha: alpha)

        return color
    }
}
英文:

I am using CAGradientLayer to add a gradient to my UIView. I am setting the gradient ad a solid red colourful testing, and when I check the color that is being displayed, it is showing different RGB values to those I have specified. Is there a way that I can make sure the gradient is showing the colours that I set.

let gradientLayer2 = CAGradientLayer()
gradientLayer2.frame.size = colourPickerView.frame.size
gradientLayer2.colors = [
    UIColor(red: 1.00, green: 0.00, blue: 0.00, alpha: 1.00).cgColor
    UIColor(red: 1.00, green: 0.00, blue: 0.00, alpha: 1.00).cgColor,
]
    
gradientLayer2.startPoint = CGPoint(x: 0.0, y: 0.0)
gradientLayer2.endPoint = CGPoint(x: 1, y: 0)
gradientLayer2.cornerRadius = 20
colourPickerView.layer.insertSublayer(gradientLayer2, at: 0)

This shows the red color as: &lt;CGColor 0x283c8e400&gt; [&lt;CGColorSpace 0x283c989c0&gt; (kCGColorSpaceICCBased; kCGColorSpaceModelRGB; sRGB IEC61966-2.1; extended range)] ( 1 0.14902 0 1 )
(Please note, it is showing the green value as '0.14902')

When I add a solid background colour to the layer, instead of a gradient, it does show the correct RGB values.

let layer = CALayer()
layer.frame.size = colourPickerView.frame.size
layer.backgroundColor = UIColor(red: 1.00, green: 0.00, blue: 0.00, alpha: 1.00).cgColor
colourPickerView.layer.insertSublayer(layer, at: 0)

Here is the code that I am using to get the colour of a certain pixel:

extension UIView {
func colorOfPointView(point: CGPoint) -&gt; UIColor {
    let colorSpace: CGColorSpace = CGColorSpaceCreateDeviceRGB()
    let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue)

    var pixelData: [UInt8] = [0, 0, 0, 0]

    let context = CGContext(data: &amp;pixelData, width: 1, height: 1, bitsPerComponent: 8, bytesPerRow: 4, space: colorSpace, bitmapInfo: bitmapInfo.rawValue)

    context!.translateBy(x: -point.x, y: -point.y)

    self.layer.render(in: context!)

    let red: CGFloat = CGFloat(pixelData[0]) / CGFloat(255.0)
    let green: CGFloat = CGFloat(pixelData[1]) / CGFloat(255.0)
    let blue: CGFloat = CGFloat(pixelData[2]) / CGFloat(255.0)
    let alpha: CGFloat = CGFloat(pixelData[3]) / CGFloat(255.0)

    let color: UIColor = UIColor(red: red, green: green, blue: blue, alpha: alpha)

    return color
}

答案1

得分: 1

你遇到的问题是RGBADisplay P3Extended sRGBA之间的差异。

使用CGContextCAGradientLayer的方法,例如,我们会得到Display P3的值。

要获取“传统”的每组分量8位的值,我们可以首先将视图呈现为UIImage,然后从图像中的某一点获取RGBA值。

使用以下两个扩展:

extension UIView {
    func colorAt(point: CGPoint) -> UIColor? {
        return renderView().getPixelColor(point: point)
    }
    func renderView() -> UIImage {
        let renderer = UIGraphicsImageRenderer(size: bounds.size)
        let image = renderer.image { rendererContext in
            drawHierarchy(in: bounds, afterScreenUpdates: true)
        }
        return image
    }
}
extension UIImage {
    // 来自:https://stackoverflow.com/a/34596653/6257435
    func getPixelColor(point: CGPoint) -> UIColor? {
        guard let cgImage = cgImage else { return nil }
        
        if point.x < 0 || point.x > size.width || point.y < 0 || point.y > size.height {
            return nil
        }
        
        let width = Int(size.width)
        let height = Int(size.height)
        let colorSpace = CGColorSpaceCreateDeviceRGB()
        
        guard let context = CGContext(data: nil,
                                      width: width,
                                      height: height,
                                      bitsPerComponent: 8,
                                      bytesPerRow: width * 4,
                                      space: colorSpace,
                                      bitmapInfo: CGBitmapInfo.byteOrder32Little.rawValue | CGImageAlphaInfo.premultipliedFirst.rawValue)
        else {
            return nil
        }
        
        context.draw(cgImage, in: CGRect(origin: .zero, size: size))
        
        guard let pixelBuffer = context.data else { return nil }
        
        let pointer = pixelBuffer.bindMemory(to: UInt32.self, capacity: width * height)
        let pixel = pointer[Int(point.y) * width + Int(point.x)]
        
        let r: CGFloat = CGFloat(red(for: pixel))   / 255
        let g: CGFloat = CGFloat(green(for: pixel)) / 255
        let b: CGFloat = CGFloat(blue(for: pixel))  / 255
        let a: CGFloat = CGFloat(alpha(for: pixel)) / 255
        
        return UIColor(red: r, green: g, blue: b, alpha: a)
    }
    
    private func alpha(for pixelData: UInt32) -> UInt8 {
        return UInt8((pixelData >> 24) & 255)
    }
    private func red(for pixelData: UInt32) -> UInt8 {
        return UInt8((pixelData >> 16) & 255)
    }
    private func green(for pixelData: UInt32) -> UInt8 {
        return UInt8((pixelData >> 8) & 255)
    }
    private func blue(for pixelData: UInt32) -> UInt8 {
        return UInt8((pixelData >> 0) & 255)
    }
    private func rgba(red: UInt8, green: UInt8, blue: UInt8, alpha: UInt8) -> UInt32 {
        return (UInt32(alpha) << 24) | (UInt32(red) << 16) | (UInt32(green) << 8) | (UInt32(blue) << 0)
    }
}

我们可以调用:

let theColor = someView.colorAt(point: CGPoint(x: 10, y: 10))

然后我们将得到我们期望的结果。

由于需要“以UIImage形式捕获”,我们不希望反复调用它 - 例如,如果我们沿着渐变拖动以获取当前颜色... 如果可能的话,我们希望将视图呈现为UIImage 一次,然后重复调用preRenderedImage.getPixelColor(point: pt)

以下是一个快速示例...

运行时将如下所示:

Swift CAGradientLayer显示的颜色不准确。 Swift CAGradientLayer显示的颜色不准确。

Swift CAGradientLayer显示的颜色不准确。 Swift CAGradientLayer显示的颜色不准确。

我们有2个CAGradientLayer视图... 第一个使用Red -> secondColor,第二个使用secondColor -> secondColor(因此它看起来是实心的)。

第三个视图有一个“左半部分”CALayer和一个“右半部分”CALayer,第四个视图是一个普通的UIView,其.backgroundColor设置为color2

按钮会循环显示红色、绿色、蓝色、黄色作为第二个颜色。

当我们触摸/拖动虚线时,我们将获得相同x坐标上每个视图的RGBA值(在中心y处),并在按钮下方的标签中显示结果。

使用上述扩展与以下代码...

View Controller

// 请参考原始文本,代码太长,无法一次性翻译完毕。

UIView子类

// 请参考原始文本,代码太长,无法一次性翻译完毕。

<details>
<summary>英文:</summary>
The issue you are running into is the difference between `RGBA` and `Display P3` or `Extended sRGBA`. 
Using your approach with `CGContext` and a `CAGradientLayer`, for example, we get back the Display P3 values.
To get the &quot;traditional&quot; 8-bits-per-component values, we can first render the view to a `UIImage` and then get the RGBA values from a point in the image.
Using these two extensions:
extension UIView {
func colorAt(point: CGPoint) -&gt; UIColor? {
return renderView().getPixelColor(point: point)
}
func renderView() -&gt; UIImage {
let renderer = UIGraphicsImageRenderer(size: bounds.size)
let image = renderer.image { rendererContext in
drawHierarchy(in: bounds, afterScreenUpdates: true)
}
return image
}
}
extension UIImage {
// from: https://stackoverflow.com/a/34596653/6257435
func getPixelColor(point: CGPoint) -&gt; UIColor? {
guard let cgImage = cgImage else { return nil }
if point.x &lt; 0 || point.x &gt; size.width || point.y &lt; 0 || point.y &gt; size.height {
return nil
}
let width = Int(size.width)
let height = Int(size.height)
let colorSpace = CGColorSpaceCreateDeviceRGB()
guard let context = CGContext(data: nil,
width: width,
height: height,
bitsPerComponent: 8,
bytesPerRow: width * 4,
space: colorSpace,
bitmapInfo: CGBitmapInfo.byteOrder32Little.rawValue | CGImageAlphaInfo.premultipliedFirst.rawValue)
else {
return nil
}
context.draw(cgImage, in: CGRect(origin: .zero, size: size))
guard let pixelBuffer = context.data else { return nil }
let pointer = pixelBuffer.bindMemory(to: UInt32.self, capacity: width * height)
let pixel = pointer[Int(point.y) * width + Int(point.x)]
let r: CGFloat = CGFloat(red(for: pixel))   / 255
let g: CGFloat = CGFloat(green(for: pixel)) / 255
let b: CGFloat = CGFloat(blue(for: pixel))  / 255
let a: CGFloat = CGFloat(alpha(for: pixel)) / 255
return UIColor(red: r, green: g, blue: b, alpha: a)
}
private func alpha(for pixelData: UInt32) -&gt; UInt8 {
return UInt8((pixelData &gt;&gt; 24) &amp; 255)
}
private func red(for pixelData: UInt32) -&gt; UInt8 {
return UInt8((pixelData &gt;&gt; 16) &amp; 255)
}
private func green(for pixelData: UInt32) -&gt; UInt8 {
return UInt8((pixelData &gt;&gt; 8) &amp; 255)
}
private func blue(for pixelData: UInt32) -&gt; UInt8 {
return UInt8((pixelData &gt;&gt; 0) &amp; 255)
}
private func rgba(red: UInt8, green: UInt8, blue: UInt8, alpha: UInt8) -&gt; UInt32 {
return (UInt32(alpha) &lt;&lt; 24) | (UInt32(red) &lt;&lt; 16) | (UInt32(green) &lt;&lt; 8) | (UInt32(blue) &lt;&lt; 0)
}
}
We can call:
let theColor = someView.colorAt(point: CGPoint(x: 10, y: 10))
and we&#39;ll get back what we were expecting.
Because of the need to &quot;capture as `UIImage`&quot; we don&#39;t want to be calling that over and over - such as if we&#39;re dragging along a gradient to get the current color... Instead, if possible, we&#39;d want to render the view to a `UIImage` **once** and then repeatedly call `prerenderedImage.getPixelColor(point: pt)`.
Here&#39;s a quick example...
It will look like this when running:
[![enter image description here][1]][1] [![enter image description here][2]][2]
[![enter image description here][3]][3] [![enter image description here][4]][4]
We have 2 `CAGradientLayer` views... the first one using `Red -&gt; secondColor` and the second one using `secondColor -&gt; secondColor` (so it appear solid).
The 3rd view has a &quot;left-half&quot; `CALayer` and a &quot;right-half&quot; `CALayer` and the 4th view is a plain `UIView` with the `.backgroundColor` set.
The button cycles through Red, Green, Blue, Yellow as the second-colors.
When we touch / drag the dashed-line, we&#39;ll get the RGBA values from the same x-coordinate on each view (at center-y) and show the results in the label below the button.
Use the above extensions with this code...
**View Controller**
class ColorAtPointViewController: UIViewController {
// CAGradientLayer from color1 to color2
let gradientView1 = MyGradientView()
// CAGradientLayer from color2 to color2 (will appear solid)
let gradientView2 = MyGradientView()
// left-half CALayer color1 / right-half CALayer color2
let layerView = MyLayerView()
// plain UIView with .backgroundColor set to color2
let bkgView = MyBackgroundView()
// a dash-line to show the touch-point
let lineView = MyLineView()
// where we&#39;ll show the RGBA values
let outputLabel = UILabel()
// button to cycle through the 2nd colors
var btn: UIButton!
// references to the 4-variations of views (for convenience)
var views: [UIView] = []
// we&#39;ll &quot;cache&quot; the views, rendered to UIImages
var renderedViews: [UIImage] = []
let secondColors: [UIColor] = [
UIColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0),
UIColor(red: 0.0, green: 1.0, blue: 0.0, alpha: 1.0),
UIColor(red: 0.0, green: 0.0, blue: 1.0, alpha: 1.0),
UIColor(red: 1.0, green: 1.0, blue: 0.0, alpha: 1.0),
]
let secondColorNames: [String] = [
&quot;Red&quot;, &quot;Green&quot;, &quot;Blue&quot;, &quot;Yellow&quot;,
]
var c2IDX: Int = 0
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor(white: 0.95, alpha: 1.0)
// references to the views
views = [gradientView1, gradientView2, layerView, bkgView]
let strs: [String] = [
&quot;CAGradientLayer View1 (red -&gt; color2)&quot;,
&quot;CAGradientLayer View2 (color2 -&gt; color2)&quot;,
&quot;CALayer View (left red, right color2)&quot;,
&quot;Background Color View (color2)&quot;
]
let stackView = UIStackView()
stackView.axis = .vertical
stackView.spacing = 4
for (str, v) in zip(strs, views) {
let label = UILabel()
label.text = str
v.heightAnchor.constraint(equalToConstant: 40.0).isActive = true
stackView.addArrangedSubview(label)
stackView.addArrangedSubview(v)
stackView.setCustomSpacing(20.0, after: v)
}
[stackView, lineView].forEach { v in
v.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(v)
}
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
stackView.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
stackView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
stackView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
lineView.topAnchor.constraint(equalTo: gradientView1.topAnchor, constant: -8.0),
lineView.leadingAnchor.constraint(equalTo: stackView.leadingAnchor, constant: 0.0),
lineView.trailingAnchor.constraint(equalTo: stackView.trailingAnchor, constant: 0.0),
lineView.bottomAnchor.constraint(equalTo: bkgView.bottomAnchor, constant: 12.0),
])
var config = UIButton.Configuration.filled()
config.buttonSize = .medium
config.cornerStyle = .medium
config.title = &quot;Change 2nd Color to&quot;
btn = UIButton(configuration: config)
btn.addAction (
UIAction { _ in
self.nextColor()
}, for: .touchUpInside
)
outputLabel.numberOfLines = 0
outputLabel.font = .systemFont(ofSize: 13, weight: .regular)
outputLabel.text = &quot;RGBA at X:&quot;
[btn, outputLabel].forEach { v in
v.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(v)
}
NSLayoutConstraint.activate([
btn.topAnchor.constraint(equalTo: stackView.bottomAnchor, constant: 40.0),
btn.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
btn.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
outputLabel.topAnchor.constraint(equalTo: btn.bottomAnchor, constant: 20.0),
outputLabel.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
outputLabel.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
])
c2IDX = -1
nextColor()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
lineView.x = gradientView1.bounds.midX
gotTouch(lineView.x)
}
func genImages() {
// render the views to images each time we change the colors
//	so we don&#39;t re-render them every time we want to get a color at a point
renderedViews = []
views.forEach { v in
renderedViews.append(v.renderView())
}
}
override func touchesBegan(_ touches: Set&lt;UITouch&gt;, with event: UIEvent?) {
guard let t = touches.first else { return }
let x = t.location(in: gradientView1).x
guard x &gt;= 0.0, x &lt;= gradientView1.bounds.maxX else { return }
gotTouch(x)
}
override func touchesMoved(_ touches: Set&lt;UITouch&gt;, with event: UIEvent?) {
guard let t = touches.first else { return }
let x = t.location(in: gradientView1).x
guard x &gt;= 0.0, x &lt;= gradientView1.bounds.maxX else { return }
gotTouch(x)
}
func gotTouch(_ x: CGFloat) {
var outputStr: String = &quot;RGBA at X: &quot;
if UIScreen.main.scale == 3 {
// if the screen scale is @3x - such as an iPhone 14 Pro - we get 1/3 points
//	so, display as .000 or .333 or .667 instead of .666666666667
outputStr += &quot;\(String(format: &quot;%0.3f&quot;, x))\n&quot;
} else {
// @2x scale, so display as .0 or .5
outputStr += &quot;\(String(format: &quot;%0.1f&quot;, x))\n&quot;
}
let strs: [String] = [&quot;G1&quot;, &quot;G2&quot;, &quot;L&quot;, &quot;B&quot;]
for (str, img) in zip(strs, renderedViews) {
let pt: CGPoint = .init(x: x, y: img.size.height * 0.5)
if let c = img.getPixelColor(point: pt) {
// change &quot;UIExtendedSRGBColorSpace 1 0 0 1&quot; to &quot;RGBA  1  0  0  1&quot;
//	just so we can focus on the color values
let s = &quot;\(c)&quot;.replacingOccurrences(of: &quot;UIExtendedSRGBColorSpace&quot;, with: &quot;RGBA&quot;)
.replacingOccurrences(of: &quot; &quot;, with: &quot;  &quot;)
outputStr += &quot;\(str):\t\(s)\n&quot;
}
}
lineView.x = x
outputLabel.text = outputStr
}
func nextColor() {
// cycle to the next &quot;second color&quot;
self.c2IDX += 1
let c = self.secondColors[self.c2IDX % self.secondColors.count]
self.views.forEach { v in
if let v = v as? MyBaseView {
v.c2 = c
}
}
// gradientView2 uses color2 -&gt; color2 to appear &quot;solid&quot;
self.gradientView2.c1 = c
// let the views&#39; layers update before we render new images from the views
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1, execute: {
// re-render the views
self.genImages()
// simiulate touch at last touch-point
self.gotTouch(self.lineView.x)
// update the button label
let cName = self.secondColorNames[(self.c2IDX + 1) % self.secondColorNames.count]
self.btn.configuration?.title = &quot;Change 2nd Color to \(cName)&quot;
})
}
}
**UIView subclasses**
class MyBaseView: UIView {
var c1: UIColor = .red { didSet { colorChanged() } }
var c2: UIColor = .red { didSet { colorChanged() } }
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() {
}
func colorChanged() {
}
}
class MyGradientView: MyBaseView {
let gradLayer = CAGradientLayer()
override func commonInit() {
super.commonInit()
gradLayer.startPoint = CGPoint(x: 0.0, y: 0.0)
gradLayer.endPoint = CGPoint(x: 1, y: 0)
gradLayer.colors = [c1.cgColor, c2.cgColor]
layer.addSublayer(gradLayer)
}
override func layoutSubviews() {
super.layoutSubviews()
gradLayer.frame = bounds
}
override func colorChanged() {
super.colorChanged()
CATransaction.begin()
CATransaction.setDisableActions(true)
gradLayer.colors = [c1.cgColor, c2.cgColor]
CATransaction.commit()
}
}
class MyLayerView: MyBaseView {
let myLayer1 = CALayer()
let myLayer2 = CALayer()
override func commonInit() {
super.commonInit()
myLayer1.backgroundColor = c1.cgColor
myLayer2.backgroundColor = c2.cgColor
layer.addSublayer(myLayer1)
layer.addSublayer(myLayer2)
}
override func layoutSubviews() {
super.layoutSubviews()
var r = bounds
r.size.width *= 0.5
myLayer1.frame = r
r.origin.x = r.size.width
myLayer2.frame = r
}
override func colorChanged() {
super.colorChanged()
CATransaction.begin()
CATransaction.setDisableActions(true)
myLayer1.backgroundColor = c1.cgColor
myLayer2.backgroundColor = c2.cgColor
CATransaction.commit()
}
}
class MyBackgroundView: MyBaseView {
override func commonInit() {
super.commonInit()
backgroundColor = c2
}
override func colorChanged() {
super.colorChanged()
backgroundColor = c2
}
}
class MyLineView: UIView {
var x: CGFloat = 0 { didSet { setNeedsLayout() } }
// this allows us to use the &quot;base&quot; layer as a shape layer
//	instead of adding a sublayer
lazy var shapeLayer: CAShapeLayer = self.layer as! CAShapeLayer
override class var layerClass: AnyClass {
return CAShapeLayer.self
}
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() {
layer.masksToBounds = true
shapeLayer.strokeColor = UIColor.gray.cgColor
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.lineWidth = 1
shapeLayer.lineDashPattern = [8, 8]
}
override func layoutSubviews() {
super.layoutSubviews()
let bez = UIBezierPath()
bez.move(to: .init(x: x, y: bounds.minY))
bez.addLine(to: .init(x: x, y: bounds.maxY))
CATransaction.begin()
CATransaction.setDisableActions(true)
shapeLayer.path = bez.cgPath
CATransaction.commit()
}
}
[1]: https://i.stack.imgur.com/VTEYp.png
[2]: https://i.stack.imgur.com/y2tzN.png
[3]: https://i.stack.imgur.com/Qvac2.png
[4]: https://i.stack.imgur.com/qrq05.png
</details>
# 答案2
**得分**: 0
以下是翻译好的内容:
"that's odd! Is this the only code that involves with this part of code? I just tested and got true result :
这很奇怪!这是唯一涉及到这部分代码的吗?我刚刚测试并获得了正确的结果:
Copy and paste this code in a new Xcode project and check if you still get the wrong result.
复制并粘贴这段代码到一个新的Xcode项目中,然后检查是否仍然得到错误的结果。
import UIKit
class ViewController: UIViewController {
let gradientLayer2 = CAGradientLayer()
let slider = UISlider(frame: CGRect(x: 10, y: 400, width: 100, height: 50))
override func viewDidLoad() {
super.viewDidLoad()
slider.maximumValue = 1
slider.minimumValue = 0
slider.addTarget(self, action: #selector(sliderChanged), for: .valueChanged)
slider.backgroundColor = .red
gradientLayer2.frame.size = CGSize(width: 200, height: 200)
gradientLayer2.colors = [
UIColor(red: 1.00, green: 0.00, blue: 0.00, alpha: 1.00).cgColor,
UIColor(red: 1.00, green: 0.00, blue: 0.00, alpha: 1.00).cgColor
]
gradientLayer2.startPoint = CGPoint(x: 0.0, y: 0.0)
gradientLayer2.endPoint = CGPoint(x: 1, y: 0)
gradientLayer2.cornerRadius = 20
view.layer.insertSublayer(gradientLayer2, at: 0)
view.addSubview(slider)
}
@objc func sliderChanged()
{
gradientLayer2.colors = [
UIColor(red: 1.00, green: 0.00, blue: 0.00, alpha: 1.00).cgColor,
UIColor(red: CGFloat(slider.value), green: 0.00, blue: 0.00, alpha: 1.00).cgColor
]
print(gradientLayer2.colors)
}"
希望对你有所帮助。
<details>
<summary>英文:</summary>
that&#39;s odd! Is this the only code that involves with this part of code? I just tested and got true result :
Optional([&lt;CGColor 0x6000002bd6e0&gt; [&lt;CGColorSpace 0x6000002b9980&gt; (kCGColorSpaceICCBased; kCGColorSpaceModelRGB; sRGB IEC61966-2.1; extended range)] ( 1 0 0 1 ), &lt;CGColor 0x6000002bd2c0&gt; [&lt;CGColorSpace 0x6000002b9980&gt; (kCGColorSpaceICCBased; kCGColorSpaceModelRGB; sRGB IEC61966-2.1; extended range)] ( 1 0 0 1 )])
Copy and paste this code in a new Xcode project and check if you still get the wrong result.
import UIKit
class ViewController: UIViewController {
let gradientLayer2 = CAGradientLayer()
let slider = UISlider(frame: CGRect(x: 10, y: 400, width: 100, height: 50))
override func viewDidLoad() {
super.viewDidLoad()
slider.maximumValue = 1
slider.minimumValue = 0
slider.addTarget(self, action: #selector(sliderChanged), for: .valueChanged)
slider.backgroundColor = .red
gradientLayer2.frame.size = CGSize(width: 200, height: 200)
gradientLayer2.colors = [
UIColor(red: 1.00, green: 0.00, blue: 0.00, alpha: 1.00).cgColor,
UIColor(red: 1.00, green: 0.00, blue: 0.00, alpha: 1.00).cgColor
]
gradientLayer2.startPoint = CGPoint(x: 0.0, y: 0.0)
gradientLayer2.endPoint = CGPoint(x: 1, y: 0)
gradientLayer2.cornerRadius = 20
view.layer.insertSublayer(gradientLayer2, at: 0)
view.addSubview(slider)
}
@objc func sliderChanged()
{
gradientLayer2.colors = [
UIColor(red: 1.00, green: 0.00, blue: 0.00, alpha: 1.00).cgColor,
UIColor(red: CGFloat(slider.value), green: 0.00, blue: 0.00, alpha: 1.00).cgColor
]
print(gradientLayer2.colors)
}
}
</details>

huangapple
  • 本文由 发表于 2023年3月3日 23:32:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/75629031.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定