在iPad上,苹果提供的有专门的菜单显示的控制器。而在iphone上却没有。所以需要我们自定义。下面就是我所介绍的这么一个菜单组件的大概样子:
![组件概览](http://img.blog.csdn.net/20151204180632512)
#import <Foundation/Foundation.h>
@interface KxMenuItem : NSObject
@property (readwrite, nonatomic, strong) UIImage *image;
@property (readwrite, nonatomic, strong) NSString *title;
@property (readwrite, nonatomic) id target;
@property (readwrite, nonatomic) SEL action;
@property (readwrite, nonatomic, strong) UIColor *foreColor;
@property (readwrite, nonatomic) NSTextAlignment alignment;
+ (instancetype) menuItem:(NSString *) title
image:(UIImage *) image
target:(id)target
action:(SEL) action;
@end
@interface KxMenu : NSObject
+ (void) showMenuInView:(UIView *)view
fromRect:(CGRect)rect
menuItems:(NSArray *)menuItems;
+ (void) dismissMenu;
+ (UIColor *) tintColor;
+ (void) setTintColor: (UIColor *) tintColor;
+ (UIFont *) titleFont;
+ (void) setTitleFont: (UIFont *) titleFont;
@end
#import "KxMenu.h"
#import <QuartzCore/QuartzCore.h>
const CGFloat kArrowSize = 12.f;
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
@interface KxMenuView : UIView
@end
@interface KxMenuOverlay : UIView
@end
@implementation KxMenuOverlay
// - (void) dealloc { NSLog(@"dealloc %@", self); }
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor clearColor];
self.opaque = NO;
}
return self;
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
UIView *touched = [[touches anyObject] view];
if (touched == self) {
for (UIView *v in self.subviews) {
if ([v isKindOfClass:[KxMenuView class]]
&& [v respondsToSelector:@selector(dismissMenu:)]) {
[v performSelector:@selector(dismissMenu:) withObject:@(YES)];
}
}
}
}
@end
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
@implementation KxMenuItem
+ (instancetype) menuItem:(NSString *) title
image:(UIImage *) image
target:(id)target
action:(SEL) action
{
return [[KxMenuItem alloc] init:title
image:image
target:target
action:action];
}
- (id) init:(NSString *) title
image:(UIImage *) image
target:(id)target
action:(SEL) action
{
NSParameterAssert(title.length || image);
self = [super init];
if (self) {
_title = title;
_image = image;
_target = target;
_action = action;
}
return self;
}
- (BOOL) enabled
{
return _target != nil && _action != NULL;
}
- (void) performAction
{
__strong id target = self.target;
if (target && [target respondsToSelector:_action]) {
[target performSelectorOnMainThread:_action withObject:self waitUntilDone:YES];
}
}
- (NSString *) description
{
return [NSString stringWithFormat:@"<%@ #%p %@>", [self class], self, _title];
}
@end
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
typedef enum {
KxMenuViewArrowDirectionNone,
KxMenuViewArrowDirectionUp,
KxMenuViewArrowDirectionDown,
KxMenuViewArrowDirectionLeft,
KxMenuViewArrowDirectionRight,
} KxMenuViewArrowDirection;
@implementation KxMenuView {
KxMenuViewArrowDirection _arrowDirection;
CGFloat _arrowPosition;
UIView *_contentView;
NSArray *_menuItems;
}
- (id)init
{
self = [super initWithFrame:CGRectZero];
if(self) {
self.backgroundColor = [UIColor clearColor];
self.opaque = YES;
self.alpha = 0;
// self.layer.shadowOpacity = 0.5;
// self.layer.shadowOffset = CGSizeMake(2, 2);
// self.layer.shadowRadius = 2;
}
return self;
}
// - (void) dealloc { NSLog(@"dealloc %@", self); }
- (void) setupFrameInView:(UIView *)view
fromRect:(CGRect)fromRect
{
const CGSize contentSize = _contentView.frame.size;
const CGFloat outerWidth = view.bounds.size.width;
const CGFloat outerHeight = view.bounds.size.height;
const CGFloat rectX0 = fromRect.origin.x;
const CGFloat rectX1 = fromRect.origin.x + fromRect.size.width;
const CGFloat rectXM = fromRect.origin.x + fromRect.size.width * 0.5f;
const CGFloat rectY0 = fromRect.origin.y;
const CGFloat rectY1 = fromRect.origin.y + fromRect.size.height;
const CGFloat rectYM = fromRect.origin.y + fromRect.size.height * 0.5f;;
const CGFloat widthPlusArrow = contentSize.width + kArrowSize;
const CGFloat heightPlusArrow = contentSize.height + kArrowSize;
const CGFloat widthHalf = contentSize.width * 0.5f;
const CGFloat heightHalf = contentSize.height * 0.5f;
// NSLog(@"%f %f %f \n%f %f %f \n%f %f \n%f %f",rectX0,rectX1,rectXM,rectY0,rectY1,rectYM,widthPlusArrow,heightPlusArrow,outerWidth,outerHeight);
const CGFloat kMargin = 5.f;
if (heightPlusArrow < (outerHeight - rectY1)) {
if(rectX0 <= 0)
{
_arrowDirection = KxMenuViewArrowDirectionLeft;
CGPoint point = (CGPoint){
rectX1,
rectYM - heightHalf
};
if (point.y < kMargin)
point.y = kMargin;
if ((point.y + contentSize.height + kMargin) > outerHeight)
point.y = outerHeight - contentSize.height - kMargin;
_arrowPosition = rectYM - point.y;
_contentView.frame = (CGRect){kArrowSize, 0, contentSize};
self.frame = (CGRect) {
point,
contentSize.width + kArrowSize,
contentSize.height
};
}
else
{
_arrowDirection = KxMenuViewArrowDirectionUp;
CGPoint point = (CGPoint){
rectXM - widthHalf,
rectY1
};
if (point.x < kMargin)
point.x = kMargin;
if ((point.x + contentSize.width + kMargin) > outerWidth)
point.x = outerWidth - contentSize.width - kMargin;
_arrowPosition = rectXM - point.x;
//_arrowPosition = MAX(16, MIN(_arrowPosition, contentSize.width - 16));
_contentView.frame = (CGRect){0, kArrowSize, contentSize};
self.frame = (CGRect) {
point,
contentSize.width,
contentSize.height + kArrowSize
};
}
} else if (heightPlusArrow < rectY0) {
_arrowDirection = KxMenuViewArrowDirectionDown;
CGPoint point = (CGPoint){
rectXM - widthHalf,
rectY0 - heightPlusArrow
};
if (point.x < kMargin)
point.x = kMargin;
if ((point.x + contentSize.width + kMargin) > outerWidth)
point.x = outerWidth - contentSize.width - kMargin;
_arrowPosition = rectXM - point.x;
_contentView.frame = (CGRect){CGPointZero, contentSize};
self.frame = (CGRect) {
point,
contentSize.width,
contentSize.height + kArrowSize
};
} else if (widthPlusArrow < (outerWidth - rectX1)) {
_arrowDirection = KxMenuViewArrowDirectionLeft;
CGPoint point = (CGPoint){
rectX1,
rectYM - heightHalf
};
if (point.y < kMargin)
point.y = kMargin;
if ((point.y + contentSize.height + kMargin) > outerHeight)
point.y = outerHeight - contentSize.height - kMargin;
_arrowPosition = rectYM - point.y;
_contentView.frame = (CGRect){kArrowSize, 0, contentSize};
self.frame = (CGRect) {
point,
contentSize.width + kArrowSize,
contentSize.height
};
} else if (widthPlusArrow < rectX0) {
_arrowDirection = KxMenuViewArrowDirectionRight;
CGPoint point = (CGPoint){
rectX0 - widthPlusArrow,
rectYM - heightHalf
};
if (point.y < kMargin)
point.y = kMargin;
if ((point.y + contentSize.height + 5) > outerHeight)
point.y = outerHeight - contentSize.height - kMargin;
_arrowPosition = rectYM - point.y;
_contentView.frame = (CGRect){CGPointZero, contentSize};
self.frame = (CGRect) {
point,
contentSize.width + kArrowSize,
contentSize.height
};
} else {
_arrowDirection = KxMenuViewArrowDirectionNone;
self.frame = (CGRect) {
(outerWidth - contentSize.width) * 0.5f,
(outerHeight - contentSize.height) * 0.5f,
contentSize,
};
}
}
- (void)showMenuInView:(UIView *)view
fromRect:(CGRect)rect
menuItems:(NSArray *)menuItems
{
if (_menuItems)
{
[_menuItems release];
_menuItems = Nil;
}
_menuItems = menuItems.copy;
_contentView = [self mkContentView];
[self addSubview:_contentView];
[self setupFrameInView:view fromRect:rect];
KxMenuOverlay *overlay = [[KxMenuOverlay alloc] initWithFrame:view.bounds];
[overlay addSubview:self];
[view addSubview:overlay];
_contentView.hidden = YES;
const CGRect toFrame = self.frame;
self.frame = (CGRect){self.arrowPoint, 1, 1};
[UIView animateWithDuration:0.2
animations:^(void) {
self.alpha = 1.0f;
self.frame = toFrame;
} completion:^(BOOL completed) {
_contentView.hidden = NO;
}];
}
- (void)dismissMenu:(BOOL) animated
{
if (self.superview) {
if (animated) {
_contentView.hidden = YES;
const CGRect toFrame = (CGRect){self.arrowPoint, 1, 1};
[UIView animateWithDuration:0.2
animations:^(void) {
self.alpha = 0;
self.frame = toFrame;
} completion:^(BOOL finished) {
if ([self.superview isKindOfClass:[KxMenuOverlay class]])
[self.superview removeFromSuperview];
[self removeFromSuperview];
}];
} else {
if ([self.superview isKindOfClass:[KxMenuOverlay class]])
[self.superview removeFromSuperview];
[self removeFromSuperview];
}
}
}
- (void)performAction:(id)sender
{
[self dismissMenu:YES];
UIButton *button = (UIButton *)sender;
KxMenuItem *menuItem = _menuItems[button.tag];
[menuItem performAction];
}
- (UIView *) mkContentView
{
for (UIView *v in self.subviews) {
[v removeFromSuperview];
}
if (!_menuItems.count)
return nil;
const CGFloat kMinMenuItemHeight = 32.f;
const CGFloat kMinMenuItemWidth = 32.f;
const CGFloat kMarginX = 10.f;
const CGFloat kMarginY = 5.f;
UIFont *titleFont = [KxMenu titleFont];
if (!titleFont) titleFont = [UIFont boldSystemFontOfSize:16];
CGFloat maxImageWidth = 0;
CGFloat maxItemHeight = 0;
CGFloat maxItemWidth = 0;
for (KxMenuItem *menuItem in _menuItems) {
const CGSize imageSize = menuItem.image.size;
if (imageSize.width > maxImageWidth)
maxImageWidth = imageSize.width;
}
for (KxMenuItem *menuItem in _menuItems) {
const CGSize titleSize = [menuItem.title sizeWithFont:titleFont];
const CGSize imageSize = menuItem.image.size;
const CGFloat itemHeight = MAX(titleSize.height, imageSize.height) + kMarginY * 2;
const CGFloat itemWidth = (menuItem.image ? maxImageWidth + kMarginX : 0) + titleSize.width + kMarginX * 4;
if (itemHeight > maxItemHeight)
maxItemHeight = itemHeight;
if (itemWidth > maxItemWidth)
maxItemWidth = itemWidth;
}
maxItemWidth = MAX(maxItemWidth, kMinMenuItemWidth);
maxItemHeight = MAX(maxItemHeight, kMinMenuItemHeight);
const CGFloat titleX = kMarginX * 2 + (maxImageWidth > 0 ? maxImageWidth + kMarginX : 0);
const CGFloat titleWidth = maxItemWidth - titleX - kMarginX;
UIImage *selectedImage = [KxMenuView selectedImage:(CGSize){maxItemWidth, maxItemHeight + 2}];
UIImage *gradientLine = [KxMenuView gradientLine: (CGSize){maxItemWidth - kMarginX * 4, 1}];
UIView *contentView = [[UIView alloc] initWithFrame:CGRectZero];
contentView.autoresizingMask = UIViewAutoresizingNone;
contentView.backgroundColor = [UIColor clearColor];
contentView.opaque = NO;
CGFloat itemY = kMarginY * 2;
NSUInteger itemNum = 0;
for (KxMenuItem *menuItem in _menuItems) {
const CGRect itemFrame = (CGRect){0, itemY, maxItemWidth, maxItemHeight};
UIView *itemView = [[UIView alloc] initWithFrame:itemFrame];
itemView.autoresizingMask = UIViewAutoresizingNone;
itemView.backgroundColor = [UIColor clearColor];
itemView.opaque = NO;
[contentView addSubview:itemView];
if (menuItem.enabled) {
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.tag = itemNum;
button.frame = itemView.bounds;
button.enabled = menuItem.enabled;
button.backgroundColor = [UIColor clearColor];
button.opaque = NO;
button.autoresizingMask = UIViewAutoresizingNone;
[button addTarget:self
action:@selector(performAction:)
forControlEvents:UIControlEventTouchUpInside];
[button setBackgroundImage:selectedImage forState:UIControlStateHighlighted];
[itemView addSubview:button];
}
if (menuItem.title.length) {
CGRect titleFrame;
if (!menuItem.enabled && !menuItem.image) {
titleFrame = (CGRect){
kMarginX * 2,
kMarginY,
maxItemWidth - kMarginX * 4,
maxItemHeight - kMarginY * 2
};
} else {
titleFrame = (CGRect){
titleX,
kMarginY,
titleWidth,
maxItemHeight - kMarginY * 2
};
}
UILabel *titleLabel = [[UILabel alloc] initWithFrame:titleFrame];
titleLabel.text = menuItem.title;
titleLabel.font = titleFont;
titleLabel.textAlignment = menuItem.alignment;
titleLabel.textColor = menuItem.foreColor ? menuItem.foreColor : [UIColor whiteColor];
titleLabel.backgroundColor = [UIColor clearColor];
titleLabel.autoresizingMask = UIViewAutoresizingNone;
//titleLabel.backgroundColor = [UIColor greenColor];
[itemView addSubview:titleLabel];
}
if (menuItem.image) {
const CGRect imageFrame = {kMarginX * 2, kMarginY, maxImageWidth, maxItemHeight - kMarginY * 2};
UIImageView *imageView = [[UIImageView alloc] initWithFrame:imageFrame];
imageView.image = menuItem.image;
imageView.clipsToBounds = YES;
imageView.contentMode = UIViewContentModeCenter;
imageView.autoresizingMask = UIViewAutoresizingNone;
[itemView addSubview:imageView];
}
if (itemNum < _menuItems.count - 1) {
UIImageView *gradientView = [[UIImageView alloc] initWithImage:gradientLine];
gradientView.frame = (CGRect){kMarginX * 2, maxItemHeight + 1, gradientLine.size};
gradientView.contentMode = UIViewContentModeLeft;
[itemView addSubview:gradientView];
itemY += 2;
}
itemY += maxItemHeight;
++itemNum;
}
contentView.frame = (CGRect){0, 0, maxItemWidth, itemY + kMarginY * 2};
return contentView;
}
- (CGPoint) arrowPoint
{
CGPoint point;
if (_arrowDirection == KxMenuViewArrowDirectionUp) {
point = (CGPoint){ CGRectGetMinX(self.frame) + _arrowPosition, CGRectGetMinY(self.frame) };
} else if (_arrowDirection == KxMenuViewArrowDirectionDown) {
point = (CGPoint){ CGRectGetMinX(self.frame) + _arrowPosition, CGRectGetMaxY(self.frame)};
} else if (_arrowDirection == KxMenuViewArrowDirectionLeft) {
point = (CGPoint){ CGRectGetMinX(self.frame), CGRectGetMinY(self.frame) + _arrowPosition };
} else if (_arrowDirection == KxMenuViewArrowDirectionRight) {
point = (CGPoint){ CGRectGetMaxX(self.frame), CGRectGetMinY(self.frame) + _arrowPosition };
} else {
point = self.center;
}
return point;
}
+ (UIImage *) selectedImage: (CGSize) size
{
const CGFloat locations[] = {0,1};
const CGFloat components[] = {
0.216, 0.471, 0.871, 1,
0.059, 0.353, 0.839, 1,
};
return [self gradientImageWithSize:size locations:locations components:components count:2];
}
+ (UIImage *) gradientLine: (CGSize) size
{
const CGFloat locations[5] = {0,0.2,0.5,0.8,1};
// const CGFloat R = 0.44f, G = 0.44f, B = 0.44f;
//
// const CGFloat components[20] = {
// R,G,B,0.1,
// R,G,B,0.4,
// R,G,B,0.7,
// R,G,B,0.4,
// R,G,B,0.1
// };
const CGFloat R = 0, G = 0, B = 0;
const CGFloat components[20] =
{
R,G,B,0.2,
R,G,B,0.2,
R,G,B,0.2,
R,G,B,0.2,
R,G,B,0.2
};
return [self gradientImageWithSize:size locations:locations components:components count:5];
}
+ (UIImage *) gradientImageWithSize:(CGSize) size
locations:(const CGFloat []) locations
components:(const CGFloat []) components
count:(NSUInteger)count
{
UIGraphicsBeginImageContextWithOptions(size, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGGradientRef colorGradient = CGGradientCreateWithColorComponents(colorSpace, components, locations, 2);
CGColorSpaceRelease(colorSpace);
CGContextDrawLinearGradient(context, colorGradient, (CGPoint){0, 0}, (CGPoint){size.width, 0}, 0);
CGGradientRelease(colorGradient);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
- (void) drawRect:(CGRect)rect
{
[self drawBackground:self.bounds
inContext:UIGraphicsGetCurrentContext()];
}
- (void)drawBackground:(CGRect)frame
inContext:(CGContextRef) context
{
CGFloat R0 = 0.267, G0 = 0.303, B0 = 0.335;
CGFloat R1 = 0.040, G1 = 0.040, B1 = 0.040;
UIColor *tintColor = [KxMenu tintColor];
if (tintColor) {
CGFloat a;
[tintColor getRed:&R0 green:&G0 blue:&B0 alpha:&a];
}
CGFloat X0 = frame.origin.x;
CGFloat X1 = frame.origin.x + frame.size.width;
CGFloat Y0 = frame.origin.y;
CGFloat Y1 = frame.origin.y + frame.size.height;
// render arrow
UIBezierPath *arrowPath = [UIBezierPath bezierPath];
[[UIColor whiteColor]setStroke];
// fix the issue with gap of arrow's base if on the edge
const CGFloat kEmbedFix = 3.f;
if (_arrowDirection == KxMenuViewArrowDirectionUp) {
const CGFloat arrowXM = _arrowPosition;
const CGFloat arrowX0 = arrowXM - kArrowSize;
const CGFloat arrowX1 = arrowXM + kArrowSize;
const CGFloat arrowY0 = Y0;
const CGFloat arrowY1 = Y0 + kArrowSize + kEmbedFix;
[arrowPath moveToPoint: (CGPoint){arrowXM, arrowY0}];
[arrowPath addLineToPoint: (CGPoint){arrowX1, arrowY1}];
[arrowPath addLineToPoint: (CGPoint){arrowX0, arrowY1}];
[arrowPath addLineToPoint: (CGPoint){arrowXM, arrowY0}];
[[UIColor colorWithRed:R0 green:G0 blue:B0 alpha:0.4] set];
Y0 += kArrowSize;
} else if (_arrowDirection == KxMenuViewArrowDirectionDown) {
const CGFloat arrowXM = _arrowPosition;
const CGFloat arrowX0 = arrowXM - kArrowSize;
const CGFloat arrowX1 = arrowXM + kArrowSize;
const CGFloat arrowY0 = Y1 - kArrowSize - kEmbedFix + 3.f;
const CGFloat arrowY1 = Y1;
[arrowPath moveToPoint: (CGPoint){arrowXM, arrowY1}];
[arrowPath addLineToPoint: (CGPoint){arrowX1, arrowY0}];
[arrowPath addLineToPoint: (CGPoint){arrowX0, arrowY0}];
[arrowPath addLineToPoint: (CGPoint){arrowXM, arrowY1}];
[[UIColor colorWithRed:R1 green:G1 blue:B1 alpha:0.4] set];
Y1 -= kArrowSize;
} else if (_arrowDirection == KxMenuViewArrowDirectionLeft) {
const CGFloat arrowYM = _arrowPosition;
const CGFloat arrowX0 = X0;
const CGFloat arrowX1 = X0 + kArrowSize + kEmbedFix;
const CGFloat arrowY0 = arrowYM - kArrowSize;;
const CGFloat arrowY1 = arrowYM + kArrowSize;
[arrowPath moveToPoint: (CGPoint){arrowX0, arrowYM}];
[arrowPath addLineToPoint: (CGPoint){arrowX1, arrowY0}];
[arrowPath addLineToPoint: (CGPoint){arrowX1, arrowY1}];
[arrowPath addLineToPoint: (CGPoint){arrowX0, arrowYM}];
[[UIColor colorWithRed:R0 green:G0 blue:B0 alpha:0.4] set];
X0 += kArrowSize;
} else if (_arrowDirection == KxMenuViewArrowDirectionRight) {
const CGFloat arrowYM = _arrowPosition;
const CGFloat arrowX0 = X1;
const CGFloat arrowX1 = X1 - kArrowSize - kEmbedFix;
const CGFloat arrowY0 = arrowYM - kArrowSize;;
const CGFloat arrowY1 = arrowYM + kArrowSize;
[arrowPath moveToPoint: (CGPoint){arrowX0, arrowYM}];
[arrowPath addLineToPoint: (CGPoint){arrowX1, arrowY0}];
[arrowPath addLineToPoint: (CGPoint){arrowX1, arrowY1}];
[arrowPath addLineToPoint: (CGPoint){arrowX0, arrowYM}];
[[UIColor colorWithRed:R1 green:G1 blue:B1 alpha:0.4] set];
X1 -= kArrowSize;
}
[arrowPath fill];
[arrowPath stroke];
// render body
const CGRect bodyFrame = {X0, Y0, X1 - X0, Y1 - Y0};
UIBezierPath *borderPath = [UIBezierPath bezierPathWithRoundedRect:bodyFrame
cornerRadius:8];
const CGFloat locations[] = {0, 1};
const CGFloat components[] = {
R0, G0, B0, 0.4,
R1, G1, B1, 0.4,
};
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace,
components,
locations,
sizeof(locations)/sizeof(locations[0]));
CGColorSpaceRelease(colorSpace);
[borderPath addClip];
[borderPath stroke];
CGPoint start, end;
if (_arrowDirection == KxMenuViewArrowDirectionLeft ||
_arrowDirection == KxMenuViewArrowDirectionRight) {
start = (CGPoint){X0, Y0};
end = (CGPoint){X1, Y0};
} else {
start = (CGPoint){X0, Y0};
end = (CGPoint){X0, Y1};
}
CGContextDrawLinearGradient(context, gradient, start, end, 0);
CGGradientRelease(gradient);
}
@end
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
static KxMenu *gMenu;
static UIColor *gTintColor;
static UIFont *gTitleFont;
@implementation KxMenu {
KxMenuView *_menuView;
BOOL _observing;
}
+ (instancetype) sharedMenu
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
gMenu = [[KxMenu alloc] init];
});
return gMenu;
}
- (id) init
{
NSAssert(!gMenu, @"singleton object");
self = [super init];
if (self) {
}
return self;
}
- (void) dealloc
{
if (_observing) {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
}
- (void) showMenuInView:(UIView *)view
fromRect:(CGRect)rect
menuItems:(NSArray *)menuItems
{
NSParameterAssert(view);
NSParameterAssert(menuItems.count);
if (_menuView) {
[_menuView dismissMenu:NO];
_menuView = nil;
}
if (!_observing) {
_observing = YES;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(orientationWillChange:)
name:UIApplicationWillChangeStatusBarOrientationNotification
object:nil];
}
_menuView = [[KxMenuView alloc] init];
[_menuView showMenuInView:view fromRect:rect menuItems:menuItems];
}
- (void) dismissMenu
{
if (_menuView) {
[_menuView dismissMenu:NO];
_menuView = nil;
}
if (_observing) {
_observing = NO;
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
}
- (void) orientationWillChange: (NSNotification *) n
{
[self dismissMenu];
}
+ (void) showMenuInView:(UIView *)view
fromRect:(CGRect)rect
menuItems:(NSArray *)menuItems
{
[[self sharedMenu] showMenuInView:view fromRect:rect menuItems:menuItems];
}
+ (void) dismissMenu
{
[[self sharedMenu] dismissMenu];
}
+ (UIColor *) tintColor
{
return gTintColor;
}
+ (void) setTintColor: (UIColor *) tintColor
{
if (tintColor != gTintColor) {
gTintColor = tintColor;
}
}
+ (UIFont *) titleFont
{
return gTitleFont;
}
+ (void) setTitleFont: (UIFont *) titleFont
{
if (titleFont != gTitleFont) {
gTitleFont = titleFont;
}
}
@end
其用法非常简单,只需要在项目中导入以上文件。然后构造参数调用之:
以下代码的目的是让菜单显示在m_addbutton的下方:
CGRect addbtnframe = m_popupload.m_addbutton.frame;
CGRect frame = CGRectMake(addbtnframe.origin.x, addbtnframe.origin.y-30, addbtnframe.size.width, addbtnframe.size.height);
//frame.size.width -= 90;
NSArray *menuItems =
@[
[KxMenuItem menuItem:NSLocalizedString(@"Album",nil)
image:nil//[UIImage imageNamed:@"action_icon"]
target:self
action:@selector(layonAlbumPicker)],
[KxMenuItem menuItem:NSLocalizedString(@"Voice Memos",nil)
image:nil//[UIImage imageNamed:@"check_icon"]
target:self
action:@selector(layonVoiceMemos)],
[KxMenuItem menuItem:@"哈哈哈"
image:nil
target:self
action:nil]
];
[KxMenu showMenuInView:m_popupload.view
fromRect:frame
menuItems:menuItems];