我正在尝试创建一个这样的图层:
但是我无法创造这种效果......有人可以帮助我吗?我找不到具有类似结果的教程。
答案 0 :(得分:1)
尽管以编程方式执行此操作可能很复杂,但最简单的解决方案是使用您选择的图形工具制作表示边框的图像,将其添加到项目中,然后使用capInsets
(例如{{ 3}})在调整图像大小之前,从而保留图像的边缘。
如果您想使用resizableImageWithCapInsets
,可能的实现可能类似于:
将Quartz.framework添加到项目中,然后定义UIView
子类,如:
#import <UIKit/UIKit.h>
@interface BoxWithGradientView : UIView
@property (nonatomic) CGFloat radius;
@property (nonatomic) CGFloat lineWidth;
@property (nonatomic) CGPoint offset;
@end
实施方式如下:
#import "BoxWithGradientView.h"
#import <QuartzCore/QuartzCore.h>
@implementation BoxWithGradientView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
_radius = 20.0;
_lineWidth = 10.0;
_offset = CGPointMake(0.0, -2.0);
}
return self;
}
- (void)drawLineInContext:(CGContextRef)context
from:(CGPoint)startPoint
to:(CGPoint)endPoint
usingGradient:(CGGradientRef)gradient
{
CGContextSaveGState(context);
CGContextMoveToPoint(context, startPoint.x, startPoint.y);
CGContextAddLineToPoint(context, endPoint.x, endPoint.y);
CGContextSetLineWidth(context, self.lineWidth);
CGFloat angle = atan2f(endPoint.y - startPoint.y, endPoint.x - startPoint.x);
CGPoint start = CGPointMake(startPoint.x - sinf(angle) * self.lineWidth / 2.0 + self.offset.x,
startPoint.y - cosf(angle) * self.lineWidth / 2.0 + self.offset.y);
CGPoint end = CGPointMake(startPoint.x + sinf(angle) * self.lineWidth / 2.0 + self.offset.x,
startPoint.y + cosf(angle) * self.lineWidth / 2.0 + self.offset.y);
CGContextReplacePathWithStrokedPath(context);
CGContextClip(context);
CGContextDrawLinearGradient(context, gradient, start, end, kCGGradientDrawsAfterEndLocation | kCGGradientDrawsBeforeStartLocation);
CGContextRestoreGState(context);
}
- (void)drawArcInContext:(CGContextRef)context
center:(CGPoint)center
radius:(CGFloat)radius
startAngle:(CGFloat)startAngle
endAngle:(CGFloat)endAngle
clockwise:(BOOL)clockwise
usingGradient:(CGGradientRef)gradient
{
CGContextSaveGState(context);
CGContextAddArc(context, center.x, center.y, radius, startAngle, endAngle, clockwise);
// CGContextMoveToPoint(context, startPoint.x, startPoint.y);
CGContextSetLineWidth(context, self.lineWidth);
CGPoint gradientCenter = center;
gradientCenter.x += self.offset.x;
gradientCenter.y += self.offset.y;
CGContextReplacePathWithStrokedPath(context);
CGContextClip(context);
CGContextDrawRadialGradient(context,
gradient,
gradientCenter,
radius - self.lineWidth / 2.0,
gradientCenter,
radius + self.lineWidth / 2.0,
kCGGradientDrawsAfterEndLocation | kCGGradientDrawsBeforeStartLocation);
CGContextRestoreGState(context);
}
- (void)drawRect:(CGRect)rect
{
// Create a gradient from black to blue to black
CGFloat colors [] = {
0.0, 0.0, 2.0, 1.0,
0.7, 0.7, 1.0, 1.0,
0.0, 0.0, 2.0, 1.0,
};
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, colors, NULL, 3);
CGColorSpaceRelease(colorSpace);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetAllowsAntialiasing(context, YES);
// top
[self drawLineInContext:context
from:CGPointMake(self.radius + self.lineWidth / 2.0,
self.lineWidth / 2.0)
to:CGPointMake(rect.size.width - self.radius - self.lineWidth / 2.0,
self.lineWidth / 2.0)
usingGradient:gradient];
// top right corner
[self drawArcInContext:context
center:CGPointMake(rect.size.width - self.radius - self.lineWidth / 2.0,
self.radius + self.lineWidth / 2.0)
radius:self.radius
startAngle:M_PI_2 * 3.0
endAngle:M_PI * 2.0
clockwise:NO
usingGradient:gradient];
// right
[self drawLineInContext:context
from:CGPointMake(rect.size.width - self.lineWidth / 2.0,
self.radius + self.lineWidth / 2.0)
to:CGPointMake(rect.size.width - self.lineWidth / 2.0,
rect.size.height - self.radius - self.lineWidth / 2.0)
usingGradient:gradient];
// lower right corner
[self drawArcInContext:context
center:CGPointMake(rect.size.width - self.radius - self.lineWidth / 2.0,
rect.size.height - self.radius - self.lineWidth / 2.0)
radius:self.radius
startAngle:0.0
endAngle:M_PI_2
clockwise:NO
usingGradient:gradient];
// bottom
[self drawLineInContext:context
from:CGPointMake(self.radius + self.lineWidth / 2.0,
rect.size.height - self.lineWidth / 2.0)
to:CGPointMake(rect.size.width - self.radius - self.lineWidth / 2.0,
rect.size.height - self.lineWidth / 2.0)
usingGradient:gradient];
// bottom left corner
[self drawArcInContext:context
center:CGPointMake(self.radius + self.lineWidth / 2.0,
rect.size.height - self.radius - self.lineWidth / 2.0)
radius:self.radius
startAngle:M_PI_2
endAngle:M_PI
clockwise:NO
usingGradient:gradient];
// left
[self drawLineInContext:context
from:CGPointMake(self.lineWidth / 2.0,
self.radius + self.lineWidth / 2.0)
to:CGPointMake(self.lineWidth / 2.0,
rect.size.height - self.radius - self.lineWidth / 2.0)
usingGradient:gradient];
// top left corner
[self drawArcInContext:context
center:CGPointMake(self.radius + self.lineWidth / 2.0,
self.radius + self.lineWidth / 2.0)
radius:self.radius
startAngle:M_PI
endAngle:M_PI_2 * 3.0
clockwise:NO
usingGradient:gradient];
}
#pragma mark - setters will redraw
- (void)setRadius:(CGFloat)radius
{
_radius = radius;
[self setNeedsDisplay];
}
- (void)setLineWidth:(CGFloat)lineWidth
{
_lineWidth = lineWidth;
[self setNeedsDisplay];
}
- (void)setOffset:(CGPoint)offset
{
_offset = offset;
[self setNeedsDisplay];
}
@end
然后,您可以在视图控制器中使用它,如:
- (void)viewDidAppear:(BOOL)animated
{
CGFloat margin = 3.0;
CGRect frame = CGRectMake(margin,
margin,
self.view.frame.size.width - margin * 2,
self.view.frame.size.height - margin * 2);
BoxWithGradientView *boxWithGradientView = [[BoxWithGradientView alloc] initWithFrame:frame];
boxWithGradientView.backgroundColor = [UIColor clearColor];
[self.view addSubview:boxWithGradientView];
}
显然,您可以使用渐变(尽管保持对称,否则您将不得不调整代码),但它是一种可能的CoreGraphics实现。我怀疑有更好的方法来实现更复杂的效果,但它会让你非常接近。