【问题标题】:UIButton Top and Bottom Border additional lineUIButton 顶部和底部边框附加行
【发布时间】:2015-07-12 07:22:30
【问题描述】:

我正在尝试将顶部和底部边框添加到 uibutton 我添加边框的函数看起来像这样

    CALayer *topBorder = [CALayer layer];

    topBorder.frame = CGRectMake(os, 1.0f, b.bounds.size.width - (os * 2.0f), 1.0f);

    topBorder.backgroundColor = [c1 CGColor];

    [b.layer addSublayer:topBorder];

    CALayer *bottomBorder = [CALayer layer];

    bottomBorder.frame = CGRectMake(os, b.bounds.size.height, b.bounds.size.width - (os * 2.0f), 1.0f);

    bottomBorder.backgroundColor = [c1 CGColor];

    [b.layer addSublayer:bottomBorder];

    //os..offset, b..uibutton, c1..color

当我在viewDidAppear 中调用函数时,这工作正常(但有延迟)但是当我将它放入viewdidlayoutsubviews 时,它添加了一个额外的行,不知何故看起来像这样

我为它的超级视图设置了一个前导和尾随空格,我在这里做错了什么?

【问题讨论】:

    标签: ios objective-c xcode uibutton


    【解决方案1】:

    viewDidAppear 在您的视图出现在屏幕上并且每次从导航流程中的其他视图控制器返回时执行。因此,您的代码会多次添加行。您可以查看视图控制器生命周期here

    如果您想去掉“延迟”并执行一次,请将您的代码写入viewDidLoad

    更新

    我看到了两种方法。创建一个 UIButton 子类,然后:

    1. 如果你想继续使用 CALayers,你需要调用一个重绘方法,总是你的按钮改变它的大小。如果更改为动画会出现奇怪的伪影。

    2. 好的。我建议您使用“drawRect”来绘制这条线,并使用按钮框架来动态计算线 XY。如果你的按钮改变它的大小,动画与否……没问题,Core Animation 完成所有工作。

      - (void)drawRect:(CGRect)rect
      {
          // Frames
          CGRect frame = self.bounds;
      
          // Parameters (change these values if you want to change appearance)
          UIColor *lineColor = [UIColor colorWithRed: 0.5 green: 0.5 blue: 0.5 alpha: 1];
          CGFloat topRatioPositionY = 0.02;
          CGFloat middleRatioPositionY = 0.6;
          CGFloat bottomRatioPositionY = 0.98;
          CGFloat middleRatioPositionX = 0.33333;
          CGFloat lineWidth = 1.0;
      
          //// Top line
          UIBezierPath* bezierPath = [UIBezierPath bezierPath];
          [bezierPath moveToPoint: CGPointMake(CGRectGetMinX(frame), CGRectGetMinY(frame) + topRatioPositionY * CGRectGetHeight(frame))];
          [bezierPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 1.00000 * CGRectGetWidth(frame), CGRectGetMinY(frame) + topRatioPositionY * CGRectGetHeight(frame))];
          [lineColor setStroke];
          bezierPath.lineWidth = lineWidth;
          [bezierPath stroke];
      
      
          // Middle line
          UIBezierPath* bezier2Path = [UIBezierPath bezierPath];
          [bezier2Path moveToPoint: CGPointMake(CGRectGetMinX(frame), CGRectGetMinY(frame) + bottomRatioPositionY * CGRectGetHeight(frame))];
          [bezier2Path addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 1.00000 * CGRectGetWidth(frame), CGRectGetMinY(frame) + bottomRatioPositionY * CGRectGetHeight(frame))];
          [lineColor setStroke];
          bezier2Path.lineWidth = lineWidth;
          [bezier2Path stroke];
      
      
          // Bottom Line
          UIBezierPath* bezier3Path = [UIBezierPath bezierPath];
          [bezier3Path moveToPoint: CGPointMake(CGRectGetMinX(frame), CGRectGetMinY(frame) + middleRatioPositionY * CGRectGetHeight(frame))];
          [bezier3Path addLineToPoint: CGPointMake(CGRectGetMinX(frame) + middleRatioPositionX * CGRectGetWidth(frame), CGRectGetMinY(frame) + middleRatioPositionY * CGRectGetHeight(frame))];
          [lineColor setStroke];
          bezier3Path.lineWidth = lineWidth;
          [bezier3Path stroke];
      
      }// drawRect:
      

    我已附上此 source code 与 CALayer 和 UIBezierPath 解决方案的行。触摸按钮并查看它们变化时的区别。

    【讨论】:

    • 这就是为什么我将它放入 viewdidlayoutsubviews 的原因,因为在那个阶段它知道按钮的宽度,而在 viewdidload 中却不是这样
    • 你是对的,但是在viewDidLoad 中你有真正的根视图框架。它允许您使用多种方法来解决它。但是我建议你忘记 CALayer 并使用drawRect。我编辑了我的答案。
    • 嘿torcelly,谢谢你的付出,我不知道这是否只是我的一些奇怪的设置,但drawRect方法对按钮内标题前面的这个工件做同样的事情(在您的 xcode 项目),但不是 calayer 解决方案,我可能会使用后者...谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多