I was using SBTableAlert library in my app, but with iOS 7 this library won't work.
I fix it whit adding TSAlertView and dialogs are showing fine.
But my problem is that position of button is not as it should be.
I set position of the button in :
-(void)willPresentTableAlert:(SBTableAlert *)tableAlert{
int counter = 0;
for (id view_sub in self.filterAlert.view.subviews) {
if ([view_sub isKindOfClass:[UIButton class]]) {
switch (counter) {
case 0:
((UIButton*)view_sub).frame = CGRectMake(10,
10,
144,
44);
((UIButton*)view_sub).backgroundColor = [UIColor redColor];
break;
case 1:
((UIButton*)view_sub).frame = CGRectMake(169,
150,
144,
44);
break;
case 2:
((UIButton*)view_sub).frame = CGRectMake(328,
150,
144,
44);
break;
default:
break;
}
counter++;
}
}
}
The thing is that button is painted red but frame set is ignored, instead of lining in one line, they are put one under the other and out of the Alert frame.
I finally found the answer.
The problem was in TSAlertVeiw library, because it has function recalcSizeAndLayout:layout which is called at the end and overwrite your custom position of the buttons.
The solution was to add new BOOL variable in TSAlertView customLayoutOfButton and then check it before auto layout your buttons:
if (!self.customLayoutOfButton) {
CGFloat buttonHeight = [[self.buttons objectAtIndex:0] sizeThatFits: CGSizeZero].height;
if ( stacked )
{
CGFloat buttonWidth = maxWidth;
for ( UIButton* b in self.buttons )
{
b.frame = CGRectMake( kTSAlertView_LeftMargin, y, buttonWidth, buttonHeight );
y += buttonHeight + kTSAlertView_RowMargin;
}
}
else
{
CGFloat buttonWidth = (maxWidth - kTSAlertView_ColumnMargin) / 2.0;
CGFloat x = kTSAlertView_LeftMargin;
for ( UIButton* b in self.buttons )
{
b.frame = CGRectMake( x, y, buttonWidth, buttonHeight );
x += buttonWidth + kTSAlertView_ColumnMargin;
}
}
}
Related
Currently I am displaying a list of items to choose from, the scrollview scrolls to the bottom, however, it goes 'under' the GUI/Banner, whereas I would prefer the scrollview to stop displaying beyond that point - the user should still be able to keep scrolling but the scrollview should not overlap the bottom if that makes sense?
At the moment the scrollview takes up the whole screen.
- (void)reloadScroll
{
for(UIView *view in [scroll subviews])
[view removeFromSuperview];
scroll.contentSize = CGSizeMake(scroll.frame.size.width, 1760);
for(int i = 0; i < 20; i++)
{
int xCoord = 0;
if(i % 2 == 0)
xCoord = 57;
else
xCoord = 188;
UIButton *glasss = [[UIButton alloc] initWithFrame:CGRectMake(xCoord, 20 + i/2 * 150 + i/2 * 20, 75, 150)];
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
int xCoord = 0;
if(i % 2 == 0)
xCoord = 156;
else
xCoord = 462;
glasss.frame = CGRectMake(xCoord, 20 + i/2 * 300 + i/2 * 20, 150, 300);
scroll.contentSize = CGSizeMake(scroll.frame.size.width, 3240);
}
}
I am stuck in this position from last 3 days. I am unable to find out how to solve this. I have multiple data in a array. According to data I have to create a route in my Application. I am creating the button in a for loop. but its coming one row by row. But my requirement is like, in every row it should be a opposite direction.
This is my requirement.
This purple color is my buttons, and red colors are path.
int x_pos = 40;
int y_pos = 50;
for (int i = 0; i < 5 ; i ++)
{
UIButton *courseBtn = [UIButton buttonWithType:UIButtonTypeCustom];
courseBtn.frame = CGRectMake(x_pos, y_pos, 40, 40);
courseBtn.backgroundColor = [UIColor purpleColor];
[self.courseMapScroll addSubview:courseBtn];
courseBtn.layer.cornerRadius = courseBtn.frame.size.height/2;
courseBtn.layer.masksToBounds = YES;
NSLog(#"x_pos == %d",x_pos);
x_pos = x_pos + (SCREEN_WIDTH - 120);
if (x_pos > 320)
{
x_pos = 40;
y_pos = y_pos + 100;
}
[self.courseMapScroll setContentSize:CGSizeMake(SCREEN_WIDTH, y_pos + 70)];
}
My code is like this
Please anybody can help me. Please
Thanks alots
Here it is, exactly how you asked for it (with the green line that you requested in chat). Have fun tweaking the values :)
int numButtons = 6;
int yInterval = 100;
int leftX = 50;
int rightX = self.view.frame.size.width - leftX*2;
int lineWidth = 6;
int buttonRadius = 40;
int topMargin = 60;
for (float i = 1; i < numButtons+1 ; i++) {
float yPos = (ceil(i/2)-1)*yInterval+topMargin;
BOOL isRightDirection = (fmod(ceil(i/2),2) == 1);
BOOL isEven = (fmod(i,2) == 0);
BOOL isOnLeft = (isRightDirection != isEven);
float xPos = (isOnLeft) ? leftX : rightX;
if (i != numButtons) {
double nextUnlockedDecimal = (double)nextPercentUnlocked/100;
UIView *redLine = [[UIView alloc] initWithFrame:CGRectZero];
redLine.backgroundColor = [UIColor redColor];
UIView *greenLine = [[UIView alloc] initWithFrame:CGRectZero];
greenLine.backgroundColor = [UIColor greenColor];
if (isEven) {
//Vertical
int xToUse = (isRightDirection) ? rightX : leftX;
redLine.frame = CGRectMake(xToUse + buttonRadius/2 - lineWidth/2, yPos + buttonRadius/2, lineWidth, yInterval);
if (i == latestUnlocked) {
greenLine.frame = CGRectMake(xToUse + buttonRadius/2 - lineWidth/2, yPos + buttonRadius/2, lineWidth, nextUnlockedDecimal * yInterval);
} else if (i < latestUnlocked) {
greenLine.frame = redLine.frame;
}
} else {
//Horizontal
redLine.frame = CGRectMake(leftX + buttonRadius/2, yPos + buttonRadius/2 - lineWidth/2, rightX-leftX, lineWidth);
if (i == latestUnlocked) {
double greenLineX = (isRightDirection) ? leftX + buttonRadius/2 : rightX + buttonRadius/2 - nextUnlockedDecimal * (rightX-leftX);
greenLine.frame = CGRectMake(greenLineX, yPos + buttonRadius/2 - lineWidth/2, nextUnlockedDecimal * (rightX-leftX), lineWidth);
} else if (i < latestUnlocked) {
greenLine.frame = redLine.frame;
}
}
greenLine.layer.cornerRadius = 2.5;
[self.view addSubview:redLine];
[self.view addSubview:greenLine];
}
UIButton *courseBtn = [UIButton buttonWithType:UIButtonTypeCustom];
courseBtn.backgroundColor = [UIColor purpleColor];
courseBtn.layer.cornerRadius = buttonRadius/2;
courseBtn.layer.masksToBounds = YES;
courseBtn.frame = CGRectMake(xPos, yPos, 40, 40);
NSString *numStr = [NSString stringWithFormat:#"%i",(int)i];
[courseBtn setTitle:numStr forState:UIControlStateNormal];
[self.courseMapScroll setContentSize:CGSizeMake(SCREEN_WIDTH, yPos + 70)];
[self.courseMapScroll addSubview:courseBtn];
}
I don't know why I really did that... This should work, I haven't tested it though... I would recommend you to use a global mutable array (courseButtons) to store the buttons so you can check on the target their index against the array and know which one was clicked.
CGFloat buttonHorizontalMargin=40;
CGFloat buttonVerticalMargin=50;
CGFloat buttonSize=40;
CGFloat x_pos = buttonHorizontalMargin;
CGFloat y_pos = buttonVerticalMargin;
[self.courseMapScroll setContentSize:CGSizeMake(self.courseMapScroll.bounds.size.width, y_pos + buttonSize+buttonVerticalMargin*0.5)];
for (NSInteger i = 0; i < [_buttonPoints count] ; i ++)
{
UIButton *courseBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[courseBtn setTitle:[NSString stringWithFormat:#"%ld",(long)i] forState:UIControlStateNormal];
[courseBtn setTranslatesAutoresizingMaskIntoConstraints:YES];
[courseBtn setAutoresizesSubviews:(((i+1)%2==0&&(i+1)%4!=0)||(i+1)%3==0)?UIViewAutoresizingFlexibleLeftMargin:UIViewAutoresizingRightMargin];
[courseBtn addTarget:self action:#selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];
courseBtn.frame = CGRectMake(x_pos, y_pos, buttonSize, buttonSize);
courseBtn.backgroundColor = [UIColor purpleColor];
[self.courseButtons addObject:courseBtn];
[self.courseMapScroll addSubview:courseBtn];
courseBtn.layer.cornerRadius = courseBtn.frame.size.height*0.5;
courseBtn.layer.masksToBounds = YES;
NSLog(#"x_pos == %d",x_pos);
if((i+1)%4){
x_pos = buttonHorizontalMargin;
}else if((i+1)%3||(i+1)%2){
x_pos = self.courseMapScroll.bounds.size.width-buttonHorizontalMargin-buttonSize;
}else{
x_pos = buttonHorizontalMargin;
}
if (i>0 && i%2==0){
y_pos = y_pos + buttonSize+buttonVerticalMargin;
[self.courseMapScroll setContentSize:CGSizeMake(self.courseMapScroll.bounds.size.width, y_pos + buttonSize+buttonVerticalMargin*0.5)];
}
}
I know there is alot of documentation on this topic, and from what i've read i've learned a lot. My issue here is that i began creating a custom UIView within a viewcontroller & now when i'm trying to make it the UIView its own class, so as to be called & used within a working app, i'm pretty confused as to what i need to do to achieve it.
The overall aim of the class is to be able to select a button one a view controller, which will instantiate the custom view, then display. The visual effect for the user is that they click the button, then a window will animate-appear from the bounds of the button (although the code below uses the positioning of top left currently), then display a combination of switches & labels, along with a back & save button.
You can see from my code that what i need to achieve this process, i've managed to implement into a single function (again, this was from creating it within a viewcontroller). What i'm after now, and can't quite fathom out is for the custom view to be imported, then on the action of the main view controller's button, add the view to self.view.
- (void)makeBox{
//view bounds
CGFloat viewWidth = CGRectGetWidth(self.view.frame);
CGFloat viewHeight = CGRectGetHeight(self.view.frame);
//red box x, y & size
CGFloat startx = (viewWidth / 100) * 10;
CGFloat starty = (viewHeight /100) * 20;
CGFloat width = (viewWidth / 100) * 80;
CGFloat height = (viewHeight /100) * 70;
CGRect view1Frame = CGRectMake(startx, starty, width, height);
//label & switch frame
CGRect labelMR = CGRectMake(10, ((height / 100) * 12), ((width / 100) * 80) - 7.5, 25);
CGRect switchMR = CGRectMake(((width / 100) * 80) + 7.5, ((height / 100) * 11), ((width / 100) * 10), 15);
//this is repeated for 6 other labels & switches
CGRect backButtonR = CGRectMake(5, 5, 50, 35);
CGRect saveButtonR = CGRectMake((width - 50), 5, 50, 35);
if (!self.view1) {
self.switchM = [[UISwitch alloc] initWithFrame:switchMR];
self.switchM.tag = 10;
if(self.monday){ //self.monday refers to a BOOL property of the viewcontroller that this was originally made in
self.switchM.on = true;
} else{
self.switchM.on = false;
}
[self.switchM addTarget:self action:#selector(switched:) forControlEvents:UIControlEventTouchUpInside];
// this switch instantiation process is repeated 6 other times
self.backButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[self.backButton addTarget:self
action:#selector(hideBox)
forControlEvents:UIControlEventTouchUpInside];
[self.backButton setTitle:#"Back" forState:UIControlStateNormal];
self.backButton.frame = backButtonR;
self.saveButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[self.saveButton addTarget:self
action:#selector(daysChanged)
forControlEvents:UIControlEventTouchUpInside];
[self.saveButton setTitle:#"Save" forState:UIControlStateNormal];
self.saveButton.frame = saveButtonR;
self.labelM = [[UILabel alloc] initWithFrame:labelMR];
self.labelM.layer.masksToBounds = YES;
self.labelM.layer.cornerRadius = 5;
self.labelM.layer.borderColor = [UIColor blackColor].CGColor;
self.labelM.layer.borderWidth = .5;
self.labelM.text = #" Monday";
self.labelM.backgroundColor = [UIColor whiteColor];
//again - repeated 6 times
//use this starting frame to make the 'popover' appear small at first
CGRect startFrame = CGRectMake(10, 10, 10, 10);
self.view1 = [[UIView alloc] initWithFrame:startFrame];
[self.view addSubview:self.view1];
[UIView animateWithDuration:0.5 animations:^(void){
self.view1.layer.cornerRadius = 10;
self.view1.layer.borderColor = [UIColor blackColor].CGColor;
self.view1.layer.borderWidth = .5;
[self.view1 setBackgroundColor:[UIColor lightGrayColor]];
self.view1.frame = view1Frame;
} completion:^(BOOL finished){
[self.view1 addSubview:self.labelM];
[self.view1 addSubview:self.switchM];
//repeat 6 times for other labels & switches
}];
}
else {
[UIView animateWithDuration:0.3 animations:^() {
self.view1.frame = view1Frame;
} completion:^(BOOL finished) {
self.labelM.frame = labelMR;
self.switchM.frame = switchMR;
//repeated for the other 6
self.backButton.frame = backButtonR;
self.saveButton.frame = saveButtonR;
}];
}
}
-(void) hideBox{
//back button was selected
[UIView animateWithDuration:0.5 animations:^(void){
[self.view1 removeFromSuperview];
self.view1 = nil;
}];
}
I understand that as i'm doing/calling this via code, i need to override either init or initWithFrame:. Do i pass the initWithFrame: the containing view controllers bounds, of which the custom view can be calculated on, and how do i handle the animation?
I've managed to set up the delegate protocol which will notify when the save button is pressed. that part i understand, its just the rest of the parts i'm unclear on.
First some background.
Typically for a popover controller, you have a single transparent root view which contains the popover view itself. This root view is the size of the containing window and usually higher in z-order than all other views. There are two reasons for this:
1) The popover needs to draw on top of all other views. If the root view wasn't on top of all other views, the popover could be clipped and not draw all of its contents.
2) The user usually needs some place to tap and dismiss the popover (effectively a cancel action).
UIPopoverController does this as do some 3rd party popovers. Some even go so far as to use their own UIWindows.
To answer your specific questions:
1) initWithFrame: / setFrame: should be passed a CGRect that is in the coordinate space of the view that will contain the view. In other words, the superview. If you decide to use a transparent root view, the popover (the part that draw on screen) will be passed a CGRect in the coordinate space of the transparent root view.
2) Usually a popover is animated like so:
// set initial frame
popover.frame = CGRectMake(x, y, width, 0);
popover.alpha = 0.0;
[rootView addSubview:popover];
[UIView animateWithDuration:0.5
animations:^{
CGRect frame = popover.frame;
frame.size.height = some-height;
popover.frame = frame;
popover.alpha = 1;
}
];
I actually got it to work! (although i can't promise this is the cleanest or most resourceful way - we'll work on that).
Here's what i did:
Split the makeBox function into 3 function, initWithWidth:andHeight:forView, openBox & updateBoxWithWidth:andHeight.
I used a saveButton delegate method that informs the parent that save button has been pressed.
.h
#protocol BoxDelegate
-(void) daysChanged;
#end
__weak id <BoxDelegate> delegate;
#interface aBox : UIView
#property (nonatomic) BOOL monday;
#property (nonatomic, weak) id <BoxDelegate> delegate;
//property values for the custom view
-(id) initWithWidth: (CGFloat) width andHeight: (CGFloat) height withView: (UIView*) theView;
-(void) updateViewWithWidth: (CGFloat) width andHeight: (CGFloat) height;
-(void) openBox;
#end
.m
#synthesize delegate;
-(id) initWithWidth:(CGFloat)inWidth andHeight:(CGFloat)inHeight withView: (UIView*) theView{
self = [super init];
self.mainView = theView;
//super view bounds
self.viewWidth = inWidth;
self.viewHeight = inHeight;
//red box x, y & size
CGFloat startx = (self.viewWidth / 100) * 10;
CGFloat starty = (self.viewHeight /100) * 20;
self.width = (self.viewWidth / 100) * 80;
self.height = (self.viewHeight /100) * 70;
self.view1Frame = CGRectMake(startx, starty, self.width, self.height);
//label & switch frame
self.labelMR = CGRectMake(10, ((self.height / 100) * 12), ((self.width / 100) * 80) - 7.5, 25);
self.switchMR = CGRectMake(((self.width / 100) * 80) + 7.5, ((self.height / 100) * 11), ((self.width / 100) * 10), 15);
//repeated for the other 6
self.backButtonR = CGRectMake(5, 5, 50, 35);
self.saveButtonR = CGRectMake((self.width - 50), 5, 50, 35);
self.switchM = [[UISwitch alloc] initWithFrame:self.switchMR];
self.switchM.tag = 10;
if(self.monday){
self.switchM.on = true;
} else{
self.switchM.on = false;
}
[self.switchM addTarget:self action:#selector(switched:) forControlEvents:UIControlEventTouchUpInside];
self.labelM = [[UILabel alloc] initWithFrame:self.labelMR];
self.labelM.layer.masksToBounds = YES;
self.labelM.layer.cornerRadius = 5;
self.labelM.layer.borderColor = [UIColor blackColor].CGColor;
self.labelM.layer.borderWidth = .5;
self.labelM.text = #" Monday";
self.labelM.backgroundColor = [UIColor whiteColor];
//repeated for the other 6
self.saveButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[self.saveButton addTarget:delegate
action:#selector(daysChanged)
forControlEvents:UIControlEventTouchUpInside];
[self.saveButton setTitle:#"Save" forState:UIControlStateNormal];
self.saveButton.frame = self.saveButtonR;
return self;
}
-(void) openBox{
CGRect startFrame = CGRectMake(10, 10, 10, 10);
self.view1 = [[UIView alloc] initWithFrame:startFrame];
[self.mainView addSubview:self.view1];
[UIView animateWithDuration:0.5 animations:^(void){
self.view1.layer.cornerRadius = 10;
self.view1.layer.borderColor = [UIColor blackColor].CGColor;
self.view1.layer.borderWidth = .5;
[self.view1 setBackgroundColor:[UIColor lightGrayColor]];
// repeated for the other 6
self.view1.frame = self.view1Frame;
} completion:^(BOOL finished){
[self.view1 addSubview:self.labelM];
[self.view1 addSubview:self.switchM];
[self.view1 addSubview:self.backButton];
[self.view1 addSubview:self.saveButton];
}];
}
-(void) updateViewWithWidth: (CGFloat) width andHeight:(CGFloat) height{
//re-calculate
self.viewWidth = width;
self.viewHeight = height;
CGFloat startx = (self.viewWidth / 100) * 10;
CGFloat starty = (self.viewHeight /100) * 20;
self.width = (self.viewWidth / 100) * 80;
self.height = (self.viewHeight /100) * 70;
self.view1Frame = CGRectMake(startx, starty, self.width, self.height);
//label & switch frame
self.labelMR = CGRectMake(10, ((self.height / 100) * 12), ((self.width / 100) * 80) - 7.5, 25);
self.switchMR = CGRectMake(((self.width / 100) * 80) + 7.5, ((self.height / 100) * 11), ((self.width / 100) * 10), 15);
self.backButtonR = CGRectMake(5, 5, 50, 35);
self.saveButtonR = CGRectMake((self.width - 50), 5, 50, 35);
[UIView animateWithDuration:0.3 animations:^() {
self.view1.frame = self.view1Frame;
} completion:^(BOOL finished) {
self.labelM.frame = self.labelMR;
self.switchM.frame = self.switchMR;
self.backButton.frame = self.backButtonR;
self.saveButton.frame = self.saveButtonR;
}];
}
And then in our parent viewcontroller
#property aBox *theBox;
...
- (void)viewDidLoad {
[super viewDidLoad];
self.theBox = [[aBox alloc] initWithWidth:self.view.frame.size.width andHeight:self.view.frame.size.height withView:self.view];
[self.theBox openBox];
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation{
[self.theBox updateViewWithWidth:self.view.frame.size.width andHeight:self.view.frame.size.height];
}
- (void) daysChanged{
NSLog(#"Days Changed!");
}
I want to create 15 UIButtons progaramatically using for loop. I want to arrange buttons like matrix with rows and colums, say 3 rows and 5 columns. The buttons height is 50 and width is 80. I can set y,width,height coordinates. But I face problem only with x coordinate. Tell me the logic for setting x coordinate.
Thanks in advance.
float x = 10;
float y = 10;
float width = 50;
float height = 50;
for(int i =0;i<15;i++)
{
UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btn setFrame:CGRectMake(x, y, width, height)];
[btn setTitle:[NSString stringWithFormat:#"B%d",i+1] forState:UIControlStateNormal];
[self.view addSubview:btn];
x = x + width + 20;
if((i+1)%3==0)
{
x = 10;
y = y + height + 20;
}
}
Just replace x and y and also set height and width in above code.
int row = 0;
int column = 0;
for (int i = 0; i < 15; i++)
{
if((row%3 == 0) && (row > 0))
{
row = 0;
column++;
}
else{
row++;
}
CGRect btnFrame = CGRectMake(row*80+10, column*50+10, 80, 50);//your button frame
UIButton *btnTemp = [UIButton buttonWithType:UIButtonTypeCustom];
[btnTemp setFrame:btnFrame];
[self.view addSubView:btnTemp];
}
Here you go:
CGFloat marginX = 10.f;
CGFloat marginY = 5.f;
CGRect buttonFrame = CGRectMake(0., 0., 80., 50.f);
for(NSUInteger row = 0; row < 5; row++) {
for(NSUInteger column = 0; column < 3; column++) {
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = buttonFrame;
//... more button settings
[self.view addSubview:button];
buttonFrame.origin.x += marginX;
}
buttonFrame.origin.x = 0.;
buttonFrame.origin.y += marginY;
}
I have rewards that a user can get in my game. Now they only show if they unlock them. There are 4 different rewards they can get. Now they may have 1 reward unlocked or 2 or 3 or 4. However I want the images to be positioned dynamically so it looks like the image below. In the image below, each line should look the way it is with the number of rewards unlocked.
Now, how would I go upon doing this? (Note: The images are not changing on the Y axis, they will just be dynamically positioned on the X axis, so don't be fooled by the image)
Thanks!
I would create a custom UIView subclass that does this so that you can use it anywhere that a view can be used.
Usage:
MyFlexibleSpacedButtons *myButtons = [[MyFlexibleSpacedButtons alloc] initWithFrame:CGRectMake(50, 50, 250, 60)];
[myButtons setButtonAtIndex:2 hidden:NO];
[myButtons setButtonAtIndex:0 hidden:NO];
[self.view addSubview:myButtons];
Here is the example class:
MyFlexibleSpacedButtons.h:
#import <UIKit/UIKit.h>
#interface MyFlexibleSpacedButtons : UIView
#property (nonatomic, readonly) NSArray *allButtons;
- (void)setButtonAtIndex:(NSUInteger)index hidden:(BOOL)hidden;
#end
MyFlexibleSpacedButtons.m:
#import "MyFlexibleSpacedButtons.h"
const NSUInteger maxButtons = 9;
const NSUInteger buttonsPerRow = 3; // This can not be 0.
const CGFloat buttonHeight = 50;
const CGFloat buttonWidth = 50;
const CGFloat spaceBetweenButtons = 10.0;
#interface MyFlexibleSpacedButtons ()
#property (nonatomic, readwrite) NSArray *allButtons;
#end
#implementation MyFlexibleSpacedButtons
#synthesize allButtons;
- (id)initWithFrame:(CGRect)frame
{
NSUInteger numberOfRows = ceil((double)maxButtons / (double)buttonsPerRow);
CGFloat minHeight = buttonHeight * numberOfRows + spaceBetweenButtons * (numberOfRows - 1);
if (frame.size.height < minHeight)
{
frame.size.height = minHeight;
}
CGFloat minWidth = buttonWidth * maxButtons + spaceBetweenButtons * (maxButtons-1);
if (frame.size.width < minWidth)
{
frame.size.width = minWidth;
}
self = [super initWithFrame:frame];
if (self) {
// Defaults
// Uncomment the following line if needed for debugging:
// self.backgroundColor = [UIColor grayColor];
// Create the buttons and add them to the array. Default to hidden buttons
self.allButtons = [NSArray new];
for (int i = 0; i < maxButtons; i++)
{
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.hidden = YES;
[button setTitle:[NSString stringWithFormat:#"%d", i] forState:UIControlStateNormal];
[self addSubview:button];
self.allButtons = [self.allButtons arrayByAddingObject:button];
}
[self setButtonFrames];
}
return self;
}
- (void)dealloc
{
allButtons = nil;
}
- (void)setButtonFrames
{
CGFloat viewHeight = self.bounds.size.height;
CGFloat viewWidth = self.bounds.size.width;
NSUInteger buttonCount = [self visibleButtonsCount];
NSUInteger numberOfRows = ceil((double)maxButtons / (double)buttonsPerRow);
CGFloat buttonY = (viewHeight - buttonHeight * numberOfRows - spaceBetweenButtons * (numberOfRows - 1)) / 2;
CGFloat buttonGroupTotalWidth = buttonCount * buttonWidth + (buttonCount - 1) * spaceBetweenButtons;
CGFloat buttonGroupStartingX = (viewWidth - buttonGroupTotalWidth) / 2;
// Set frames of buttons
NSUInteger visibleButtonIndex = 0;
for (int i = 0; i < maxButtons; i++)
{
UIButton *button = [self.allButtons objectAtIndex:i];
if (!button.hidden)
{
CGFloat buttonX = buttonGroupStartingX + visibleButtonIndex % buttonsPerRow * (buttonWidth + spaceBetweenButtons);
button.frame = CGRectMake(buttonX, buttonY, buttonWidth, buttonHeight);
visibleButtonIndex++;
if (visibleButtonIndex % buttonsPerRow == 0)
{
buttonY = buttonY + buttonHeight + spaceBetweenButtons;
}
}
}
}
- (void)setButtonAtIndex:(NSUInteger)index hidden:(BOOL)hidden
{
if (index > maxButtons - 1)
{
return;
}
UIButton *button = [self.allButtons objectAtIndex:index];
button.hidden = hidden;
[self setButtonFrames];
}
- (NSUInteger)visibleButtonsCount
{
NSUInteger buttonCount = 0;
for (UIButton *button in self.allButtons)
{
if (!button.hidden)
{
buttonCount++;
}
}
return buttonCount;
}
#end
I think the easiest and more flexible way would be to use an UITableView and a custom cell with a method: - (void)NumberOfButtonsInCell:(NSUInteger)buttons;
so when called in the tableView data source
you just set the number of buttons accordingly as
- (void)numberOfButtonsInCell:(NSUInteger)buttons {
int i;
for (i = 0; i<buttons;i++) {
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake((cell.frame.size.widht/buttons)*i, 0, buttonWidth, buttonHeight)];
button.tag = i;
[self addSubview:button];
[button addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
}
}
- (void)buttonPressed:(id)sender {
UIButton *button = (UIButton*)sender;
[self.delegate userDidSelectButtonAtIndex:(button.tag)];
//so your table view resolves the row with [self.tableView indexPathForCell:cell];
}
That way you can set a method, for [cell configureButtonAtIndex:index];
You could easily change all the behavior, the looks, and even the design, with a few lines of code.