写了一个自定义的弹出框,其中用到了根据 UILabel 文字的多少自动计算 label 的高度,编写的过程中还是会遇到一些坑的,记下来免得忘记了。
功能:支持 Titile,Message,1个或2个按钮。如下:
代码:
// // TTSMessage.h // TTSMessage // // Created by aaron.zheng on 2/12/14. // Copyright (c) 2014 aaron.zheng. All rights reserved. // #import <Foundation/Foundation.h> typedef void (^CancelBtnTouchBlock)(); typedef void (^OtherBtnTouchBlock)(); @interface TTSMessage : NSObject +(void)showMessageViewWithTitle:(NSString*)title message:(NSString*)message cancelButtonTitle:(NSString*)cancelButtonTitle otherButtonTitle:(NSString*)otherButtonTitle onCancel:(CancelBtnTouchBlock)canceled onOther:(OtherBtnTouchBlock)other; @end
// // TTSMessage.m // TTSMessage // // Created by aaron.zheng on 2/12/14. // Copyright (c) 2014 aaron.zheng. All rights reserved. // #import "TTSMessage.h" #import <QuartzCore/QuartzCore.h> #define MARGIN 10 #define MARGIN_L 10 #define MARGIN_R 10 #define BUTTON_HEIGHT 36 static CancelBtnTouchBlock _cancelBtnTouchBlock; static OtherBtnTouchBlock _otherBtnTouchBlock; static TTSMessage *_ttsMessage; @implementation TTSMessage{ UIView *_view; UIView *_contentView; } -(id)init{ if ([super init]) { _view = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds]; } return self; } +(void)showMessageViewWithTitle:(NSString*)title message:(NSString*)message cancelButtonTitle:(NSString*)cancelButtonTitle otherButtonTitle:(NSString*)otherButtonTitle onCancel:(CancelBtnTouchBlock)canceled onOther:(OtherBtnTouchBlock)other{ _cancelBtnTouchBlock = [canceled copy]; _otherBtnTouchBlock = [other copy]; _ttsMessage = [[TTSMessage alloc] init]; UIImage *blueImage = [UIImage imageNamed:@"image-button_blue.png"]; blueImage = [blueImage resizableImageWithCapInsets:UIEdgeInsetsMake(2,2, 2, 2) resizingMode:UIImageResizingModeStretch]; UIImage *pressBlueImage = [UIImage imageNamed:@"image-button_blue_highlighted.png"]; pressBlueImage = [pressBlueImage resizableImageWithCapInsets:UIEdgeInsetsMake(2,2, 2, 2) resizingMode:UIImageResizingModeStretch]; UIWindow *window = [UIApplication sharedApplication].keyWindow; _ttsMessage->_view.frame = [UIScreen mainScreen].bounds; _ttsMessage->_view.backgroundColor = [UIColor clearColor]; UIImageView *imageView = [[UIImageView alloc] initWithFrame:_ttsMessage->_view.frame]; imageView.backgroundColor = [UIColor blackColor]; imageView.alpha = 0.5; [_ttsMessage->_view addSubview:imageView]; [window addSubview:_ttsMessage->_view]; CGRect newRect; CGRect mainRect = [UIScreen mainScreen].bounds; _ttsMessage->_contentView = [[UIView alloc] initWithFrame:CGRectMake(MARGIN, 0, _ttsMessage->_view.frame.size.width - 2*MARGIN, 100)]; _ttsMessage->_contentView.backgroundColor = [UIColor whiteColor]; _ttsMessage->_contentView.layer.cornerRadius = 5.0f; UILabel *titleLabel; if (title != nil && ![title isEqualToString:@""]) { newRect = CGRectMake(MARGIN_L, MARGIN, _ttsMessage->_contentView.frame.size.width - 2*MARGIN_L,23); titleLabel = [[UILabel alloc] initWithFrame:newRect]; //同下描述。 titleLabel.textAlignment = UITextAlignmentCenter; titleLabel.font = [UIFont fontWithName:@"Helvetica-Bold" size:FONT_SIZE_DIALOG_TITLE_TEXT]; titleLabel.layer.masksToBounds = YES; titleLabel.layer.cornerRadius = 3.0f; titleLabel.backgroundColor = [UIColor grayColor]; titleLabel.text = title; newRect.size.height = [_ttsMessage expectedHeight:titleLabel andFontSize:17]; titleLabel.frame = newRect; [_ttsMessage->_contentView addSubview:titleLabel]; } UILabel *messageLabel; if (message != nil && ![message isEqualToString:@""]) { newRect = CGRectMake(MARGIN_L, MARGIN + titleLabel.frame.size.height + MARGIN, _ttsMessage->_contentView.frame.size.width - 2*MARGIN_L, 21); messageLabel = [[UILabel alloc] initWithFrame:newRect]; //如果 alloc 的时候不初始化 label 的高度的话,在接下来调用[self expectedHeight: andFontSize:]的时候会出现计算高度偏小,导致文字显示不完全。 messageLabel.layer.masksToBounds = YES; messageLabel.layer.cornerRadius = 3.0f; messageLabel.textAlignment = UITextAlignmentCenter; // messageLabel.backgroundColor = [UIColor grayColor]; messageLabel.text = message; newRect.size.height = [_ttsMessage expectedHeight:messageLabel andFontSize:FONT_SIZE_DIALOG_CONTENT_LABEL_TEXT]; messageLabel.frame = newRect; [_ttsMessage->_contentView addSubview:messageLabel]; } UIButton *cancelBtn,*otherBtn; if ((cancelButtonTitle != nil && ![cancelButtonTitle isEqualToString:@""]) && (otherButtonTitle == nil || [otherButtonTitle isEqualToString:@""])) { cancelBtn = [[UIButton alloc] initWithFrame:CGRectMake(MARGIN_L, 3*MARGIN + titleLabel.frame.size.height + messageLabel.frame.size.height, _ttsMessage->_contentView.frame.size.width - 2*MARGIN_L, BUTTON_HEIGHT)]; cancelBtn.layer.masksToBounds = YES; cancelBtn.layer.cornerRadius = 3.0f; [cancelBtn setBackgroundImage:blueImage forState:UIControlStateNormal]; [cancelBtn setBackgroundImage:pressBlueImage forState:UIControlStateHighlighted]; cancelBtn.titleLabel.font = [UIFont systemFontOfSize:FONT_SIZE_GREY_BUTTON_TEXT]; [cancelBtn addTarget:self action:@selector(cancelBtnTouch) forControlEvents:UIControlEventTouchUpInside]; cancelBtn.backgroundColor = [UIColor grayColor]; [cancelBtn setTitle:cancelButtonTitle forState:UIControlStateNormal]; [_ttsMessage->_contentView addSubview:cancelBtn]; }else if(cancelButtonTitle != nil && ![cancelButtonTitle isEqualToString:@""] && otherButtonTitle != nil && ![otherButtonTitle isEqualToString:@""]){ cancelBtn = [[UIButton alloc] initWithFrame:CGRectMake(MARGIN_L,3*MARGIN + titleLabel.frame.size.height + messageLabel.frame.size.height , (_ttsMessage->_contentView.frame.size.width -3*MARGIN_L)/2.0, BUTTON_HEIGHT)]; cancelBtn.layer.masksToBounds = YES; cancelBtn.layer.cornerRadius = 3.0f; [cancelBtn setBackgroundImage:blueImage forState:UIControlStateNormal]; [cancelBtn setBackgroundImage:pressBlueImage forState:UIControlStateHighlighted]; [cancelBtn addTarget:self action:@selector(cancelBtnTouch) forControlEvents:UIControlEventTouchUpInside]; cancelBtn.backgroundColor = [UIColor grayColor]; [cancelBtn setTitle:cancelButtonTitle forState:UIControlStateNormal]; [_ttsMessage->_contentView addSubview:cancelBtn]; otherBtn = [[UIButton alloc] initWithFrame:CGRectMake(2*MARGIN_L + cancelBtn.frame.size.width,3*MARGIN + titleLabel.frame.size.height + messageLabel.frame.size.height , (_ttsMessage->_contentView.frame.size.width -3*MARGIN_L)/2.0, BUTTON_HEIGHT)]; otherBtn.layer.masksToBounds = YES; otherBtn.layer.cornerRadius = 3.0f; [otherBtn setBackgroundImage:blueImage forState:UIControlStateNormal]; [otherBtn setBackgroundImage:pressBlueImage forState:UIControlStateHighlighted]; [otherBtn addTarget:self action:@selector(otherBtnTouch) forControlEvents:UIControlEventTouchUpInside]; otherBtn.backgroundColor = [UIColor grayColor]; [otherBtn setTitle:otherButtonTitle forState:UIControlStateNormal]; [_ttsMessage->_contentView addSubview:otherBtn]; } newRect = _ttsMessage->_contentView.bounds; newRect.size.height = 4*MARGIN + titleLabel.frame.size.height + messageLabel.frame.size.height + cancelBtn.frame.size.height; newRect.origin.x = MARGIN_L; newRect.origin.y = (mainRect.size.height - _ttsMessage->_contentView.frame.size.height)/2.0 - _ttsMessage->_contentView.frame.size.height/2.0; _ttsMessage->_contentView.frame = newRect; [_ttsMessage->_view addSubview:_ttsMessage->_contentView]; } +(void)cancelBtnTouch{ _cancelBtnTouchBlock(); [_ttsMessage->_view removeFromSuperview]; } +(void)otherBtnTouch{ _otherBtnTouchBlock(); [_ttsMessage->_view removeFromSuperview]; } -(float)expectedHeight:(UILabel*)label andFontSize:(int)fontSize{ [label setNumberOfLines:0]; [label setLineBreakMode:NSLineBreakByCharWrapping]; UIFont *font = [UIFont systemFontOfSize:fontSize]; NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys: font, NSFontAttributeName, nil]; CGSize maximumLabelSize = CGSizeMake(_contentView.frame.size.width - 2*MARGIN,9999); CGRect expectedLabelRect = [label.text boundingRectWithSize:maximumLabelSize options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading) attributes:attributesDictionary context:nil]; CGSize *expectedLabelSize = &expectedLabelRect.size; return expectedLabelSize->height + label.frame.size.height; } @end
[TTSMessage showMessageViewWithTitle:@"" message:@"渔家傲(辛弃疾):风月小斋模画舫。绿窗朱户江湖样。酒是短桡歌是桨。和情放。醉乡稳到无风浪。自有拍浮千斛酿。从教日日蒲桃涨。门外独醒人也访。同俯仰。赏心却在鸱夷上。" cancelButtonTitle:@"OK" otherButtonTitle:@"cancel" onCancel:^{ NSLog(@"onCancel called.."); } onOther:^{ NSLog(@"onOther called.."); }];
之前是需要 alloc 一个TTSMessage 之后再调用接口的,感觉接口的调用不是很方便,现在把它接口改为静态方法,调用起来就方便多了,当然,你也可以考虑把它写成UIViewController分类或者是UIView的分类,这样就可以直接用self 或者self.view 来调用了,反正看使用方便吧。
参考:UILabel - auto-size label to fit text?
//-----------------------------------------------------------------分割线--2014-04-15 再次编辑--------------------------------------------------------------
在看 AFNetworking 源码的时候有一段代码是计算 cell 高度的,也许以后会用到,mark 下来先。
- (CGFloat)tableView:(__unused UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return [PostTableViewCell heightForCellWithPost:[self.posts objectAtIndex:(NSUInteger)indexPath.row]]; }
+ (CGFloat)heightForCellWithPost:(Post *)post { return (CGFloat)fmaxf(70.0f, (float)[self detailTextHeight:post.text] + 45.0f); } + (CGFloat)detailTextHeight:(NSString *)text { CGRect rectToFit = [text boundingRectWithSize:CGSizeMake(240.0f, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: [UIFont systemFontOfSize:12.0f]} context:nil]; return rectToFit.size.height; }