写了一个自定义的弹出框,其中用到了根据 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
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
#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;
}