Search code examples
iosuiviewbevelled

Add bevel effect to UIView


I want my button to look this.

enter image description here

I asked the designer and he said he has used bevel effect on it and I'm hearing the word bevel for the first time.

I searched Stack Overflow but couldn't find anything helpful.


Solution

  • A bevel is a "sloping surface along the edge of a piece of wood, glass etc". In the computing world we use a "bevel" typically around a button, to give the illusion of 3D. Although there's been a definite trend since iOS7 to prefer a flatter look.

    When you say you wish to apply a bevel to a UI view, you're referring to the gradient around the edge. I've highlighted this in red, in the image below.

    Highlighted bevel

    When you say you want your button to look like your image, the bevel might only be part of that goal.

    As has already been suggested, the quickest and easiest way to make your button look like that, would be to use an image of the button, and apply this to your view. This is probably more efficient way of doing it too. Alternatively, it is possible to create the button using code. Although you would need the button in a vector format.

    In order generate the button in code, you would need to ask your designer for the button in a vector format. The SVG format would probably be easiest. There are a number of third party programs that can convert vector images to Core Graphics code. For this example, I've used a program called Graphic (by Autodesk). Although, I had to fix a couple of bugs in its generated code. A more up to date alternative may be better. I've not tried Graphic to generate code in Swift.

    Here's my example of a button, which is similar to your design. This code is a proof of concept, so the button isn't sized or positioned very well. I've not spent too long matching my button to your exact design. However, it will produce a view with a similar button in it.

    #import "Button.h"
    #import <CoreText/CoreText.h>
    
    @implementation Button
    
    - (void)drawRect:(CGRect)rect {
    
        // Do any additional setup after loading the view, typically from a nib.
    
        CGContextRef ctx = UIGraphicsGetCurrentContext();
        // enable the following lines for flipped coordinate systems
        //CGContextTranslateCTM(ctx, 0, self.bounds.size.height);
        //CGContextScaleCTM(ctx, 1, -1);
        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    
        /*  Shape   */
        CGMutablePathRef pathRef = CGPathCreateMutable();
        CGPathMoveToPoint(pathRef, NULL, 251.424, 272.035);
        CGPathAddCurveToPoint(pathRef, NULL, 251.424, 288.189, 238.328, 301.285, 222.174, 301.285);
        CGPathAddCurveToPoint(pathRef, NULL, 206.02, 301.285, 192.924, 288.189, 192.924, 272.035);
        CGPathAddCurveToPoint(pathRef, NULL, 192.924, 255.881, 206.02, 242.785, 222.174, 242.785);
        CGPathAddCurveToPoint(pathRef, NULL, 238.328, 242.785, 251.424, 255.881, 251.424, 272.035);
        CGPathCloseSubpath(pathRef);
    
        /*  Gradient Fill  */
        CGContextSaveGState(ctx);
        CGContextAddPath(ctx, pathRef);
        CGContextClip(ctx);
    
        CGFloat gradientColors[] = {
            0.549, 0.557, 0.565, 1,
            0, 0, 0, 1 };
        CGFloat gradientLocations[] = { 0, 0.973 };
    
        CGGradientRef gradientRef = CGGradientCreateWithColorComponents(colorSpace, gradientColors, gradientLocations, 2);
        CGContextDrawLinearGradient(ctx, gradientRef, CGPointMake(201.492, 251.353), CGPointMake(242.857, 292.719), (kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation));
        CGGradientRelease(gradientRef);
        CGContextRestoreGState(ctx);
    
        CGPathRelease(pathRef);
    
        /*  Shape 2  */
        CGMutablePathRef pathRef2 = CGPathCreateMutable();
        CGPathMoveToPoint(pathRef2, NULL, 247.069, 272.035);
        CGPathAddCurveToPoint(pathRef2, NULL, 247.069, 285.784, 235.923, 296.93, 222.174, 296.93);
        CGPathAddCurveToPoint(pathRef2, NULL, 208.425, 296.93, 197.279, 285.784, 197.279, 272.035);
        CGPathAddCurveToPoint(pathRef2, NULL, 197.279, 258.286, 208.425, 247.14, 222.174, 247.14);
        CGPathAddCurveToPoint(pathRef2, NULL, 235.923, 247.14, 247.069, 258.286, 247.069, 272.035);
        CGPathCloseSubpath(pathRef2);
    
        /*  Gradient Fill  */
        CGContextSaveGState(ctx);
        CGContextAddPath(ctx, pathRef2);
        CGContextClip(ctx);
    
        CGFloat gradientColors2[] = {
            0.165, 0.153, 0.153, 1,
            0, 0, 0, 0.651 };
        CGFloat gradientLocations2[] = { 0.897, 0.991 };
    
        CGGradientRef gradientRef2 = CGGradientCreateWithColorComponents(colorSpace, gradientColors2, gradientLocations2, 2);
        CGContextDrawRadialGradient(ctx, gradientRef2, CGPointMake(222.174, 272.035), 0, CGPointMake(222.174, 272.035), 24.895, (kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation));
        CGGradientRelease(gradientRef2);
        CGContextRestoreGState(ctx);
    
        CGPathRelease(pathRef2);
    
        /*  Text   */
        UIColor *colour = [UIColor colorWithRed:1 green:1 blue:1 alpha:1];
        NSMutableAttributedString *attributedStr = [[NSMutableAttributedString alloc] initWithString:@"STOP"];
        NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
        paragraphStyle.alignment = NSTextAlignmentLeft;
        NSDictionary *textAttribs = @{
                                      NSFontAttributeName: [UIFont fontWithName:@"Helvetica" size:10],
                                      NSForegroundColorAttributeName: colour,
                                      NSParagraphStyleAttributeName: paragraphStyle
                                      };
        [attributedStr setAttributes:textAttribs range:NSMakeRange(0, 4)];
    
    
        CGRect textBox = CGRectMake(208.736, 270.375, 28.051, 14);
        CGPathRef textBoxPath = CGPathCreateWithRect(CGRectMake(0, 0, textBox.size.width, textBox.size.height), NULL);
        CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attributedStr);
        CTFrameRef frameRef = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), textBoxPath, NULL);
        CGContextSaveGState(ctx);
        CGContextTranslateCTM(ctx, textBox.origin.x, textBox.origin.y);
    
        CGContextSetTextMatrix(ctx, CGAffineTransformIdentity);
        CGContextTranslateCTM(ctx, 0.0, textBox.size.height);
        CGContextScaleCTM(ctx, 1.0, -1.0);
        CTFrameDraw(frameRef, ctx);
    
        CGContextRestoreGState(ctx);
        CGPathRelease(textBoxPath);
        CFRelease(framesetter);
        CFRelease(frameRef);
    
        /*  Shape 3  */
        CGMutablePathRef pathRef3 = CGPathCreateMutable();
        CGPathMoveToPoint(pathRef3, NULL, 229.861, 260.812);
        CGPathAddCurveToPoint(pathRef3, NULL, 229.861, 262.987, 228.098, 264.75, 225.923, 264.75);
        CGPathAddLineToPoint(pathRef3, NULL, 218.423, 264.75);
        CGPathAddCurveToPoint(pathRef3, NULL, 216.248, 264.75, 214.485, 262.987, 214.485, 260.812);
        CGPathAddLineToPoint(pathRef3, NULL, 214.485, 260.812);
        CGPathAddCurveToPoint(pathRef3, NULL, 214.485, 258.637, 216.248, 256.874, 218.423, 256.874);
        CGPathAddLineToPoint(pathRef3, NULL, 225.923, 256.874);
        CGPathAddCurveToPoint(pathRef3, NULL, 228.099, 256.875, 229.861, 258.638, 229.861, 260.812);
        CGPathAddLineToPoint(pathRef3, NULL, 229.861, 260.812);
        CGPathCloseSubpath(pathRef3);
    
        CGContextSetRGBFillColor(ctx, 0.514, 0.773, 0.357, 1);
        CGContextAddPath(ctx, pathRef3);
        CGContextFillPath(ctx);
    
        CGPathRelease(pathRef3);
        CGColorSpaceRelease(colorSpace);
    
    }
    
    
    @end
    

    Screenshot of the result in the iOS simulator