如何向 UILabel 添加三角形以使其看起来像工具提示?
how to add a triangle to UILabel to make it look like a tooltip?
我想用一些自定义代码制作一个像 UILabel 这样的工具提示。我设法向 UILabel 添加了一个三角形,但是因为它超出了 UILabel 本身的边界(或框架)。它不是在屏幕上绘图。
这是我的方法:
- (void) addTriangleTipToLayer: (CALayer *) targetLayer{
[targetLayer setBackgroundColor: [UIColor whiteColor].CGColor];
CGPoint startPoint = CGPointMake(0, targetLayer.frame.size.height);
CGPoint endPoint = CGPointMake(15, targetLayer.frame.size.height);
UIBezierPath *trianglePath = [UIBezierPath bezierPath];
CGFloat middleX = (startPoint.x + endPoint.x) / 2;
CGFloat middleY = 7.5 * tan(M_PI / 3);
CGPoint middlePoint = CGPointMake(middleX, -middleY);
[trianglePath moveToPoint:startPoint];
[trianglePath addLineToPoint:middlePoint];
[trianglePath addLineToPoint:endPoint];
[trianglePath closePath];
CGAffineTransform rotate = CGAffineTransformMakeRotation(180);
[trianglePath applyTransform:rotate];
CAShapeLayer *triangleLayer = [CAShapeLayer layer];
[triangleLayer setFillColor: [UIColor whiteColor].CGColor];
[triangleLayer setPath:trianglePath.CGPath];
[targetLayer addSublayer:triangleLayer];
}
我还将标签转换为图像内容,用作 Google 地图标记图标。这是我对这个 UILabel 做的其他事情。
UILabel *klabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 50, 20)];
[klabel setFont: [UIFont fontWithName:@"Roboto-Light" size:9]];
[klabel setText: @"Tower"];
// here I apply the add triangle function to the uilabel.layer
[self addTriangleTipToLayer:klabel.layer];
//set the label to fit text content before rendered as a image
[klabel sizeToFit];
//convert the uilabel to image content
UIGraphicsBeginImageContextWithOptions(klabel.bounds.size, NO, [[UIScreen mainScreen] scale]);
[klabel.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * kicon = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// the rest of code is just use the image content as marker icon on google map.
kaliaMarker = [[GMSMarker alloc] init];
kaliaMarker.tappable = NO;
kaliaMarker.position = CLLocationCoordinate2DMake(21.283652, -157.836971);
kaliaMarker.infoWindowAnchor = CGPointMake(0.5, 0.5);
kaliaMarker.icon = kicon;
kaliaMarker.map = self.mapView;
targetLayer
是 myLabel.layer
,这是我添加三角形的地方。问题是 middleY
是计算得出的 -12.4
,我猜它从我的 UILabel 的可见 bound/frame 中掉了出来,你就是看不到它。
我想知道我应该做什么或者增加 UILabel 的可见部分以显示这个小三角形的正确方法是什么。
感谢大家的帮助!
P.S。它应该是这样的。
但它看起来像这样。如果我将路径旋转 90 度,我可以看到半个三角形,它当然就在那里。所以对于 180 度,整个三角形都超出范围,无法看到。
实际上你的箭头就在那里,你的背景是白色的,所以你看不到。为图层设置填充颜色。
[triangleLayer setFillColor:[[UIColor redColor] CGColor]];
这个稍微修改过的代码工作正常。我将方法的参数更改为 UIView 以便我可以访问其背景颜色以使三角形具有相同的颜色,并使三角形点的 y 值与视图的高度成比例。
- (void) addTriangleTipToLayer: (UIView *) view{
CALayer *targetLayer = view.layer;
[targetLayer setBackgroundColor: [UIColor whiteColor].CGColor];
CGPoint startPoint = CGPointMake(0, targetLayer.frame.size.height);
CGPoint endPoint = CGPointMake(15, targetLayer.frame.size.height);
UIBezierPath *trianglePath = [UIBezierPath bezierPath];
CGFloat middleX = (startPoint.x + endPoint.x) / 2;
CGFloat middleY = targetLayer.frame.size.height * 1.8;
CGPoint middlePoint = CGPointMake(middleX, middleY);
[trianglePath moveToPoint:startPoint];
[trianglePath addLineToPoint:middlePoint];
[trianglePath addLineToPoint:endPoint];
[trianglePath closePath];
CAShapeLayer *triangleLayer = [CAShapeLayer layer];
[triangleLayer setFillColor: view.backgroundColor.CGColor];
[triangleLayer setPath:trianglePath.CGPath];
[targetLayer addSublayer:triangleLayer];
}
我发现我的代码有问题。
//convert the uilabel to image content
UIGraphicsBeginImageContextWithOptions(klabel.bounds.size, NO, [[UIScreen mainScreen] scale]);
没有包含足够的 space 用于添加到 uilabel 的箭头层。
我还以错误的方式添加了三角形。正确的代码应该是:
[targetLayer setBackgroundColor: [UIColor whiteColor].CGColor];
CGFloat side = targetLayer.frame.size.height;
CGPoint startPoint = CGPointMake(targetLayer.frame.size.width / 2 - side / 2, side);
CGPoint endPoint = CGPointMake(targetLayer.frame.size.width / 2 + side / 2, side);
UIBezierPath *trianglePath = [UIBezierPath bezierPath];
CGFloat middleX = targetLayer.frame.size.width / 2;
CGFloat middleY = (side / 2) * tan(M_PI / 3) + side;
CGPoint middlePoint = CGPointMake(middleX, middleY);
[trianglePath moveToPoint:startPoint];
[trianglePath addLineToPoint:middlePoint];
[trianglePath addLineToPoint:endPoint];
[trianglePath closePath];
CAShapeLayer *triangleLayer = [CAShapeLayer layer];
[triangleLayer setFillColor: [UIColor whiteColor].CGColor];
[triangleLayer setPath:trianglePath.CGPath];
[targetLayer addSublayer:triangleLayer];
这会将等边三角形中心添加到标签本身。那么绘制转换为图像的代码应该是:
//convert the uilabel to image content
UIGraphicsBeginImageContextWithOptions(CGRectMake(self.klabel.bounds.size.width, 2 * self.klabel.bounds.size.height), NO, [[UIScreen mainScreen] scale]);
感谢大家的帮助!
我想用一些自定义代码制作一个像 UILabel 这样的工具提示。我设法向 UILabel 添加了一个三角形,但是因为它超出了 UILabel 本身的边界(或框架)。它不是在屏幕上绘图。
这是我的方法:
- (void) addTriangleTipToLayer: (CALayer *) targetLayer{
[targetLayer setBackgroundColor: [UIColor whiteColor].CGColor];
CGPoint startPoint = CGPointMake(0, targetLayer.frame.size.height);
CGPoint endPoint = CGPointMake(15, targetLayer.frame.size.height);
UIBezierPath *trianglePath = [UIBezierPath bezierPath];
CGFloat middleX = (startPoint.x + endPoint.x) / 2;
CGFloat middleY = 7.5 * tan(M_PI / 3);
CGPoint middlePoint = CGPointMake(middleX, -middleY);
[trianglePath moveToPoint:startPoint];
[trianglePath addLineToPoint:middlePoint];
[trianglePath addLineToPoint:endPoint];
[trianglePath closePath];
CGAffineTransform rotate = CGAffineTransformMakeRotation(180);
[trianglePath applyTransform:rotate];
CAShapeLayer *triangleLayer = [CAShapeLayer layer];
[triangleLayer setFillColor: [UIColor whiteColor].CGColor];
[triangleLayer setPath:trianglePath.CGPath];
[targetLayer addSublayer:triangleLayer];
}
我还将标签转换为图像内容,用作 Google 地图标记图标。这是我对这个 UILabel 做的其他事情。
UILabel *klabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 50, 20)];
[klabel setFont: [UIFont fontWithName:@"Roboto-Light" size:9]];
[klabel setText: @"Tower"];
// here I apply the add triangle function to the uilabel.layer
[self addTriangleTipToLayer:klabel.layer];
//set the label to fit text content before rendered as a image
[klabel sizeToFit];
//convert the uilabel to image content
UIGraphicsBeginImageContextWithOptions(klabel.bounds.size, NO, [[UIScreen mainScreen] scale]);
[klabel.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * kicon = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// the rest of code is just use the image content as marker icon on google map.
kaliaMarker = [[GMSMarker alloc] init];
kaliaMarker.tappable = NO;
kaliaMarker.position = CLLocationCoordinate2DMake(21.283652, -157.836971);
kaliaMarker.infoWindowAnchor = CGPointMake(0.5, 0.5);
kaliaMarker.icon = kicon;
kaliaMarker.map = self.mapView;
targetLayer
是 myLabel.layer
,这是我添加三角形的地方。问题是 middleY
是计算得出的 -12.4
,我猜它从我的 UILabel 的可见 bound/frame 中掉了出来,你就是看不到它。
我想知道我应该做什么或者增加 UILabel 的可见部分以显示这个小三角形的正确方法是什么。
感谢大家的帮助!
P.S。它应该是这样的。
但它看起来像这样。如果我将路径旋转 90 度,我可以看到半个三角形,它当然就在那里。所以对于 180 度,整个三角形都超出范围,无法看到。
实际上你的箭头就在那里,你的背景是白色的,所以你看不到。为图层设置填充颜色。
[triangleLayer setFillColor:[[UIColor redColor] CGColor]];
这个稍微修改过的代码工作正常。我将方法的参数更改为 UIView 以便我可以访问其背景颜色以使三角形具有相同的颜色,并使三角形点的 y 值与视图的高度成比例。
- (void) addTriangleTipToLayer: (UIView *) view{
CALayer *targetLayer = view.layer;
[targetLayer setBackgroundColor: [UIColor whiteColor].CGColor];
CGPoint startPoint = CGPointMake(0, targetLayer.frame.size.height);
CGPoint endPoint = CGPointMake(15, targetLayer.frame.size.height);
UIBezierPath *trianglePath = [UIBezierPath bezierPath];
CGFloat middleX = (startPoint.x + endPoint.x) / 2;
CGFloat middleY = targetLayer.frame.size.height * 1.8;
CGPoint middlePoint = CGPointMake(middleX, middleY);
[trianglePath moveToPoint:startPoint];
[trianglePath addLineToPoint:middlePoint];
[trianglePath addLineToPoint:endPoint];
[trianglePath closePath];
CAShapeLayer *triangleLayer = [CAShapeLayer layer];
[triangleLayer setFillColor: view.backgroundColor.CGColor];
[triangleLayer setPath:trianglePath.CGPath];
[targetLayer addSublayer:triangleLayer];
}
我发现我的代码有问题。
//convert the uilabel to image content
UIGraphicsBeginImageContextWithOptions(klabel.bounds.size, NO, [[UIScreen mainScreen] scale]);
没有包含足够的 space 用于添加到 uilabel 的箭头层。 我还以错误的方式添加了三角形。正确的代码应该是:
[targetLayer setBackgroundColor: [UIColor whiteColor].CGColor];
CGFloat side = targetLayer.frame.size.height;
CGPoint startPoint = CGPointMake(targetLayer.frame.size.width / 2 - side / 2, side);
CGPoint endPoint = CGPointMake(targetLayer.frame.size.width / 2 + side / 2, side);
UIBezierPath *trianglePath = [UIBezierPath bezierPath];
CGFloat middleX = targetLayer.frame.size.width / 2;
CGFloat middleY = (side / 2) * tan(M_PI / 3) + side;
CGPoint middlePoint = CGPointMake(middleX, middleY);
[trianglePath moveToPoint:startPoint];
[trianglePath addLineToPoint:middlePoint];
[trianglePath addLineToPoint:endPoint];
[trianglePath closePath];
CAShapeLayer *triangleLayer = [CAShapeLayer layer];
[triangleLayer setFillColor: [UIColor whiteColor].CGColor];
[triangleLayer setPath:trianglePath.CGPath];
[targetLayer addSublayer:triangleLayer];
这会将等边三角形中心添加到标签本身。那么绘制转换为图像的代码应该是:
//convert the uilabel to image content
UIGraphicsBeginImageContextWithOptions(CGRectMake(self.klabel.bounds.size.width, 2 * self.klabel.bounds.size.height), NO, [[UIScreen mainScreen] scale]);