【问题标题】:UIView with background color looks different than CALayer with background color. Why, and how to make them match?具有背景颜色的 UIView 看起来与具有背景颜色的 CALayer 不同。为什么,以及如何使它们匹配?
【发布时间】:2022-01-21 13:14:06
【问题描述】:

我创建了一个小项目 (Github link),演示如何在 UITextField 下添加一行以回答 this SO question

OP 试图使用 CALayer 添加下划线,这就是我最初实现该解决方案的方式。对于那个版本,我创建了一个名为“UnderlinedTextField”的UITextField 的自定义子类。该自定义子类创建并维护一个具有背景颜色的 CALayer。

然后我注意到,在文本字段的底部简单地添加一个 1 点 UIView 会更容易。我更新了我的演示项目以说明这种方法。

这两种方法都在UITextField 下方添加了一条 1 点蓝线。基于视图的方法可以完成 Storyboard 中的所有操作,并且不需要任何代码。由于它使用 AutoLayout 约束将下划线视图固定到文本字段的底部,因此即使文本字段移动,约束也会将视图保持在正确的位置。

但是,我注意到基于图层的下划线和基于视图的下划线看起来不同,这是一个截图:

基于图层的下划线看起来更重。仔细看,基于图层的下划线的抗锯齿颜色比基于视图的下划线的抗锯齿颜色深。

为什么会这样,我会改变什么以使它们看起来一样?

(下面是UnderlinedTextField 类的代码,以防你不想去看 Github 仓库)

/// This is a custom subclass of UITextField that adds a 1-point colored underline under the text field using a CALayer.
/// It implments the `layoutSubviews()` method to reposition the underline layer if the text field is moved or resized.
class UnderlinedTextField: UITextField {

    /// Change this color to change the color used for the underline
    public var underlineColor = UIColor.blue {
        didSet {
            underlineLayer.backgroundColor = underlineColor.cgColor
        }
    }

    private let underlineLayer = CALayer()

    /// Size the underline layer and position it as a one point line under the text field.
    func setupUnderlineLayer() {
        var frame = self.bounds
        frame.origin.y = frame.size.height - 1
        frame.size.height = 1

        underlineLayer.frame = frame
        underlineLayer.backgroundColor = underlineColor.cgColor
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        // In `init?(coder:)` Add our underlineLayer as a sublayer of the view's main layer
        self.layer.addSublayer(underlineLayer)
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        // in `init(frame:)` Add our underlineLayer as a sublayer of the view's main layer
        self.layer.addSublayer(underlineLayer)
    }

    // Any time we are asked to update our subviews,
    // adjust the size and placement of the underline layer too
    override func layoutSubviews() {
        super.layoutSubviews()
        setupUnderlineLayer()
    }
}

编辑:

我根据 Matt 的回答更改了我的项目(并推送了更改),以使 Storyboard 使用设备颜色配置文件。这使得下划线的颜色值非常接近,但仍不完全相同。

如果我使用“数字色度计”应用程序检查模拟器中的线条,顶部和底部的线条会略有不同。但是,如果我使用控件 S 将屏幕保存到模拟器中的磁盘(将其保存为全尺寸)并在 PS 中打开生成的图像,则线条显示为无锯齿的纯 sRGB 蓝色。我想将模拟器屏幕映射到 Mac 屏幕会导致 2 行的别名略有不同。

(您必须在 PS 或其他可让您查看像素颜色的应用程序中打开图片以检测两条线的差异。将情节提要的颜色配置文件更改为设备 RGB (sRGB) 后,我看不到差别太大了。)

【问题讨论】:

  • Xcode 和您介绍的资源(即 Adob​​e 的颜色空间定义与 Apple 的定义)中颜色空间的不同使用可能会让人头疼,这就是为什么我总是扩展 UIColor 并定义我自己的颜色使用UIColor(hue:saturation:brightness:alpha:) 以编程方式在 Storyboard 中也可用(使用 HSB 滑块创建自定义颜色),它们将始终保持同步。对于阅读本文的任何 Adob​​e 用户,sRGB 是您要用于 Xcode 资源的色彩空间。
  • @liquid 非常好的观点。我在回答中给出了不同的工作技术,但你的更好,因为它消除了整个问题。
  • @liquid,有时我发现 HSB 颜色空间对描述颜色很有用,而其他时候我想使用 RGB。之前在 PS 中取色时遇到过切换到 sRGB 的需求,所以我应该考虑检查 Storyboard 中的颜色配置文件。令人抓狂的是 IDE 的不同部分使用不同的颜色配置文件。

标签: ios swift uikit calayer


【解决方案1】:

实际上你给了它们不同的颜色。

  • 图层的颜色在代码中设置为UIColor.blue.cgColor

  • 视图的颜色是在情节提要中创建的,并且是

      R:0.02 G:0.2 B:1 A:1
    

    正如在视图调试器中检查它所揭示的那样。

为什么?因为您没有考虑故事板颜色的色彩空间。它是Generic RGB,而您在代码中创建的颜色是Device RGB,即sRGB

查看这一点的另一种方法是进行一些日志记录。在运行的app中,两种颜色分别是

<CGColor 0x60000296aa60> 
[<CGColorSpace 0x60000296ab20> 
    (kCGColorSpaceICCBased; kCGColorSpaceModelRGB; sRGB IEC61966-2.1; extended range)] 
( 0 0 1 1 )>

<CGColor 0x600002976940> 
[<CGColorSpace 0x60000296ab20> 
    (kCGColorSpaceICCBased; kCGColorSpaceModelRGB; sRGB IEC61966-2.1; extended range)] 
( 0.01675 0.198341 1 1 )>

如您所见,第二种颜色已转换为sRGB颜色空间,与您开始使用的Generic RGB不一样,因此转换后我们得到了不同的颜色。

我会改变什么让它们看起来一样

如果您将情节提要颜色的颜色空间设置为 Device RGB,然后将滑块设置为简单的蓝色,那么在运行的应用程序中您最终会得到相同的颜色。

【讨论】:

  • 当然。我应该考虑检查色彩空间。 (故事板默认为通用 RGB,这很烦人。)谢谢马特。 (已投票)
  • 我编辑了我的项目以将 Storyboard 颜色设置为设备 RGB (sRGB) 配置文件,这很有帮助,但基于图层和基于视图的颜色仍然略有不同。如果我使线条多点粗,则中心部分完全匹配,但抗锯齿中的颜色略有不同。它不再足以可见,但它仍然很好奇。此外,由于某种原因,水平“线”(一点内容)上的抗锯齿不是上下对称的,并且图层抗锯齿从视图抗锯齿垂直翻转。
  • 好的,看起来差异是模拟器在 Mac 屏幕上渲染的产物。如果我使用“Digital Color Meter”像素窥视实用程序检查两条线,顶线和底线给出的颜色略有不同(取决于我在模拟器中选择的缩放比例。)如果我改为将全尺寸图像保存到磁盘并在 PS 中打开,我发现两条线都是纯的,0/0/255 蓝线,没有抗锯齿。
  • 你是说如果你在设备上运行它会得到正确的颜色????我没有测试,但也许我应该测试。
猜你喜欢
  • 1970-01-01
  • 2023-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多