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

Changes when adding strings and images #22

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
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
276 changes: 150 additions & 126 deletions PopoverView/PopoverView.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,24 @@
#import "PopoverView_Configuration.h"
#import <QuartzCore/QuartzCore.h>

#pragma mark - Private Interface

@interface PopoverView()

// Returns an array of UIButtons generated from an array of NSStrings
- (NSMutableArray *)_makeButtonsWithStrings:(NSArray *)strings;

// Returns an array of UIButtons with images above the label generated from an array of NSStrings and UIImages
- (NSMutableArray *)_makeVerticalButtonsWithStrings:(NSArray *)strings andImages:(NSArray *)images;

// Returns an array of UIButtons with inline images generated from an array of NSStrings and UIImages
- (NSMutableArray *)_makeHorizontalButtonsWithStrings:(NSArray *)strings andImages:(NSArray *)images;

// generates a UIButton from a string
- (UIButton *)_makeButtonWithString:(NSString *)string;

@end

#pragma mark - Implementation

@implementation PopoverView
Expand Down Expand Up @@ -212,7 +230,7 @@ - (void)showAtPoint:(CGPoint)point inView:(UIView *)view withViewArray:(NSArray
float padding = (i == viewArray.count-1) ? 0 : kBoxPadding;

totalHeight += view.frame.size.height + padding;
if (view.frame.size.width > totalWidth) {
totalWidth = view.frame.size.width;
}
Expand All @@ -233,17 +251,10 @@ - (void)showAtPoint:(CGPoint)point inView:(UIView *)view withViewArray:(NSArray

totalHeight = 0;

//Now we actually change the frame element for each subview, and center the views horizontally.
//Now we actually change the frame element for each subview to make sure all views are the full width.
for (UIView *view in viewArray) {
if ([view autoresizingMask] == UIViewAutoresizingFlexibleWidth) {
//Now make sure all flexible views are the full width
view.frame = CGRectMake(view.frame.origin.x, view.frame.origin.y, totalWidth, view.frame.size.height);
} else {
//If the view is not flexible width, then we position it centered in the view
//without stretching it.
view.frame = CGRectMake(floorf(CGRectGetMinX(boxFrame) + totalWidth*0.5f - view.frame.size.width*0.5f), view.frame.origin.y, view.frame.size.width, view.frame.size.height);
}

view.frame = CGRectMake(view.frame.origin.x, view.frame.origin.y, totalWidth, view.frame.size.height);

//and if dividers are enabled, we record their position for the drawing methods
if (kShowDividersBetweenViews && i != viewArray.count-1) {
CGRect dividerRect = CGRectMake(view.frame.origin.x, floorf(view.frame.origin.y + view.frame.size.height + kBoxPadding*0.5f), view.frame.size.width, 0.5f);
Expand Down Expand Up @@ -296,13 +307,10 @@ - (void)showAtPoint:(CGPoint)point inView:(UIView *)view withTitle:(NSString *)t
float padding = (i == viewArray.count-1) ? 0.f : kBoxPadding;

totalHeight += view.frame.size.height + padding;

if (view.frame.size.width > totalWidth) {
totalWidth = view.frame.size.width;
}

[container addSubview:view];

totalWidth = MAX(totalWidth, view.frame.size.width);

[container addSubview:view];

i++;
}

Expand All @@ -312,17 +320,11 @@ - (void)showAtPoint:(CGPoint)point inView:(UIView *)view withTitle:(NSString *)t
}

i = 0;

for (UIView *view in viewArray) {
if ([view autoresizingMask] == UIViewAutoresizingFlexibleWidth) {
//Now make sure all flexible views are the full width
view.frame = CGRectMake(view.frame.origin.x, view.frame.origin.y, totalWidth, view.frame.size.height);
} else {
//If the view is not flexible width, then we position it centered in the view
//without stretching it.
view.frame = CGRectMake(floorf(CGRectGetMinX(boxFrame) + totalWidth*0.5f - view.frame.size.width*0.5f), view.frame.origin.y, view.frame.size.width, view.frame.size.height);
}


//Now we actually change the frame element for each subview to make sure all views are the full width.
for (UIView *view in viewArray) {
view.frame = CGRectMake(view.frame.origin.x, view.frame.origin.y, totalWidth, view.frame.size.height);

//and if dividers are enabled, we record their position for the drawing methods
if (kShowDividersBetweenViews && i != viewArray.count-1) {
CGRect dividerRect = CGRectMake(view.frame.origin.x, floorf(view.frame.origin.y + view.frame.size.height + kBoxPadding*0.5f), view.frame.size.width, 0.5f);
Expand Down Expand Up @@ -351,119 +353,141 @@ - (void)showAtPoint:(CGPoint)point inView:(UIView *)view withTitle:(NSString *)t

- (void)showAtPoint:(CGPoint)point inView:(UIView *)view withStringArray:(NSArray *)stringArray
{
NSMutableArray *labelArray = [[NSMutableArray alloc] initWithCapacity:stringArray.count];

UIFont *font = kTextFont;

for (NSString *string in stringArray) {
CGSize textSize = [string sizeWithFont:font];
UIButton *textButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, textSize.width, textSize.height)];
textButton.backgroundColor = [UIColor clearColor];
textButton.titleLabel.font = font;
textButton.titleLabel.textAlignment = kTextAlignment;
textButton.titleLabel.textColor = kTextColor;
[textButton setTitle:string forState:UIControlStateNormal];
textButton.layer.cornerRadius = 4.f;
[textButton setTitleColor:kTextColor forState:UIControlStateNormal];
[textButton setTitleColor:kTextHighlightColor forState:UIControlStateHighlighted];
[textButton addTarget:self action:@selector(didTapButton:) forControlEvents:UIControlEventTouchUpInside];

[labelArray addObject:[textButton autorelease]];
}

[self showAtPoint:point inView:view withViewArray:[labelArray autorelease]];
[self showAtPoint:point inView:view withViewArray:[self _makeButtonsWithStrings:stringArray]];
}

- (void)showAtPoint:(CGPoint)point inView:(UIView *)view withTitle:(NSString *)title withStringArray:(NSArray *)stringArray
{
NSMutableArray *labelArray = [[NSMutableArray alloc] initWithCapacity:stringArray.count];

UIFont *font = kTextFont;

for (NSString *string in stringArray) {
CGSize textSize = [string sizeWithFont:font];
UIButton *textButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, textSize.width, textSize.height)];
textButton.backgroundColor = [UIColor clearColor];
textButton.titleLabel.font = font;
textButton.titleLabel.textAlignment = kTextAlignment;
textButton.titleLabel.textColor = kTextColor;
[textButton setTitle:string forState:UIControlStateNormal];
textButton.layer.cornerRadius = 4.f;
[textButton setTitleColor:kTextColor forState:UIControlStateNormal];
[textButton setTitleColor:kTextHighlightColor forState:UIControlStateHighlighted];
[textButton addTarget:self action:@selector(didTapButton:) forControlEvents:UIControlEventTouchUpInside];

[labelArray addObject:[textButton autorelease]];
}

[self showAtPoint:point inView:view withTitle:title withViewArray:[labelArray autorelease]];
{
[self showAtPoint:point inView:view withTitle:title withViewArray:[self _makeButtonsWithStrings:stringArray]];
}

- (void)showAtPoint:(CGPoint)point inView:(UIView *)view withStringArray:(NSArray *)stringArray withImageArray:(NSArray *)imageArray
{
//Here we do something pretty similar to the stringArray method above.
//We create an array of subviews that contains the strings and images centered above a label.

NSAssert((stringArray.count == imageArray.count), @"stringArray.count should equal imageArray.count");
NSMutableArray* tempViewArray = [self makeTempViewsWithStrings:stringArray andImages:imageArray];
NSMutableArray* tempViews = [self _makeButtonsWithStrings:stringArray andImages:imageArray];

[self showAtPoint:point inView:view withViewArray:[tempViewArray autorelease]];
[self showAtPoint:point inView:view withViewArray:tempViews];
}

- (void)showAtPoint:(CGPoint)point inView:(UIView *)view withTitle:(NSString *)title withStringArray:(NSArray *)stringArray withImageArray:(NSArray *)imageArray
{
NSAssert((stringArray.count == imageArray.count), @"stringArray.count should equal imageArray.count");
NSMutableArray* tempViewArray = [self makeTempViewsWithStrings:stringArray andImages:imageArray];

[self showAtPoint:point inView:view withTitle:title withViewArray:[tempViewArray autorelease]];
NSMutableArray* tempViews = [self _makeButtonsWithStrings:stringArray andImages:imageArray];

[self showAtPoint:point inView:view withTitle:title withViewArray:tempViews];
}

- (NSMutableArray*) makeTempViewsWithStrings:(NSArray *)stringArray andImages:(NSArray *)imageArray
- (NSMutableArray *)_makeButtonsWithStrings:(NSArray *)strings
{
NSMutableArray *tempViewArray = [[NSMutableArray alloc] initWithCapacity:stringArray.count];

UIFont *font = kTextFont;

for (int i = 0; i < stringArray.count; i++) {
NSString *string = [stringArray objectAtIndex:i];

//First we build a label for the text to set in.
CGSize textSize = [string sizeWithFont:font];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, textSize.width, textSize.height)];
label.backgroundColor = [UIColor clearColor];
label.font = font;
label.textAlignment = kTextAlignment;
label.textColor = kTextColor;
label.text = string;
label.layer.cornerRadius = 4.f;

//Now we grab the image at the same index in the imageArray, and create
//a UIImageView for it.
UIImage *image = [imageArray objectAtIndex:i];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];

//Take the larger of the two widths as the width for the container
float containerWidth = MAX(imageView.frame.size.width, label.frame.size.width);
float containerHeight = label.frame.size.height + kImageTopPadding + kImageBottomPadding + imageView.frame.size.height;

//This container will hold both the image and the label
UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, containerWidth, containerHeight)];

//Now we do the frame manipulations to put the imageView on top of the label, both centered
imageView.frame = CGRectMake(floorf(containerWidth*0.5f - imageView.frame.size.width*0.5f), kImageTopPadding, imageView.frame.size.width, imageView.frame.size.height);
label.frame = CGRectMake(floorf(containerWidth*0.5f - label.frame.size.width*0.5f), imageView.frame.size.height + kImageBottomPadding + kImageTopPadding, label.frame.size.width, label.frame.size.height);

[containerView addSubview:imageView];
[containerView addSubview:label];

[label release];
[imageView release];

[tempViewArray addObject:containerView];
[containerView release];
}
NSMutableArray *buttons = [[NSMutableArray alloc] initWithCapacity:strings.count];

for (NSString *string in strings) {
[buttons addObject:[self _makeButtonWithString:string]];
}

return [buttons autorelease];
}

- (NSMutableArray *)_makeButtonsWithStrings:(NSArray *)strings andImages:(NSArray *)images
{
NSAssert((strings.count == images.count), @"strings.count should equal images.count");
if (kImageAboveLabel) {
return [self _makeVerticalButtonsWithStrings:strings andImages:images];
} else {
return [self _makeHorizontalButtonsWithStrings:strings andImages:images];
}
}

return tempViewArray;
- (NSMutableArray *)_makeVerticalButtonsWithStrings:(NSArray *)strings andImages:(NSArray *)images
{
NSMutableArray *buttons = [[NSMutableArray alloc] initWithCapacity:strings.count];

// create buttons and add images to them
for (int i = 0; i < strings.count; i++) {
UIButton *button = [self _makeButtonWithString:strings[i]];
UIImage *image = images[i];
[button setImage:image forState:UIControlStateNormal];
button.imageView.contentMode = UIViewContentModeScaleAspectFit;

//Take the larger of the two widths as the width for the button
float containerWidth = MAX(image.size.width, button.frame.size.width);
float containerHeight = button.frame.size.height + kImageTopPadding + kImageBottomPadding + kImageTitlePadding + image.size.height;
button.frame = CGRectMake(0, 0, containerWidth, containerHeight);

[button setImage:image forState:UIControlStateNormal];
button.imageView.contentMode = UIViewContentModeScaleAspectFit;

CGSize imageSize = button.imageView.frame.size;
CGSize titleSize = button.titleLabel.frame.size;

// lower the text and push it left to center it
button.titleEdgeInsets = UIEdgeInsetsMake(0.0, -imageSize.width, -(imageSize.height + kImageTitlePadding), 0.0);

// the text width might have changed (in case it was shortened before due to
// lack of space and isn't anymore now), so we get the frame size again
titleSize = button.titleLabel.frame.size;

// raise the image and push it right to center it
button.imageEdgeInsets = UIEdgeInsetsMake(-(titleSize.height + kImageTitlePadding), 0.0, 0.0, -titleSize.width);

[buttons addObject:button];
}

return [buttons autorelease];
}

- (NSMutableArray *)_makeHorizontalButtonsWithStrings:(NSArray *)strings andImages:(NSArray *)images
{
NSAssert((strings.count == images.count), @"strings.count should equal images.count");
NSMutableArray *buttons = [[NSMutableArray alloc] initWithCapacity:strings.count];
CGFloat maxImageWidth = 0.0;

// create buttons and add images to them
for (int i = 0; i < strings.count; i++) {
UIButton *button = [self _makeButtonWithString:strings[i]];

// resize the button based on the image width
UIImage *image = images[i];
button.frame = CGRectInset(button.frame, image.size.width * -0.5 - kImageTitlePadding, (kImageTopPadding + kImageBottomPadding) * -1.f);

[button setImage:image forState:UIControlStateNormal];
button.imageView.contentMode = UIViewContentModeScaleAspectFit;
[buttons addObject:button];

maxImageWidth = MAX(image.size.width, maxImageWidth);
}

// resize buttons based on maxImageWidth
for (UIButton * button in buttons) {
CGFloat insetWidth = (maxImageWidth - button.imageView.frame.size.width);
button.frame = CGRectInset(button.frame, insetWidth * -0.25, 0);
button.imageEdgeInsets = UIEdgeInsetsMake(0, insetWidth * 0.5, 0, 0);
button.titleEdgeInsets = UIEdgeInsetsMake(0, insetWidth + kImageTitlePadding, 0, 0);
}

return [buttons autorelease];
}

- (UIButton *)_makeButtonWithString:(NSString *)string
{
UIFont *font = kTextFont;

CGSize textSize = [string sizeWithFont:font];
UIButton *textButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, textSize.width, textSize.height)];
textButton.backgroundColor = [UIColor clearColor];
textButton.titleLabel.font = font;
textButton.titleLabel.textColor = kTextColor;
[textButton setTitle:string forState:UIControlStateNormal];
textButton.layer.cornerRadius = 4.f;
[textButton setTitleColor:kTextColor forState:UIControlStateNormal];
[textButton setTitleColor:kTextHighlightColor forState:UIControlStateHighlighted];
[textButton addTarget:self action:@selector(didTapButton:) forControlEvents:UIControlEventTouchUpInside];

if (kTextAlignment == UITextAlignmentLeft || kTextAlignment == NSTextAlignmentLeft) {
textButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
} else if (kTextAlignment == UITextAlignmentRight || kTextAlignment == NSTextAlignmentRight) {
textButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentRight;
}

return [textButton autorelease];
}

- (void)showAtPoint:(CGPoint)point inView:(UIView *)view withTitle:(NSString *)title withContentView:(UIView *)cView
Expand Down
7 changes: 7 additions & 0 deletions PopoverView/PopoverView_Configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@
//padding along bottom of icons/images
#define kImageBottomPadding 3.f

//padding between icons/images and titles
#define kImageTitlePadding 6.f

// POSITION OF IMAGES

//Bool that positions icons/images above or to the left of labels
#define kImageAboveLabel YES

// DIVIDERS BETWEEN VIEWS

Expand Down