0

I am trying to add a top and bottom border to a uibutton my function to add the border looks like this

    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

this works fine when i call the function in viewDidAppear (but there is a delay then) but when i put it in viewdidlayoutsubviews it adds an additional line, what somehow looks like this enter image description here

i set it up with a leading and trailing space to its superview, what a i doing wrong here?

Markus
  • 693
  • 8
  • 23

1 Answers1

0

The viewDidAppear is executed when you view appears on screen and every time come back from other view controller in your navigation flow. So your code add lines several times. You can review the view controller lifecycle here.

If you want to remove the "delay" and executed once, write your code in the viewDidLoad.

UPDATE

I see two approach. Create a UIButton subclass and then:

  1. If you want to keep working with CALayers, you'll need to call a redraw method always your button change its size. If the change is animated will appear weird artifact.

  2. The good one. I recommend you use the 'drawRect' to paint this lines and use the button frame to calculate line XY dynamically. If you button change its size, animated or not… no problem, Core Animation do all the job.

    - (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:
    

I've attached this source code with lines with CALayer and with UIBezierPath solutions. Touch on buttons and see the difference when they change.

Community
  • 1
  • 1
torcelly
  • 516
  • 4
  • 8
  • thats why i put it into the viewdidlayoutsubviews because at that stage it knows how wide the button will be, whats not the case in the viewdidload – Markus Jul 12 '15 at 10:11
  • You’re right but in the `viewDidLoad` you have the real root view frame. It allow you several approach to solve it. However I recommend you forget CALayer and use `drawRect`. I edited my answer. – torcelly Jul 13 '15 at 17:33
  • hey torcelly, thank you for your afford, I don't know if its just some weird setting of mine but the drawRect Method does the same with this artifact in front of the title inside the button (in your xcode project), but not the calayer solution i will probably use the later one...thank you – Markus Jul 13 '15 at 18:18