Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Turns the menu into a scrollable view. If the menu is greater than th… #33

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 75 additions & 51 deletions Source/KxMenu.m
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
*/

/*
Some ideas was taken from QBPopupMenu project by Katsuma Tanaka.
https://github.com/questbeat/QBPopupMenu
*/
*/

#import "KxMenu.h"
#import <QuartzCore/QuartzCore.h>
Expand All @@ -52,8 +52,6 @@ @interface KxMenuOverlay : UIView

@implementation KxMenuOverlay

// - (void) dealloc { NSLog(@"dealloc %@", self); }

- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
Expand Down Expand Up @@ -143,7 +141,7 @@ - (NSString *) description
////////////////////////////////////////////////////////////////////////////////

typedef enum {

KxMenuViewArrowDirectionNone,
KxMenuViewArrowDirectionUp,
KxMenuViewArrowDirectionDown,
Expand All @@ -162,9 +160,9 @@ @implementation KxMenuView {

- (id)init
{
self = [super initWithFrame:CGRectZero];
self = [super initWithFrame:CGRectZero];
if(self) {

self.backgroundColor = [UIColor clearColor];
self.opaque = YES;
self.alpha = 0;
Expand All @@ -177,8 +175,6 @@ - (id)init
return self;
}

// - (void) dealloc { NSLog(@"dealloc %@", self); }

- (void) setupFrameInView:(UIView *)view
fromRect:(CGRect)fromRect
{
Expand All @@ -202,7 +198,7 @@ - (void) setupFrameInView:(UIView *)view
const CGFloat kMargin = 5.f;

if (heightPlusArrow < (outerHeight - rectY1)) {

_arrowDirection = KxMenuViewArrowDirectionUp;
CGPoint point = (CGPoint){
rectXM - widthHalf,
Expand All @@ -216,9 +212,8 @@ - (void) setupFrameInView:(UIView *)view
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,
Expand Down Expand Up @@ -308,7 +303,7 @@ - (void) setupFrameInView:(UIView *)view
(outerHeight - contentSize.height) * 0.5f,
contentSize,
};
}
}
}

- (void)showMenuInView:(UIView *)view
Expand All @@ -321,7 +316,7 @@ - (void)showMenuInView:(UIView *)view
[self addSubview:_contentView];

[self setupFrameInView:view fromRect:rect];

KxMenuOverlay *overlay = [[KxMenuOverlay alloc] initWithFrame:view.bounds];
[overlay addSubview:self];
[view addSubview:overlay];
Expand All @@ -339,16 +334,16 @@ - (void)showMenuInView:(UIView *)view
} completion:^(BOOL completed) {
_contentView.hidden = NO;
}];

}

- (void)dismissMenu:(BOOL) animated
{
if (self.superview) {

if (animated) {

_contentView.hidden = YES;
_contentView.hidden = YES;
const CGRect toFrame = (CGRect){self.arrowPoint, 1, 1};

[UIView animateWithDuration:0.2
Expand Down Expand Up @@ -384,41 +379,61 @@ - (void)performAction:(id)sender

- (UIView *) mkContentView
{
bool scrollable = false;

for (UIView *v in self.subviews) {
[v removeFromSuperview];
}

if (!_menuItems.count)
return nil;


NSUInteger itemNum = [_menuItems count];

const CGFloat kMinMenuItemHeight = 32.f;
const CGFloat kMinMenuItemWidth = 32.f;
const CGFloat kMarginX = 10.f;
const CGFloat kMarginY = 5.f;
const CGFloat kMarginY = 3.5f;

CGRect screen = [[UIScreen mainScreen] bounds];
CGFloat screenY = screen.size.height;

CGFloat hypotheticalSize = kMinMenuItemHeight + 60 * 2 + kArrowSize;

int maxItemsToFitOnScreen = 0;

for (; ((maxItemsToFitOnScreen < itemNum) && (hypotheticalSize < screenY)); maxItemsToFitOnScreen++) {
hypotheticalSize += kMinMenuItemHeight;
}

itemNum = 0;

scrollable = (maxItemsToFitOnScreen < [_menuItems count]);


UIFont *titleFont = [KxMenu titleFont];
if (!titleFont) titleFont = [UIFont boldSystemFontOfSize:16];

CGFloat maxImageWidth = 0;
CGFloat maxImageWidth = 0;
CGFloat maxItemHeight = 0;
CGFloat maxItemWidth = 0;

for (KxMenuItem *menuItem in _menuItems) {

const CGSize imageSize = menuItem.image.size;
const CGSize imageSize = menuItem.image.size;
if (imageSize.width > maxImageWidth)
maxImageWidth = imageSize.width;
maxImageWidth = imageSize.width;
}

if (maxImageWidth) {
maxImageWidth += kMarginX;
}

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.enabled && !menuItem.image) ? titleSize.width : maxImageWidth + titleSize.width) + kMarginX * 4;

Expand All @@ -428,37 +443,38 @@ - (UIView *) mkContentView
if (itemWidth > maxItemWidth)
maxItemWidth = itemWidth;
}

maxItemWidth = MAX(maxItemWidth, kMinMenuItemWidth);
maxItemHeight = MAX(maxItemHeight, kMinMenuItemHeight);

const CGFloat titleX = kMarginX * 2 + maxImageWidth;
const CGFloat titleWidth = maxItemWidth - titleX - kMarginX * 2;

UIImage *selectedImage = [KxMenuView selectedImage:(CGSize){maxItemWidth, maxItemHeight + 2}];
UIImage *gradientLine = [KxMenuView gradientLine: (CGSize){maxItemWidth - kMarginX * 4, 1}];

UIView *contentView = [[UIView alloc] initWithFrame:CGRectZero];
UIScrollView *contentView = [[UIScrollView alloc] initWithFrame:CGRectZero];
[contentView setScrollEnabled:scrollable];
contentView.autoresizingMask = UIViewAutoresizingNone;
contentView.backgroundColor = [UIColor clearColor];
contentView.opaque = NO;

CGFloat itemY = kMarginY * 2;
NSUInteger itemNum = 0;
CGFloat itemY2 = itemY;

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.backgroundColor = [UIColor clearColor];
itemView.opaque = NO;

[contentView addSubview:itemView];

if (menuItem.enabled) {

UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.tag = itemNum;
button.frame = itemView.bounds;
Expand Down Expand Up @@ -507,7 +523,7 @@ - (UIView *) mkContentView
titleLabel.backgroundColor = [UIColor clearColor];
titleLabel.autoresizingMask = UIViewAutoresizingNone;
//titleLabel.backgroundColor = [UIColor greenColor];
[itemView addSubview:titleLabel];
[itemView addSubview:titleLabel];
}

if (menuItem.image) {
Expand All @@ -521,9 +537,12 @@ - (UIView *) mkContentView
[itemView addSubview:imageView];
}

if (itemNum < _menuItems.count - 1) {
++itemNum;

if (itemNum < [_menuItems count]) {

UIImageView *gradientView = [[UIImageView alloc] initWithImage:gradientLine];
[gradientView setUserInteractionEnabled:NO];
gradientView.frame = (CGRect){kMarginX * 2, maxItemHeight + 1, gradientLine.size};
gradientView.contentMode = UIViewContentModeLeft;
[itemView addSubview:gradientView];
Expand All @@ -532,10 +551,15 @@ - (UIView *) mkContentView
}

itemY += maxItemHeight;
++itemNum;
}

if (itemNum <= maxItemsToFitOnScreen)
itemY2 = itemY;
}


contentView.frame = (CGRect){0, 0, maxItemWidth, itemY + kMarginY * 2};
// Size of the box
contentView.frame = (CGRect){0, 0, maxItemWidth, (itemY2+10)};
contentView.contentSize = CGSizeMake(maxItemWidth, ((maxItemHeight+2) * itemNum+10));

return contentView;
}
Expand Down Expand Up @@ -584,7 +608,7 @@ + (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,
Expand Down Expand Up @@ -682,7 +706,7 @@ - (void)drawBackground:(CGRect)frame

} else if (_arrowDirection == KxMenuViewArrowDirectionLeft) {

const CGFloat arrowYM = _arrowPosition;
const CGFloat arrowYM = _arrowPosition;
const CGFloat arrowX0 = X0;
const CGFloat arrowX1 = X0 + kArrowSize + kEmbedFix;
const CGFloat arrowY0 = arrowYM - kArrowSize;;
Expand All @@ -699,7 +723,7 @@ - (void)drawBackground:(CGRect)frame

} else if (_arrowDirection == KxMenuViewArrowDirectionRight) {

const CGFloat arrowYM = _arrowPosition;
const CGFloat arrowYM = _arrowPosition;
const CGFloat arrowX0 = X1;
const CGFloat arrowX1 = X1 - kArrowSize - kEmbedFix;
const CGFloat arrowY0 = arrowYM - kArrowSize;;
Expand All @@ -716,14 +740,14 @@ - (void)drawBackground:(CGRect)frame
}

[arrowPath fill];

// 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, 1,
Expand All @@ -744,7 +768,7 @@ - (void)drawBackground:(CGRect)frame

if (_arrowDirection == KxMenuViewArrowDirectionLeft ||
_arrowDirection == KxMenuViewArrowDirectionRight) {

start = (CGPoint){X0, Y0};
end = (CGPoint){X1, Y0};

Expand All @@ -756,7 +780,7 @@ - (void)drawBackground:(CGRect)frame

CGContextDrawLinearGradient(context, gradient, start, end, 0);

CGGradientRelease(gradient);
CGGradientRelease(gradient);
}

@end
Expand Down Expand Up @@ -796,7 +820,7 @@ - (id) init

- (void) dealloc
{
if (_observing) {
if (_observing) {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
}
Expand All @@ -813,20 +837,20 @@ - (void) showMenuInView:(UIView *)view
[_menuView dismissMenu:NO];
_menuView = nil;
}

if (!_observing) {

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];
[_menuView showMenuInView:view fromRect:rect menuItems:menuItems];
}

- (void) dismissMenu
Expand Down Expand Up @@ -885,4 +909,4 @@ + (void) setTitleFont: (UIFont *) titleFont
}
}

@end
@end