结束目标
我正在为我的一个观点做一个工具提示功能。工具提示视图将以模式方式呈现在提供提示的视图上。除了一个或两个需要完全半透明的关键点外,大部分视图都是深色半透明背景。这些点本身就是圆形或矩形。
基本上我需要创建一个UIImage,以便它可以很好地进入UIImageView。
到目前为止......
目前我知道如何使用任何尺寸的颜色绘制图像:
- (UIImage *)imageWithColor:(UIColor *)color scaledToSize:(CGSize)size {
UIImage *image;
CGRect rect = CGRectMake(0.0f, 0.0f, size.width, size.height);
UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, color.CGColor);
CGContextFillRect(context, rect);
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
换句话说......
换句话说,我可以使用上面的代码制作一个半透明的矩形。然后,我需要做的就是在某些点找到一种在某些尺寸的矩形中“打孔”的方法。
问题 我怎样才能创建这些“钥匙孔”般的图像?还有另一种方法吗?
答案 0 :(得分:3)
我认为你不需要用图像来做这件事。您可以使用具有与视图大小相同的掩码的CALayer,添加不透明的子层(将用作孔)。下面的代码添加了一个带有正方形和圆形“孔”的黑暗图层。
-(IBAction)addMask:(id)sender {
CALayer *maskLayer = [CALayer layer];
maskLayer.frame = self.view.bounds;
CALayer *square = [CALayer layer];
square.frame = CGRectMake(100, 200, 50, 50);
square.backgroundColor = [UIColor blackColor].CGColor;
CAShapeLayer *circle = [CAShapeLayer layer];
UIBezierPath *circlePath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(150, 280, 50, 50)];
circle.path = circlePath.CGPath;
[maskLayer addSublayer:square];
[maskLayer addSublayer:circle];
maskLayer.backgroundColor = [UIColor colorWithWhite:1 alpha:.4].CGColor;
self.view.layer.mask = maskLayer;
}
答案 1 :(得分:0)
这是我的完整工具提示解决方案。感谢@rdelmar告诉我不需要UIIMage。
在某些地方可能是多余的,框架工作看起来很糟糕,但它完成了工作。我很乐意听到一些改进:
Home.h文件
@property (strong, nonatomic) CALayer *maskLayer;
@property (strong, nonatomic) CATextLayer *profileTitleLayerBack;
@property (strong, nonatomic) CATextLayer *profileDetailLayerBack;
@property (strong, nonatomic) CATextLayer *checkinTitleLayerBack;
@property (strong, nonatomic) CATextLayer *checkinDetailLayerBack;
@property (strong, nonatomic) CATextLayer *dismissLayerBack;
@property (strong, nonatomic) UIButton *tooltipButton;
Home.m文件
- (void)viewDidLoad {
[super viewDidLoad];
if ([self firstTimeViewingHome]) {
[self showTooltipLayers];
}
}
//FYI if you want to allow the user to see the tooltip again - just remove the 'DoesNotNeedHomeTooltip' key
- (BOOL)firstTimeViewingHome {
BOOL firstTime = YES;
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DoesNotNeedHomeTooltip"])
{
firstTime = NO;
}
else {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"DoesNotNeedHomeTooltip"];
[[NSUserDefaults standardUserDefaults] synchronize];
firstTime = YES;
}
return firstTime;
}
- (void)showTooltipLayers {
//I use JASidePanels so if I want to mask the full screen I need to use its view that I store in my session controller
UIView *sidePanelView = self.sessionController.sidePanelController.view;
//A mask is used to cover the view
self.maskLayer = [CALayer layer];
self.maskLayer.frame = sidePanelView.bounds;
self.maskLayer.backgroundColor = [UIColor colorWithWhite:1 alpha:.25].CGColor;
sidePanelView.layer.mask = self.maskLayer;
//Shapes are then used to highlight points in view behind the mask
CAShapeLayer *circle1 = [CAShapeLayer layer];
UIBezierPath *circlePath1 = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(-4, 10, 60, 60)];
circle1.path = circlePath1.CGPath;
[self.maskLayer addSublayer:circle1];
CAShapeLayer *circle2 = [CAShapeLayer layer];
CGRect checkinCircleFrame = CGRectMake(sidePanelView.frame.size.width/2 - 35, sidePanelView.frame.size.height - 65, 70, 70);
UIBezierPath *circlePath2 = [UIBezierPath bezierPathWithOvalInRect:checkinCircleFrame];
circle2.path = circlePath2.CGPath;
[self.maskLayer addSublayer:circle2];
//Text Layers
//
//Each layer is added twice.
//
//The first layer goes in the back (in the main view).
//
//The second layer goes in front (in the mask),
//creating a clear window to the text layer in the back.
//
//This solution was used because the front layer text color
//could not be changed to white (only clear).
//Using only white in the back results being affected by the mask
//Title for Profile tip
self.profileTitleLayerBack = [[CATextLayer alloc] init];
self.profileTitleLayerBack.contentsScale = UIScreen.mainScreen.scale;
self.profileTitleLayerBack.frame = CGRectMake(30, 70, 250, 40);
self.profileTitleLayerBack.font = (__bridge CFTypeRef)(@"Oswald-Light");
self.profileTitleLayerBack.fontSize = 35;
self.profileTitleLayerBack.alignmentMode = kCAAlignmentLeft;
self.profileTitleLayerBack.string = @"OBFUSCATED";
self.profileTitleLayerBack.foregroundColor = UIColor.whiteColor.CGColor;
[sidePanelView.layer addSublayer:self.profileTitleLayerBack];
CATextLayer *profileTitleLayerFront = [[CATextLayer alloc] init];
profileTitleLayerFront.contentsScale = UIScreen.mainScreen.scale;
profileTitleLayerFront.frame = self.profileTitleLayerBack.frame;
profileTitleLayerFront.font = self.profileTitleLayerBack.font;
profileTitleLayerFront.fontSize = self.profileTitleLayerBack.fontSize;
profileTitleLayerFront.alignmentMode = self.profileTitleLayerBack.alignmentMode;
profileTitleLayerFront.string = self.profileTitleLayerBack.string;
[self.maskLayer addSublayer:profileTitleLayerFront];
//Detail for Profile Tip
self.profileDetailLayerBack = [[CATextLayer alloc] init];
self.profileDetailLayerBack.contentsScale = UIScreen.mainScreen.scale;
self.profileDetailLayerBack.frame = CGRectMake(self.profileTitleLayerBack.frame.origin.x + 5,
self.profileTitleLayerBack.frame.origin.y +
self.profileTitleLayerBack.frame.size.height + 8,
300,
150);
self.profileDetailLayerBack.font = (__bridge CFTypeRef)(@"Oswald-Light");
self.profileDetailLayerBack.fontSize = 20;
self.profileDetailLayerBack.alignmentMode = kCAAlignmentLeft;
self.profileDetailLayerBack.string = @"This is your space.\nEverything about your obfuscated,\nobfuscated, and obfuscated.";
self.profileDetailLayerBack.foregroundColor = UIColor.whiteColor.CGColor;
[sidePanelView.layer addSublayer:self.profileDetailLayerBack];
CATextLayer *profileDetailLayerFront = [[CATextLayer alloc] init];
profileDetailLayerFront.contentsScale = UIScreen.mainScreen.scale;
profileDetailLayerFront.frame = self.profileDetailLayerBack.frame;
profileDetailLayerFront.font = self.profileDetailLayerBack.font;
profileDetailLayerFront.fontSize = self.profileDetailLayerBack.fontSize;
profileDetailLayerFront.alignmentMode = self.profileDetailLayerBack.alignmentMode;
profileDetailLayerFront.string = self.profileDetailLayerBack.string;
[self.maskLayer addSublayer:profileDetailLayerFront];
//Title for Checkin tip
self.checkinTitleLayerBack = [[CATextLayer alloc] init];
self.checkinTitleLayerBack.contentsScale = UIScreen.mainScreen.scale;
self.checkinTitleLayerBack.frame = CGRectMake(sidePanelView.frame.size.width/2 - 125,
checkinCircleFrame.origin.y - 40 - 115,
250,
40);
self.checkinTitleLayerBack.font = (__bridge CFTypeRef)(@"Oswald-Light");
self.checkinTitleLayerBack.fontSize = 35;
self.checkinTitleLayerBack.alignmentMode = kCAAlignmentCenter;
self.checkinTitleLayerBack.string = @"OBFUSCATED";
self.checkinTitleLayerBack.foregroundColor = UIColor.whiteColor.CGColor;
[sidePanelView.layer addSublayer:self.checkinTitleLayerBack];
CATextLayer *checkinTitleLayerFront = [[CATextLayer alloc] init];
checkinTitleLayerFront.contentsScale = UIScreen.mainScreen.scale;
checkinTitleLayerFront.frame = self.checkinTitleLayerBack.frame;
checkinTitleLayerFront.font = self.checkinTitleLayerBack.font;
checkinTitleLayerFront.fontSize = self.checkinTitleLayerBack.fontSize;
checkinTitleLayerFront.alignmentMode = self.checkinTitleLayerBack.alignmentMode;
checkinTitleLayerFront.string = self.checkinTitleLayerBack.string;
[self.maskLayer addSublayer:checkinTitleLayerFront];
//Detail for Checkin Tip
self.checkinDetailLayerBack = [[CATextLayer alloc] init];
self.checkinDetailLayerBack.contentsScale = UIScreen.mainScreen.scale;
self.checkinDetailLayerBack.frame = CGRectMake(sidePanelView.frame.size.width/2 - 150,
checkinCircleFrame.origin.y - 115 + 8,
300,
150);
self.checkinDetailLayerBack.font = (__bridge CFTypeRef)(@"Oswald-Light");
self.checkinDetailLayerBack.fontSize = 20;
self.checkinDetailLayerBack.alignmentMode = kCAAlignmentCenter;
self.checkinDetailLayerBack.string = @"Tap to view your obfuscated\nobfuscated and check in to your\nobfuscated and obfuscated.";
self.checkinDetailLayerBack.foregroundColor = UIColor.whiteColor.CGColor;
[sidePanelView.layer addSublayer:self.checkinDetailLayerBack];
CATextLayer *checkinDetailLayerFront = [[CATextLayer alloc] init];
checkinDetailLayerFront.contentsScale = UIScreen.mainScreen.scale;
checkinDetailLayerFront.frame = self.checkinDetailLayerBack.frame;
checkinDetailLayerFront.font = self.checkinDetailLayerBack.font;
checkinDetailLayerFront.fontSize = self.checkinDetailLayerBack.fontSize;
checkinDetailLayerFront.alignmentMode = self.checkinDetailLayerBack.alignmentMode;
checkinDetailLayerFront.string = self.checkinDetailLayerBack.string;
[self.maskLayer addSublayer:checkinDetailLayerFront];
//Add a notice disclosing how to dismiss the tooltip
self.dismissLayerBack = [[CATextLayer alloc] init];
self.dismissLayerBack.contentsScale = UIScreen.mainScreen.scale;
self.dismissLayerBack.frame = CGRectMake(sidePanelView.frame.size.width/2 - 75,
sidePanelView.frame.size.height/2 - 10,
150,
20);
self.dismissLayerBack.font = (__bridge CFTypeRef)(@"Oswald-Light");
self.dismissLayerBack.fontSize = 16;
self.dismissLayerBack.alignmentMode = kCAAlignmentCenter;
self.dismissLayerBack.string = @"(Tap anywhere to dismiss)";
self.dismissLayerBack.foregroundColor = self.view.backgroundColor.CGColor;
[sidePanelView.layer addSublayer:self.dismissLayerBack];
CATextLayer *dismissLayerFront = [[CATextLayer alloc] init];
dismissLayerFront.contentsScale = UIScreen.mainScreen.scale;
dismissLayerFront.frame = self.dismissLayerBack.frame;
dismissLayerFront.font = self.dismissLayerBack.font;
dismissLayerFront.fontSize = self.dismissLayerBack.fontSize;
dismissLayerFront.alignmentMode = self.dismissLayerBack.alignmentMode;
dismissLayerFront.string = self.dismissLayerBack.string;
[self.maskLayer addSublayer:dismissLayerFront];
//Add a clear button over top the view
self.tooltipButton = [[UIButton alloc] initWithFrame:CGRectMake(sidePanelView.frame.origin.x,
sidePanelView.frame.origin.y,
sidePanelView.frame.size.width,
sidePanelView.frame.size.height)];
self.tooltipButton.backgroundColor = UIColor.clearColor;
[self.tooltipButton addTarget:self action:@selector(tooltipButtonPressed) forControlEvents:UIControlEventTouchUpInside];
[sidePanelView addSubview:self.tooltipButton];
[sidePanelView bringSubviewToFront:self.tooltipButton];
}
//dismisses the tooltip view / cleans up
- (void)tooltipButtonPressed {
self.sessionController.sidePanelController.view.layer.mask = nil;
self.maskLayer = nil;
[self.profileTitleLayerBack removeFromSuperlayer];
self.profileTitleLayerBack = nil;
[self.profileDetailLayerBack removeFromSuperlayer];
self.profileDetailLayerBack = nil;
[self.checkinTitleLayerBack removeFromSuperlayer];
self.checkinTitleLayerBack = nil;
[self.checkinDetailLayerBack removeFromSuperlayer];
self.checkinDetailLayerBack = nil;
[self.dismissLayerBack removeFromSuperlayer];
self.dismissLayerBack = nil;
[self.tooltipButton removeFromSuperview];
self.tooltipButton = nil;
}