【问题标题】:How to create a line width of 0.5 pixels如何创建0.5像素的线宽
【发布时间】:2014-02-04 12:07:26
【问题描述】:

在 iOS 7 中,table view 的分隔线比以前的 iOS 更细,看起来像 0.5 px 的宽度。

我需要将一个单元格拆分为 2,使用类似的分隔线(仅垂直),我希望这条线与常规分隔线的宽度相同。

所以我想知道添加这样一行的最佳方法是什么?

如果我使用UIView 并将其宽度设置为 0.5,它将不可见,如果我将其宽度设置为 1.0,那么我当然会得到 1.0px 而不是 0.5px 的线宽。

我尝试使用视网膜大小为 1.0 像素的资源,但它也不起作用

【问题讨论】:

  • 0.5 像素实际上是不可能的。我认为您的意思是视网膜显示器上的 1 px,即 0.5 pt(点)。

标签: ios iphone objective-c uitableview


【解决方案1】:

您将宽度设置为 0.5 - 或使其始终为 1 像素,然后将其设置为 (1.0 / [UIScreen mainScreen].scale)

我以前做过,效果很好

我认为您看不到它的原因是您将线准确地居中在屏幕中间,这将使线的原点 (320 - 0.5) / 2.0,成为 159.75 的 X 原点 - 0.75 可能会搞砸 - 或者单元格正在删除视图的背景颜色

【讨论】:

  • 这不适用于 iPhone Plus 机型,因为 nativeScale 小于 scale,但它确实适用于 iPhone X,因为两者都是 3.0。
【解决方案2】:

我做了这些步骤:

  1. 创建一个高度为 1 像素的约束
  2. 将约束与 IBOutlet(文件 .m)连接
  3. 在 ViewDidLoad 中将约束的常量更改为 0.5

它对我有用。

【讨论】:

  • 工作正常,除了我必须将它添加到 viewDidAppear 而不是 viewDidLoad
  • 是的,因为你必须等待创建所有约束然后更新它。
  • 您可以在 viewDidLayoutSubviews 调用以尽早开始
  • 当你这样设置 0.5 pt 时,\@1x- 和 \@3x-devices 会发生什么?它将尝试为 \@1x(非视网膜)显示 0.5px,这是不可能的,而对于 iPhone Plus 型号,这也是不可能的 1.5px。它是向上取整到 1px 和 2px,还是向下取整到 0px 和1像素?会有抗锯齿问题吗?例如故障/滞后/闪烁的线条?
【解决方案3】:

假设您使用 Storyboard 进行单元格布局:

将具有所需高度和 1px 宽度的 UIView 放入单元格中。给它你想要的任何背景颜色。标准分隔符颜色约为。 RGB(200,199,204)。

然后创建一个 UIView 的子类,例如HairlineView 并覆盖 awakeFromNib()

-(void)awakeFromNib {
    self.layer.borderColor = [self.backgroundColor CGColor];
    self.layer.borderWidth = (1.0 / [UIScreen mainScreen].scale) / 2;

    self.backgroundColor = [UIColor clearColor];
}

您正在 1px 宽的视图周围绘制边框,即 2 * 0.25px 宽,使其总共 0.5px,这是您想要实现的宽度,然后通过将背景设置为隐藏视图的背景清除。最后一步很重要,没有它就行不通。

将视图的类型设置为 HairlineView,然后它应该可以工作。

以编程方式执行此操作时,您必须覆盖不同的方法,例如initWithFrame() 也许,因为 awakeFromNib() 仅在您从 Storyboard 布局创建视图时被调用。

【讨论】:

  • 这几乎可以完美运行。除了在视图的开头,1 像素的线粗度为 1.0,然后在视图的其余部分下降到 0.5
  • 在 1x 和 2x 上工作,但不是 3x。
  • 没有必要将 1.0 的宽度除以 2。这会使线条的颜色比预期的要浅。在 iOS 8 及更高版本上,正确的方法是使用= (1.0 / [UIScreen mainScreen].nativeScale)。这将给出:1x 设备的 1pt(和 1px),2x 设备的 0.5pt(和 1px),3x 下采样设备(6 plus,7 plus...)的 0.38pt(和 1px)和 0.33 pt(和 1px)适用于 3x 设备 (iPhone X)。
  • 如前所述,我创建了一个 IBInspectable HairlineView。我发现使用它的最佳方法是:向其父视图添加 3 侧对齐约束。如果它用作两个视图之间的分隔线,则这两个视图应该彼此相邻,并且 HairlineView 在它们之上。因此视图不会移动 0.5pt。
  • 这是非常错误的。边框位于外侧。如果你使用这个解决方案,你最终会得到 2 条线(0.25px 或 0.16px)被 (1 - 2*line_thickness) 空白空间隔开。请参阅下面的答案以轻松解决此问题。
【解决方案4】:

上面的一些答案已经是正确的,但只是一个更新:在 Xcode 8 中,现在您可以使用十进制数设置布局约束常量。不再需要连接 IBOutlet 或通过用户定义的运行时属性设置常量。

【讨论】:

  • 前段时间为我工作,但现在将其四舍五入为零(xCode 8.3.3)
  • 这是不正确的,因为对于@3x 设备,您希望将其设为 0.33(3)。请参阅下面的答案。
  • @RaimundasSakalauskas 如果 OP 的意思是“0.5 点”,我的回答是正确的,因为“0.5 像素”是不可能的。
  • 0.5px 是可能的,它会被 iOS 渲染,因为抗锯齿正在应用于视图。虽然我可能打赌他们的意思是 1px(以匹配 TableViewCell 拆分器的厚度)。那么你的答案对于 2x 屏幕来说是正确的,但总的来说它是不正确的,因为现在很多设备都有 3x 比例。
【解决方案5】:

你可以用十进制数设置布局约束的常量,但是 UIBuilder 在 Xcode 8,9,10 中有一些 bug

我的解决方案:

  1. 通过源代码打开xib文件]
  2. 找到你的布局约束常量并更改为 0.5

【讨论】:

  • 和上面一样,不能设为固定值,必须计算,因为@3x会导致不同的值。
【解决方案6】:

您可以在情节提要height 0.5f 中设置约束;它不会直接可见,但它在约束列表中可见,如屏幕截图

【讨论】:

  • 在 3x 屏幕上,有时是 2px 高,有时是 1px 高。
  • 我创建了一个 HairlineView 类似 Irina 的答案,并将以下代码放入 awakeFromNib 以更改约束。 - (void)awakeFromNib { [super awakeFromNib]; for (NSLayoutConstraint *constraint in self.constraints) { if (constraint.constant == 0.5f) { constraint.constant = (1.0 / [UIScreen mainScreen].scale); } } }
【解决方案7】:

你可以使用Core Graphics来绘制渐变:

UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 1.0f)];
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = view.bounds;
gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor whiteColor] CGColor], (id)[[UIColor blackColor] CGColor], nil];
[view.layer insertSublayer:gradient atIndex:0];

【讨论】:

    【解决方案8】:

    我的做法:

    public extension UIView {
        
        func thinDivider() {
            for c in constraints {
                if c.constant == 1 {
                    c.constant = (1.0 / UIScreen.main.scale)
                }
            }
        }
        
    }
    

    明智地使用(仅用于分隔线)。

    注意:只需将高度约束设置为 1 并从代码中调用 view.thinDivider()。这是一种懒惰的解决方案,可以避免为您需要的每个高度限制设置出口。

    旁注:在情节提要编辑器中将高度设置为 0.5 在构建和视图变得不可见后重置为 0

    【讨论】:

      【解决方案9】:

      我的解决方案:

      1. 创建一个视图,给视图设置一个约束:“height = 0px”,进入“身份检查器”,编辑这个约束的优先级为750。

      2. 然后选择视图并单击“pin”按钮,向该视图添加另一个约束:“height = 0.5”,优先级为 1000。在“Identity Inspector”中,您可以看到第二个约束自动变为“高度 >= 0.5"

      适用于 Xcode 7.3.1

      【讨论】:

        【解决方案10】:

        您将视图放在底部的单元格中。并将其设置为视图的深色。并将其高度设置为 0.5 PX。您可以在其中获取每个单元格的分隔符。根据单元格宽度保持其宽度。

        【讨论】:

          【解决方案11】:

          而不是尝试根据分隔符样式设置视图高度。删除分隔符。 将单元格分隔符样式设置为 StyleNone。
          然后在单元格的中间和底部添加两个高度为 0.5 或 1 像素的视图。现在它看起来都相同并且具有分隔符样式。

          【讨论】:

            【解决方案12】:

            诡计:

            1. 在情节提要或 xib 中,为行高约束设置一个唯一值(例如 123)
            2. 使用文本编辑器打开故事板或 xib
            3. 将唯一值(例如 123)替换为 0.5

            【讨论】:

              【解决方案13】:

              我使用这个类来绘制 1 个像素线(不是 1 个点,而是一个像素)。

              class HairlineView: UIView {
                  override func awakeFromNib() {
                      super.awakeFromNib()
              
                      for constraint in self.constraints {
                          if let _ = constraint.firstItem as? HairlineView,
                             constraint.firstAttribute == .height,
                             constraint.firstAnchor.isKind(of: NSLayoutDimension.self),
                             constraint.secondItem == nil,
                             constraint.secondAnchor == nil {
                              constraint.constant = (1.0 / UIScreen.main.scale)
                              return
                          }
                      }
                  }
              }
              

              这样做的先决条件是附加了带有高度约束的 UIView。代码将查看视图的现有约束,找到高度约束并将其值设置为 your_desired_height 以像素为单位(不要与点混淆)。

              通过将 your_desired_height 替换为您需要的任何值,可以轻松地将代码更改为任何值。

              【讨论】:

                【解决方案14】:

                SwiftUI 使用pixelLength 获取屏幕的像素大小,即任何屏幕上的最小线宽和比例。

                struct ContentView: View {
                    @Environment(\.pixelLength) var pixelLength: CGFloat
                
                    var body: some View {
                        Rectangle()
                            .foregroundColor(.clear)
                            .border(Color.black, width: pixelLength)
                     }
                }
                

                【讨论】:

                  【解决方案15】:

                  您可以在 Xcode 8 / iOS 10 中通过以下方式解决此问题,无需使用约束:

                  1. 使用 Interface Builder 在情节提要中添加 UIView。设置你认为合适的属性,只是为了直观地表示它在你的单元格中的外观(即高度 = 44,宽度 = 1)。此时,宽度是否大于您需要的宽度(即 0.5)并不重要。

                  2. 在您的视图控制器中为此视图创建一个 IBOutlet(即 UIView *splitLine)。

                  3. 在视图控制器的 viewWillAppear: 方法中添加以下方法:

                  [self.splitLine setFrame:CGRectMake(x, y, 0.5, 44)];

                  在此方法中,您将分隔线的宽度指定为 0.5,将高度指定为您想要的任何值。这些值会覆盖情节提要中指定的值。

                  【讨论】:

                    猜你喜欢
                    • 2016-05-10
                    • 1970-01-01
                    • 1970-01-01
                    • 2017-07-14
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2016-01-05
                    • 1970-01-01
                    相关资源
                    最近更新 更多