YBPopupMenu源码地址
https://github.com/lyb5834/YBPopupMenu
基础差没办法,将源码手抄了一遍,才一点点理解的;
1、initWithTitles
设置itemWidth,就是整体显示的宽度;init初始化时设置了箭头宽、高(kArrowWidth、kArrowHeight);计算好箭头三角形左下角位置kArrowPosition;后面会继续调整kArrowPosition等坐标;等等其他初始化;
2、showAtPoint、showRelyOnView
通过getMaskLayerWithPoint方法获取CAShapeLayer,赋值给layer.mask; 之后调用显示方法show;另外showRelyOnView种,会调整y的位置,放到控件上方;
3、getMaskLayerWithPoint中创建CAShapeLayer,
第一步、先调整veiw的x、y;获取箭头位置kArrowPosition,
第二步、调用drawMaskLayer绘制CAShapeLayer,
第三步、修改锚点位置,调用determineAnchorPoint方法;
第四步、判断view底部是否超出屏幕高度,进行相应的翻转操作,根据锚点翻转;
第五步、根据offset,修改偏移;
整体就是getMaskLayerWithPoint的代码逻辑;
建议使用 [[UIBarButtonItem alloc] initWithCustomView:yourCustomButton] 来实例化UIBarButtonItem,因为UIBarButtonItem没有公有方法获取它的view,用私有API虽然可以获取,但是可能会引起APPStoreSafe之类的问题
1、控制table的高度,超过的可以滑动
// 大于5,固定table的高度
self.width = itemWidth;
self.height = (titles.count > 5 ? 5 * kButtonHeight : titles.count * kButtonHeight) + 2 * kArrowHeight;
// 大于5,才可以滑动
_contentView.bounces = titles.count > 5 ? YES : NO;
2、Cell 绘制分割线、
[self setNeedsDisplay]; // setNeedsDisplay会调用自动调用drawRect方法
- (void)drawRect:(CGRect)rect
{
if (!_isShowSeparator) return;
// bezier曲线,绘制分割线
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRect:CGRectMake(0, rect.size.height - 0.5, rect.size.width, 0.5)];
[_separatorColor setFill];
[bezierPath fillWithBlendMode:kCGBlendModeNormal alpha:1];
[bezierPath closePath];
}
3、sortedArrayUsingComparator默认是升序排列;
"<" 降序排列;">"升序排列;
NSArray *sortedArray = [array sortedArrayUsingComparator: ^(id obj1, id obj2) {
if ([obj1 integerValue] > [obj2 integerValue]) {
return (NSComparisonResult)NSOrderedDescending;
}
if ([obj1 integerValue] < [obj2 integerValue]) {
return (NSComparisonResult)NSOrderedAscending;
}
return (NSComparisonResult)NSOrderedSame;
}];
1.sortedArrayUsingComparator这个方法本身就是按递增的方式排序。
2.返回的返回值(NSOrderedAscending 不交换,NSOrderedSame 不交换,NSOrderedDescending 交换)。
例如:object1 < object2 返回:NSOrderedDescending 则交换(变为object2,object1),以保证安方法本身升序。返回NSOrderedAscending,两者不交换。
sortedArrayUsingComparator
http://blog.csdn.net/u010828718/article/details/51202624
//=====TFPopupMenu.h=====
#import <UIKit/UIKit.h>
typedef NS_ENUM(NSInteger, TFPopupMenuType)
{
TFPopupMenuTypeDefault = 0,
TFPopupMenuTypeDark
};
@class TFPopupMenu;
@protocol TFPopupMenuDelegate <NSObject>
@optional
/** 点击事件回调 */
- (void)tfPopupMenuDidSelectedAtIndex:(NSInteger)index tfPopupMenu:(TFPopupMenu *)TFPopupMenu;
- (void)tfPopupMenuBeganDismiss;
- (void)tfPopupMenuDidDismiss;
@end
@interface TFPopupMenu : UIView
/** 圆角半径 Default is 5.0 */
@property (nonatomic, assign) CGFloat cornerRadius;
/** 是否显示阴影 Default is YES*/
@property (nonatomic, assign, getter=isShadowShowing) BOOL isShowShadow;
/** 选择菜单项后消失 Default is YES */
@property (nonatomic, assign) BOOL dismissOnSelected;
/** 点击菜单外消失 Default is YES */
@property (nonatomic, assign) BOOL dismissOnTouchOutside;
/** 设置字体大小 Default is 15 */
@property (nonatomic, assign) CGFloat fontSize;
/** 设置字体颜色 Default is [UIColor blackColor] */
@property (nonatomic, strong) UIColor *textColor;
/** 设置偏移距离,上下位置 (>= 0) Default is 0.0 */
@property (nonatomic, assign) CGFloat offset;
/** 设置显示模式 Default is TFPopupMenuTypeDefault */
@property (nonatomic, assign) TFPopupMenuType type;
/** 代理 */
@property (nonatomic, weak) id <TFPopupMenuDelegate> delegate;
/**
初始化popupMenu
@param titles 标题数组
@param icons 图标数组
@param itemWidth 菜单宽度
@param delegate 代理
*/
- (instancetype)initWithTitles:(NSArray *)titles
icons:(NSArray *)icons
menuWidth:(CGFloat)itemWidth
delegate:(id <TFPopupMenuDelegate>)delegate;
/** 在指定位置弹出 类方法 */
+ (instancetype)showAtPoint:(CGPoint)point
titles:(NSArray *)titles
icons:(NSArray *)icons
menuWidth:(CGFloat)itemWidth
delegate:(id<TFPopupMenuDelegate>)delegate;
/** 依赖指定view弹出 类方法 */
+ (instancetype)showRelyOnView:(UIView *)view
titles:(NSArray *)titles
icons:(NSArray *)icons
menuWidth:(CGFloat)itemWidth
delegate:(id<TFPopupMenuDelegate>)delegate;
/**
在指定位置弹出
@param point 需要弹出的point
*/
- (void)showAtPoint:(CGPoint)point;
/**
依赖指定view弹出
@param view 需要依赖的view
*/
- (void)showRelyOnView:(UIView *)view;
/** 消失 */
- (void)dismiss;
@end
//=====TFPopupMenu.m=====
#import "TFPopupMenu.h"
#define kScreenWidth [UIScreen mainScreen].bounds.size.width
#define kScreenHeight [UIScreen mainScreen].bounds.size.height
#define kMainWindow [UIApplication sharedApplication].keyWindow
#pragma mark - /////////////////
#pragma mark - private categorys
@interface UIView (TFFrame)
@property (nonatomic, assign) CGFloat x;
@property (nonatomic, assign) CGFloat y;
@property (nonatomic, assign) CGPoint origin;
@property (nonatomic, assign) CGFloat centerX;
@property (nonatomic, assign) CGFloat centerY;
@property (nonatomic, assign) CGFloat width;
@property (nonatomic, assign) CGFloat height;
@property (nonatomic, assign) CGSize size;
@end
@implementation UIView (TFFrame)
- (CGFloat)x
{
return self.frame.origin.x;
}
- (void)setX:(CGFloat)value
{
CGRect frame = self.frame;
frame.origin.x = value;
self.frame = frame;
}
- (CGFloat)y
{
return self.frame.origin.y;
}
- (void)setY:(CGFloat)value
{
CGRect frame = self.frame;
frame.origin.y = value;
self.frame = frame;
}
- (CGPoint)origin
{
return self.frame.origin;
}
- (void)setOrigin:(CGPoint)origin
{
CGRect frame = self.frame;
frame.origin = origin;
self.frame = frame;
}
- (CGFloat)centerX
{
return self.center.x;
}
- (void)setCenterX:(CGFloat)centerX
{
CGPoint center = self.center;
center.x = centerX;
self.center = center;
}
- (CGFloat)centerY
{
return self.center.y;
}
- (void)setCenterY:(CGFloat)centerY
{
CGPoint center = self.center;
center.y = centerY;
self.center = center;
}
- (CGFloat)width
{
return self.frame.size.width;
}
- (void)setWidth:(CGFloat)width
{
CGRect frame = self.frame;
frame.size.width = width;
self.frame = frame;
}
- (CGFloat)height
{
return self.frame.size.height;
}
- (void)setHeight:(CGFloat)height
{
CGRect frame = self.frame;
frame.size.height = height;
self.frame = frame;
}
- (CGSize)size
{
return self.frame.size;
}
- (void)setSize:(CGSize)size
{
CGRect frame = self.frame;
frame.size = size;
self.frame = frame;
}
@end
#pragma mark - /////////////////
@interface TFPopupMenuCell : UITableViewCell
/** 是否显示分割线 */
@property (nonatomic, assign) BOOL isShowSeparator;
/** 分割线颜色 */
@property (nonatomic, strong) UIColor *separatorColor;
@end
@implementation TFPopupMenuCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
_isShowSeparator = YES;
_separatorColor = [UIColor lightGrayColor];
[self setNeedsDisplay]; // setNeedsDisplay会调用自动调用drawRect方法
}
return self;
}
- (void)setIsShowSeparator:(BOOL)isShowSeparator
{
_isShowSeparator = isShowSeparator;
[self setNeedsDisplay];
}
- (void)setSeparatorColor:(UIColor *)separatorColor
{
_separatorColor = separatorColor;
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect
{
if (!_isShowSeparator) return;
// bezier曲线,绘制分割线
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRect:CGRectMake(0, rect.size.height - 0.5, rect.size.width, 0.5)];
[_separatorColor setFill];
[bezierPath fillWithBlendMode:kCGBlendModeNormal alpha:1];
[bezierPath closePath];
}
@end
#pragma mark - /////////////////
@interface TFPopupMenu () <UITableViewDelegate, UITableViewDataSource>
{
UIView *_mainView;
UITableView *_contentView;
UIView *_bgView;
CGPoint _anchorPoint; // 箭头锚点
CGFloat kArrowHeight; // 箭头相关
CGFloat kArrowWidth;
CGFloat kArrowPosition;
CGFloat kButtonHeight;
NSArray *_titles;
NSArray *_icons;
UIColor *_contentColor; // _mainView 背景色
UIColor *_seperatorColor; // table cell 分割线颜色
}
@end
@implementation TFPopupMenu
@synthesize cornerRadius = kCornerRadius; // 圆角半径
- (instancetype)initWithTitles:(NSArray *)titles
icons:(NSArray *)icons
menuWidth:(CGFloat)itemWidth
delegate:(id <TFPopupMenuDelegate>)delegate
{
if (self = [super init])
{
kArrowWidth = 15;
kArrowHeight = 10;
kButtonHeight = 44;
kCornerRadius = 5.0f;
_titles = titles;
_icons = icons;
_dismissOnSelected = YES;
_fontSize = 15.0f;
_textColor = [UIColor blackColor];
_offset = 0.0f;
_type = TFPopupMenuTypeDefault;
_contentColor = [UIColor whiteColor];
_seperatorColor = [UIColor lightGrayColor];
if (delegate) {
self.delegate = delegate;
}
// 大于5,固定table的高度
self.width = itemWidth;
self.height = (titles.count > 5 ? 5 * kButtonHeight : titles.count * kButtonHeight) + 2 * kArrowHeight;
kArrowPosition = 0.5 * self.width - 0.5 *kArrowWidth;
// 透明度、阴影
self.alpha = 0;
self.layer.shadowOpacity = 0.5;
self.layer.shadowOffset = CGSizeMake(0, 0);
self.layer.shadowRadius = 2.0f;
_mainView = [[UIView alloc] initWithFrame:self.bounds];
_mainView.backgroundColor = _contentColor;
_mainView.layer.cornerRadius = kCornerRadius;
_mainView.layer.masksToBounds = YES;
_contentView = [[UITableView alloc] initWithFrame:_mainView.bounds style:UITableViewStylePlain];
_contentView.backgroundColor = [UIColor clearColor];
_contentView.delegate = self;
_contentView.dataSource = self;
_contentView.bounces = titles.count > 5 ? YES : NO; // 大于5,才可以滑动
_contentView.tableFooterView = [UIView new];
_contentView.separatorStyle = UITableViewCellSeparatorStyleNone;
_contentView.height -= 2*kArrowHeight;
_contentView.centerY = _mainView.centerY;
[_mainView addSubview:_contentView];
[self addSubview:_mainView];
_bgView = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];
_bgView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.1];
_bgView.alpha = 0;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismiss)];
[_bgView addGestureRecognizer:tap];
}
return self;
}
#pragma mark - 显示、隐藏
/** 消失 */
- (void)dismiss
{
if (self.delegate && [self.delegate respondsToSelector:@selector(tfPopupMenuBeganDismiss)]) {
[self.delegate tfPopupMenuBeganDismiss];
}
[UIView animateWithDuration:0.25 animations:^{
// 缩到最小,透明看不见;完成后移除;
self.layer.affineTransform = CGAffineTransformMakeScale(0.1, 0.1);
self.alpha = 0;
_bgView.alpha = 0;
} completion:^(BOOL finished) {
if (self.delegate && [self.delegate respondsToSelector:@selector(tfPopupMenuDidDismiss)]) {
[self.delegate tfPopupMenuDidDismiss];
}
self.delegate = nil;
[self removeFromSuperview];
[_bgView removeFromSuperview];
}];
}
/** 显示 */
- (void)show
{
[kMainWindow addSubview:_bgView];
[kMainWindow addSubview:self];
TFPopupMenuCell *cell = [self getLastVisibleCell];
cell.isShowSeparator = NO;
// 显示动画,缩小--->正常 alpha:0---->1
self.layer.affineTransform = CGAffineTransformMakeScale(0.1, 0.1);
[UIView animateWithDuration:0.25 animations:^{
self.layer.affineTransform = CGAffineTransformMakeScale(1.0, 1.0);
self.alpha = 1;
_bgView.alpha = 1;
}];
}
- (void)showAtPoint:(CGPoint)point
{
_mainView.layer.mask = [self getMaskLayerWithPoint:point];
[self show];
}
- (void)showRelyOnView:(UIView *)view
{
// view的坐标转换到keyWindow下的坐标
CGRect absoluteRect = [view convertRect:view.bounds toView:kMainWindow];
// 取view底部的中点
CGPoint relyPoint = CGPointMake(absoluteRect.origin.x + absoluteRect.size.width * 0.5, absoluteRect.origin.y + absoluteRect.size.height);
_mainView.layer.mask = [self getMaskLayerWithPoint:relyPoint];
if (self.y < _anchorPoint.y) // 控件上方显示
{
self.y -= absoluteRect.size.height;
}
[self show];
}
+ (instancetype)showAtPoint:(CGPoint)point
titles:(NSArray *)titles
icons:(NSArray *)icons
menuWidth:(CGFloat)itemWidth
delegate:(id<TFPopupMenuDelegate>)delegate
{
TFPopupMenu *popupMenu = [[TFPopupMenu alloc] initWithTitles:titles
icons:icons
menuWidth:itemWidth
delegate:delegate];
[popupMenu showAtPoint:point];
return popupMenu;
}
+ (instancetype)showRelyOnView:(UIView *)view
titles:(NSArray *)titles
icons:(NSArray *)icons
menuWidth:(CGFloat)itemWidth
delegate:(id<TFPopupMenuDelegate>)delegate
{
TFPopupMenu *popupMenu = [[TFPopupMenu alloc] initWithTitles:titles
icons:icons
menuWidth:itemWidth
delegate:delegate];
[popupMenu showRelyOnView:view];
return popupMenu;
}
#pragma mark - UITableViewDelegate
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _titles.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = @"tfPopupMenuIdentifier";
TFPopupMenuCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (!cell) {
cell = [[TFPopupMenuCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identifier];
}
cell.backgroundColor = [UIColor clearColor];
cell.textLabel.textColor = _textColor;
cell.textLabel.font = [UIFont systemFontOfSize:_fontSize];
cell.textLabel.text = _titles[indexPath.row];
cell.separatorColor = _seperatorColor;
if (_icons.count >= indexPath.row + 1) // 有icons
{
if ([_icons[indexPath.row] isKindOfClass:[NSString class]]) // 图片名称
{
cell.imageView.image = [UIImage imageNamed:_icons[indexPath.row]];
}
else if ([_icons[indexPath.row] isKindOfClass:[UIImage class]]) // UIImage
{
cell.imageView.image = _icons[indexPath.row];
}
}
else
{
cell.imageView.image = nil;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if (_dismissOnSelected) {
[self dismiss];
}
// 代理调用,对响应做判断
if (self.delegate && [self.delegate respondsToSelector:@selector(tfPopupMenuDidSelectedAtIndex:tfPopupMenu:)])
{
[self.delegate tfPopupMenuDidSelectedAtIndex:indexPath.row tfPopupMenu:self];
}
}
#pragma mark - UIScrollViewDelegate
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
TFPopupMenuCell *cell = [self getLastVisibleCell];
cell.isShowSeparator = YES; // 开始拖拽,cell显示分割线
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
TFPopupMenuCell *cell = [self getLastVisibleCell];
cell.isShowSeparator = NO; // 结束滚动,cell不显示分割线
}
- (TFPopupMenuCell *)getLastVisibleCell
{
// talbeView 可见cell的indexPath
NSArray <NSIndexPath *> *indexPaths = [_contentView indexPathsForVisibleRows];
// "<" 降序排列
indexPaths = [indexPaths sortedArrayUsingComparator:^NSComparisonResult(NSIndexPath* _Nonnull obj1, NSIndexPath* _Nonnull obj2) {
return obj1.row < obj2.row;
}];
NSIndexPath *indexPath = indexPaths.firstObject;
return [_contentView cellForRowAtIndexPath:indexPath];
}
#pragma mark - Private Functions
// 改变属性,需要tableView重新加载
- (void)setType:(TFPopupMenuType)type
{
_type = type;
switch (type) {
case TFPopupMenuTypeDark:
{
_textColor = [UIColor lightGrayColor];
_contentColor = [UIColor colorWithRed:0.25 green:0.27 blue:0.29 alpha:1];
_seperatorColor = [UIColor lightGrayColor];
}
break;
case TFPopupMenuTypeDefault:
{
_textColor = [UIColor blackColor];
_contentColor = [UIColor whiteColor];
_seperatorColor = [UIColor lightGrayColor];
}
break;
default:
break;
}
_mainView.backgroundColor = _contentColor;
[_contentView reloadData];
}
- (void)setFontSize:(CGFloat)fontSize
{
_fontSize = fontSize;
[_contentView reloadData];
}
- (void)setTextColor:(UIColor *)textColor
{
_textColor = textColor;
[_contentView reloadData];
}
- (void)setDismissOnTouchOutside:(BOOL)dismissOnTouchOutside
{
_dismissOnTouchOutside = dismissOnTouchOutside;
// 不需要时,点击移除手势
if (!_dismissOnTouchOutside) {
for (UIGestureRecognizer *gr in _bgView.gestureRecognizers) {
[_bgView removeGestureRecognizer:gr];
}
}
}
- (void)setIsShowShadow:(BOOL)isShowShadow
{
_isShowShadow = isShowShadow;
// 去除阴影
if (!isShowShadow) {
self.layer.shadowOpacity = 0.0;
self.layer.shadowOffset = CGSizeMake(0, 0);
self.layer.shadowRadius = 0.0;
}
}
// @todo
// 整体view 上移、或下移;
- (void)setOffset:(CGFloat)offset
{
_offset = offset;
if (offset < 0) {
offset = 0.0;
}
self.y += self.y >= _anchorPoint.y ? offset : -offset;
}
- (void)setCornerRadius:(CGFloat)cornerRadius
{
kCornerRadius = cornerRadius;
_mainView.layer.mask = [self drawMaskLayer]; // 通过mask,控制View形状;
// @todo
// 好像整个View翻转了;
if (self.y < _anchorPoint.y) {
_mainView.layer.mask.affineTransform = CGAffineTransformMakeRotation(M_PI);
}
}
#pragma mark - Mask Layer
- (void)setAnimationAnchorPoint:(CGPoint)point
{
CGRect originRect = self.frame;
self.layer.anchorPoint = point; // 修改锚点位置;
self.frame = originRect;
}
/**
* 修改锚点位置
*
* 根据锚点翻转;
*/
- (void)determineAnchorPoint
{
CGPoint aPoint = CGPointMake(0.5, 0.5);
if (CGRectGetMaxY(self.frame) > kScreenHeight) {
aPoint = CGPointMake(fabs(kArrowPosition) / self.width, 1); // 锚点在下边(0-1, 1)
}
else {
aPoint = CGPointMake(fabs(kArrowPosition) / self.width, 0); // 锚点在上边(0-1, 1)
}
[self setAnimationAnchorPoint:aPoint];
}
/**
* mask层,用于动画
*/
- (CAShapeLayer *)getMaskLayerWithPoint:(CGPoint)point
{
[self setArrowPointingWhere:point];
CAShapeLayer *layer = [self drawMaskLayer];
[self determineAnchorPoint];
if (CGRectGetMaxY(self.frame) > kScreenHeight) // 整体翻转了,根据锚点翻转;
{
// 调整箭头位置
kArrowPosition = self.width - kArrowPosition - kArrowWidth;
layer = [self drawMaskLayer];
layer.affineTransform = CGAffineTransformMakeRotation(M_PI);
self.y = _anchorPoint.y - self.height; // 左上角往上移动下
}
// 添加偏移 +:向下方向, -:翻转了,向上了;
self.y += self.y >= _anchorPoint.y ? _offset : - _offset;
return layer;
}
/**
* 设置箭头位置;
*
* anchorPoint,点击位置坐标点,控件下边中点;
*/
- (void)setArrowPointingWhere:(CGPoint)anchorPoint
{
_anchorPoint = anchorPoint;
// 整体view的左上角x、y
self.x = anchorPoint.x - kArrowPosition - 0.5 *kArrowWidth;
self.y = anchorPoint.y;
CGFloat maxX = CGRectGetMaxX(self.frame);
CGFloat minX = CGRectGetMinX(self.frame);
// 调整x;
if (maxX > kScreenWidth - 10) // 最右边
{
self.x = kScreenWidth - 10 - self.width;
}
else if (minX < 10) // 最左边
{
self.x = 10;
}
// 必须重新获取
maxX = CGRectGetMaxX(self.frame); // frame 右边x
minX = CGRectGetMinX(self.frame); // frame 左边x
// 调整箭头位置,kArrowPosition,三角形左下点
if ((anchorPoint.x <= maxX - kCornerRadius) && (anchorPoint.x >= minX + kCornerRadius))
{
kArrowPosition = anchorPoint.x - minX - 0.5*kArrowWidth;
}
else if (anchorPoint.x < minX + kCornerRadius) // 整体最靠左,调整箭头位置
{
kArrowPosition = kCornerRadius;
}
else // 整体最靠右
{
kArrowPosition = self.width - kCornerRadius - kArrowWidth;
}
}
- (CAShapeLayer *)drawMaskLayer
{
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = _mainView.bounds;
// 4个角圆心
CGPoint topLeftArcCenter = CGPointMake(kCornerRadius, kArrowHeight + kCornerRadius);
CGPoint topRightArcCenter = CGPointMake(self.width-kCornerRadius, kArrowHeight + kCornerRadius);
CGPoint bottomLeftArcCenter = CGPointMake(kCornerRadius, self.height - kArrowHeight - kCornerRadius);
CGPoint bottomRightArcCenter = CGPointMake(self.width - kCornerRadius, self.height - kArrowHeight - kCornerRadius);
UIBezierPath *path = [UIBezierPath bezierPath];
// left-top,左上角,箭头高度、圆角半径
[path moveToPoint:CGPointMake(0, kArrowHeight + kCornerRadius)];
[path addLineToPoint:CGPointMake(0, bottomLeftArcCenter.y)];
// clockwise:NO 逆时针
[path addArcWithCenter:bottomLeftArcCenter radius:kCornerRadius startAngle:-M_PI endAngle:-M_PI-M_PI_2 clockwise:NO];
[path addLineToPoint:CGPointMake(self.width - kCornerRadius, self.height - kArrowHeight)];
[path addArcWithCenter:bottomRightArcCenter radius:kCornerRadius startAngle:-M_PI-M_PI_2 endAngle:-M_PI*2 clockwise:NO];
[path addLineToPoint:CGPointMake(self.width, kArrowHeight + kCornerRadius)]; // 右上角,距离圆弧
[path addArcWithCenter:topRightArcCenter radius:kCornerRadius startAngle:0 endAngle:-M_PI_2 clockwise:NO];
// 箭头的线 kArrowPosition,最左那个点;
[path addLineToPoint:CGPointMake(kArrowPosition + kArrowWidth, kArrowHeight)];
[path addLineToPoint:CGPointMake(kArrowPosition + 0.5*kArrowWidth, 0)];
[path addLineToPoint:CGPointMake(kArrowPosition, kArrowHeight)];
[path addLineToPoint:CGPointMake(kCornerRadius, kArrowHeight)];
[path addArcWithCenter:topLeftArcCenter radius:kCornerRadius startAngle:-M_PI_2 endAngle:-M_PI clockwise:NO];
[path closePath];
maskLayer.path = path.CGPath;
return maskLayer;
}
@end