iPhone:如何以编程方式制作提示气球?

发布于 2024-11-07 18:24:38 字数 187 浏览 0 评论 0原文

请提供代码以编程方式制作提示气球,就像 Grindr 那样。

我希望它能够根据文本和内容自动调整大小。字体大小。 而且,我希望能够更改箭头的位置。 如果它在一端,它应该是一个直角三角形。否则,它应该是一个等边三角形。

提示气球

Please provide the code to make a tip balloon programmatically, like Grindr has.

I want it to be sized automatically, based on the text & font-size.
And, I want to be able to change the location of the arrow.
If it's on an end, it should be a right triangle. Otherwise, it should be an eqilateral triangle.

tip balloon

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

夏末 2024-11-14 18:24:38
// AppDelegate.h

@interface AppDelegate : NSObject <UIApplicationDelegate> {

}

@property (nonatomic, retain) UIWindow *window;

@end

// AppDelegate.m

#import "AppDelegate.h"
#import "TipBalloon.h"

@implementation AppDelegate

@synthesize window;

#pragma mark NSObject

- (void)dealloc {
    [window release];
    [super dealloc];
}

#pragma mark UIApplicationDelegate

- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    // Add the tip balloon.
    TipBalloon *textExample =
    [[TipBalloon alloc] initAtPoint:CGPointMake(6.0f, 30.0f) withText:
     @"Hello world! I like to make things. Yay! They are really cool things!"];
    [window addSubview:textExample];
    [textExample release];

    window.backgroundColor = [UIColor brownColor];
    [window makeKeyAndVisible];
    return YES;
}

@end

// TipBalloon.h

@interface TipBalloon : UIView {

}

@property (nonatomic, copy) NSString *text;

- (id)initAtPoint:(CGPoint)point withText:(NSString *)string;
- (void)drawOutlineInContext:(CGContextRef)context;
- (void)drawTextInContext:(CGContextRef)context;

@end

// TipBallon.m

#import "TipBalloon.h"

// TODO make some of these instance variables to add more customization.
static const CGFloat kArrowOffset = 0.0f;
static const CGFloat kStrokeWidth = 2.0f;
static const CGFloat kArrowSize = 14.0f;
static const CGFloat kFontSize = 12.0f;
static const CGFloat kMaxWidth = 196.0f;
static const CGFloat kMaxHeight = CGFLOAT_MAX;
static const CGFloat kPaddingWidth = 12.0f;
static const CGFloat kPaddingHeight = 10.0f;

@implementation TipBalloon

@synthesize text;

#pragma mark NSObject

- (void)dealloc {
    [text release];
    [super dealloc];
}

#pragma mark UIView

- (void)drawRect:(CGRect)rect {
    [super drawRect:rect];
    CGContextRef contextRef = UIGraphicsGetCurrentContext();
    [self drawOutlineInContext:contextRef];
    [self drawTextInContext:contextRef];
}

#pragma mark TipBalloon

- (id)initAtPoint:(CGPoint)point withText:(NSString *)string {
    CGSize size = [string sizeWithFont:[UIFont systemFontOfSize:kFontSize]
                     constrainedToSize:CGSizeMake(kMaxWidth, kMaxHeight)
                         lineBreakMode:UILineBreakModeWordWrap];
    CGRect rect = CGRectMake(point.x, point.y, size.width+kPaddingWidth*2.0f,
                             size.height+kPaddingHeight*2.0f+kArrowSize);
    if ((self = [super initWithFrame:rect])) {
        self.text = string;
        UIColor *clearColor = [[UIColor alloc] initWithWhite:0.0f alpha:0.0f];
        self.backgroundColor = clearColor;
        [clearColor release];
    }
    return self;
}

- (void)drawOutlineInContext:(CGContextRef)context {
    CGRect rect = self.bounds;
    rect.origin.x += (kStrokeWidth/2.0f);
    rect.origin.y += kStrokeWidth + kArrowSize;
    rect.size.width -= kStrokeWidth;
    rect.size.height -= kStrokeWidth*1.5f + kArrowSize;

    CGFloat radius = 11.0f;
    CGFloat x_left = rect.origin.x;
    CGFloat x_right = x_left + rect.size.width;
    CGFloat y_top = rect.origin.y;
    CGFloat y_bottom = y_top + rect.size.height;

    CGContextBeginPath(context);
    CGContextSetLineWidth(context, kStrokeWidth);
    CGContextSetRGBStrokeColor(context, 0.0f/255.0f, 255.0f/255.0f, 0.0f/255.0f, 1.0f); // green
    CGContextSetGrayFillColor(context, 1.0f, 1.0f); // white background
    CGContextMoveToPoint(context, x_left+radius, y_top);
    CGContextAddLineToPoint(context, x_left+radius+kArrowOffset, y_top);

    // Draw triangle.
//    CGContextAddLineToPoint(context, x_left+radius+kArrowOffset+kArrowSize/2.0f, y_top-kArrowSize);
    CGContextAddLineToPoint(context, x_left+radius+kArrowOffset, y_top-kArrowSize);
    CGContextAddLineToPoint(context, x_left+radius+kArrowOffset+kArrowSize, y_top);

    static const CGFloat F_PI = (CGFloat)M_PI;
    CGContextAddArc(context, x_right-radius, y_top+radius, radius, 3.0f*F_PI/2.0f, 0.0f, 0);
    CGContextAddArc(context, x_right-radius, y_bottom-radius, radius, 0.0f, F_PI/2.0f, 0);
    CGContextAddArc(context, x_left+radius, y_bottom-radius, radius, F_PI/2.0f, F_PI, 0);
    CGContextAddArc(context, x_left+radius, y_top+radius, radius, F_PI, 3.0f*F_PI/2.0f, 0);
    CGContextClosePath(context);
    CGContextDrawPath(context, kCGPathFillStroke);
}

- (void)drawTextInContext:(CGContextRef)context {
    CGRect rect = self.bounds;
    rect.origin.x += kPaddingWidth;
    rect.origin.y += kPaddingHeight + kArrowSize;
    rect.size.width -= kPaddingWidth*2.0f;
    rect.size.height -= kPaddingHeight*2.0f;

    CGContextSetGrayFillColor(context, 0.0f, 1.0f); // black text
    [text drawInRect:rect withFont:[UIFont systemFontOfSize:kFontSize]
       lineBreakMode:UILineBreakModeWordWrap];
}

@end
// AppDelegate.h

@interface AppDelegate : NSObject <UIApplicationDelegate> {

}

@property (nonatomic, retain) UIWindow *window;

@end

// AppDelegate.m

#import "AppDelegate.h"
#import "TipBalloon.h"

@implementation AppDelegate

@synthesize window;

#pragma mark NSObject

- (void)dealloc {
    [window release];
    [super dealloc];
}

#pragma mark UIApplicationDelegate

- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    // Add the tip balloon.
    TipBalloon *textExample =
    [[TipBalloon alloc] initAtPoint:CGPointMake(6.0f, 30.0f) withText:
     @"Hello world! I like to make things. Yay! They are really cool things!"];
    [window addSubview:textExample];
    [textExample release];

    window.backgroundColor = [UIColor brownColor];
    [window makeKeyAndVisible];
    return YES;
}

@end

// TipBalloon.h

@interface TipBalloon : UIView {

}

@property (nonatomic, copy) NSString *text;

- (id)initAtPoint:(CGPoint)point withText:(NSString *)string;
- (void)drawOutlineInContext:(CGContextRef)context;
- (void)drawTextInContext:(CGContextRef)context;

@end

// TipBallon.m

#import "TipBalloon.h"

// TODO make some of these instance variables to add more customization.
static const CGFloat kArrowOffset = 0.0f;
static const CGFloat kStrokeWidth = 2.0f;
static const CGFloat kArrowSize = 14.0f;
static const CGFloat kFontSize = 12.0f;
static const CGFloat kMaxWidth = 196.0f;
static const CGFloat kMaxHeight = CGFLOAT_MAX;
static const CGFloat kPaddingWidth = 12.0f;
static const CGFloat kPaddingHeight = 10.0f;

@implementation TipBalloon

@synthesize text;

#pragma mark NSObject

- (void)dealloc {
    [text release];
    [super dealloc];
}

#pragma mark UIView

- (void)drawRect:(CGRect)rect {
    [super drawRect:rect];
    CGContextRef contextRef = UIGraphicsGetCurrentContext();
    [self drawOutlineInContext:contextRef];
    [self drawTextInContext:contextRef];
}

#pragma mark TipBalloon

- (id)initAtPoint:(CGPoint)point withText:(NSString *)string {
    CGSize size = [string sizeWithFont:[UIFont systemFontOfSize:kFontSize]
                     constrainedToSize:CGSizeMake(kMaxWidth, kMaxHeight)
                         lineBreakMode:UILineBreakModeWordWrap];
    CGRect rect = CGRectMake(point.x, point.y, size.width+kPaddingWidth*2.0f,
                             size.height+kPaddingHeight*2.0f+kArrowSize);
    if ((self = [super initWithFrame:rect])) {
        self.text = string;
        UIColor *clearColor = [[UIColor alloc] initWithWhite:0.0f alpha:0.0f];
        self.backgroundColor = clearColor;
        [clearColor release];
    }
    return self;
}

- (void)drawOutlineInContext:(CGContextRef)context {
    CGRect rect = self.bounds;
    rect.origin.x += (kStrokeWidth/2.0f);
    rect.origin.y += kStrokeWidth + kArrowSize;
    rect.size.width -= kStrokeWidth;
    rect.size.height -= kStrokeWidth*1.5f + kArrowSize;

    CGFloat radius = 11.0f;
    CGFloat x_left = rect.origin.x;
    CGFloat x_right = x_left + rect.size.width;
    CGFloat y_top = rect.origin.y;
    CGFloat y_bottom = y_top + rect.size.height;

    CGContextBeginPath(context);
    CGContextSetLineWidth(context, kStrokeWidth);
    CGContextSetRGBStrokeColor(context, 0.0f/255.0f, 255.0f/255.0f, 0.0f/255.0f, 1.0f); // green
    CGContextSetGrayFillColor(context, 1.0f, 1.0f); // white background
    CGContextMoveToPoint(context, x_left+radius, y_top);
    CGContextAddLineToPoint(context, x_left+radius+kArrowOffset, y_top);

    // Draw triangle.
//    CGContextAddLineToPoint(context, x_left+radius+kArrowOffset+kArrowSize/2.0f, y_top-kArrowSize);
    CGContextAddLineToPoint(context, x_left+radius+kArrowOffset, y_top-kArrowSize);
    CGContextAddLineToPoint(context, x_left+radius+kArrowOffset+kArrowSize, y_top);

    static const CGFloat F_PI = (CGFloat)M_PI;
    CGContextAddArc(context, x_right-radius, y_top+radius, radius, 3.0f*F_PI/2.0f, 0.0f, 0);
    CGContextAddArc(context, x_right-radius, y_bottom-radius, radius, 0.0f, F_PI/2.0f, 0);
    CGContextAddArc(context, x_left+radius, y_bottom-radius, radius, F_PI/2.0f, F_PI, 0);
    CGContextAddArc(context, x_left+radius, y_top+radius, radius, F_PI, 3.0f*F_PI/2.0f, 0);
    CGContextClosePath(context);
    CGContextDrawPath(context, kCGPathFillStroke);
}

- (void)drawTextInContext:(CGContextRef)context {
    CGRect rect = self.bounds;
    rect.origin.x += kPaddingWidth;
    rect.origin.y += kPaddingHeight + kArrowSize;
    rect.size.width -= kPaddingWidth*2.0f;
    rect.size.height -= kPaddingHeight*2.0f;

    CGContextSetGrayFillColor(context, 0.0f, 1.0f); // black text
    [text drawInRect:rect withFont:[UIFont systemFontOfSize:kFontSize]
       lineBreakMode:UILineBreakModeWordWrap];
}

@end
最后的乘客 2024-11-14 18:24:38

我不会添加另一个视图只是为了将三角形放在上面,您是否考虑过使用 UIBezierPath 绘制圆角边框和三角形?这将为您的绘图提供更大的灵活性,并且您可以将所有内容保留在一个视图中。

I wouldn't add another view just to put the triangle on it, have you considered drawing the rounded border and triangle with an UIBezierPath? That will give you more flexibility in your drawing and you can keep everything in just one view.

孤君无依 2024-11-14 18:24:38

您可以在主视图上使用 UIView 并在需要时调用它。但是,您必须使 UIView 透明,并且可能需要使用图像作为气球的主要部分。在这种情况下,您只需使用 UILabel 来设置所需的消息。

You can use a UIView on your main view and call it when you need it. You will however have to make the UIView transparent and probably will need to use an image as the main part of the balloon. In that scenario, you can just use UILabel's to set the desired message.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文