Draw grid of circles - ios

What would be the best way on iOS to achieve drawing a grid of circles with fixed columns and rows ?. I would want to identify each circle when the user taps on it.
I tried using collection views but it seems CoreGraphics is meant for tasks like these.

You can create buttons dynamically as follows :
- (void)drawSheet
{
int numberOfRow=5;
int numberOfColumn=4;
float x = 1,
y = 20,
padding = 5,
width = (self.view.frame.size.width-(padding*(numberOfColumn-1)))/numberOfColumn,
height = (self.view.frame.size.height-(padding*(numberOfRow-1)))/numberOfRow;
int counter = 0;
for (int i=0; i<numberOfRow; i++) {
for (int j=0; j<numberOfColumn; j++) {
UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake(x, y, 74, 74)];
btn.layer.cornerRadius = btn.frame.size.width/2;
btn.layer.borderColor = [UIColor grayColor].CGColor;
btn.layer.borderWidth = 2.0;
[btn addTarget:self action:#selector(buttonPress:) forControlEvents:UIControlEventTouchUpInside];
btn.clipsToBounds = YES;
btn.tag = counter;
[self.view addSubview:btn];
x = x + width + padding;
counter = counter + 1;
}
x = 0;
y = y + height + padding;
}
}
When you tap on it, you will get tag of it :
- (IBAction)buttonPress:(UIButton *)sender{
NSLog(#"%ld",sender.tag);
}

hi Please check the below code. i have added 3 circles in a row, you could use more if you want.
- (void)viewDidLoad {
[super viewDidLoad];
UIView *circleView;
int x = 10;
int y = 20;
static int tagNum = 0;
for (int row=0; row < 5;) {
for (int cirNum =0 ; cirNum <3;) {
circleView = [[UIView alloc] initWithFrame:CGRectMake(x,y,100,100)];
circleView.alpha = 0.5;
circleView.layer.cornerRadius = 50;
circleView.backgroundColor = [UIColor blueColor];
circleView.tag = tagNum;
NSLog(#"tagNum is %d", tagNum);
[self.view addSubview:circleView];
cirNum ++;
x = x + 100;
tagNum ++;
//y = y + 20;
}
row++;
y = y + 100;
x = 10;
}
// Do any additional setup after loading the view, typically from a nib.
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
CGPoint location = [[touches anyObject] locationInView:self.view];
CGRect fingerRect = CGRectMake(location.x-5, location.y-5, 10, 10);
for(UIView *view in self.view.subviews){
CGRect subviewFrame = view.frame;
if(CGRectIntersectsRect(fingerRect, subviewFrame)){
//we found the finally touched view
//NSLog(#"Yeah !, i found it %#",view);
NSLog(#"view tag touched is %ld",view.tag);
}
}
}
output would look like this

Related

How to create buttons around circle with some radius

i try to create programmatically a number of buttons. I what that buttons will created around the circle like on image 1. Now i have some results, i can rotate buttons, but don't know how to set offset between them. Now i have this result: image 2 Here is my code. And thanks for any help!
viewDidload in ViewController
CGPoint point = self.view.center;
NSArray *arrayWithImages = #[#"red", #"pink", #"green", #"blue", #"purple", #"orange", #"yellow"];
NSArray *arrayWithAngle = #[#(0), #(M_PI / 3.8f), #(M_PI / 1.8), #(M_PI / -6), #(M_PI / 6), #(M_PI / -1.8), #(M_PI / -3.8)];
NSMutableArray *arrayWithPlacePoint = [self generatePointForRound:point andAngle:arrayWithAngle andRadius:25.0f];
NSLog(#"array with place point = %#", arrayWithPlacePoint);
for (NSInteger i = 0; i < [arrayWithImages count]; i++) {
PetalObject *petal = [[PetalObject alloc] initWithImageName:arrayWithImages andRotation:arrayWithAngle andIndex:i andPointsArray:arrayWithPlacePoint andCentrPoint:point];
[self.view addSubview:petal.petalButton];
}
I try to generate some x,y point which should be a creation point of each new button
- (NSMutableArray *)generatePointForRound:(CGPoint )centrPoint andAngle:(NSArray *)arrayAngle andRadius:(float)radiusValue {
CGPoint currentPoint;
NSMutableArray *array = [[NSMutableArray alloc] init];
for (int i = 0; i < [arrayAngle count]; i++) {
CGFloat x1 = centrPoint.x + (radiusValue * sin([[arrayAngle objectAtIndex:i] doubleValue]));
CGFloat y1 = centrPoint.y + (radiusValue * cos([[arrayAngle objectAtIndex:i] doubleValue]));
currentPoint = CGPointMake(x1, y1);
[array addObject:[NSValue valueWithCGPoint:currentPoint]];
}
return array;
}
And here is my PetalObject in which i create my buttons
-(id)initWithImageName:(NSArray *)imageNameArray andRotation:(NSArray *)angleArray andIndex:(NSInteger )index andPointsArray:(NSMutableArray *)pointsArray andCentrPoint:(CGPoint )centerPoint {
self.isRecorded = NO;
self.isComplited = NO;
UIImage *image = [UIImage imageNamed:imageNameArray[index]];
CGPoint point = [[pointsArray objectAtIndex:index] CGPointValue];
self.petalButton = [[UIButton alloc] initWithFrame:CGRectMake(point.x - 43 , point.y - 180, 86, 168)];
//self.petalButton.transform = CGAffineTransformMake(cos(angle),sin(angle),-sin(angle),cos(angle),boundsPoint.x-boundsPoint.x*cos(angle)+boundsPoint.y*sin(angle),boundsPoint.y-boundsPoint.x*sin(angle)-boundsPoint.y*cos(angle));
[self.petalButton setBackgroundImage:image forState:UIControlStateNormal];
CGFloat angle = [[angleArray objectAtIndex:index] floatValue];
[self.petalButton setTransform:CGAffineTransformMakeRotation(angle)];
return self;
}
Image 1:
Image 2:
Screenshot
And code:
- (void)viewDidLoad {
[super viewDidLoad];
for (NSInteger index = 0; index < 6; index ++) {
UIButton * button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 50, 20)];
button.layer.anchorPoint = CGPointMake(-0.5, 0.5);
button.backgroundColor = [UIColor greenColor];
button.center = CGPointMake(self.view.center.x + CGRectGetWidth(button.frame) / 2.0, self.view.center.y);
button.transform = CGAffineTransformMakeRotation(M_PI * 2 * index / 6.0);
[self.view addSubview:button];
}
}
The key point is anchorPoint, you set all the button with same anchorPoint and frame, then apply different transform.

Certain placement of UIButtons created in for loop

I want to create UIButtons and have them separated inside a UIScrollView with pages such as:
The buttons will go from left to right then down in rows until it gets to bottom of view. It will then go to next page of the UIScrollView and continue on.
Here's my code so far:
for(NSString *num in nums) {
UIButton *test = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[test addTarget:self action:#selector(numPressed:) forControlEvents:UIControlEventTouchUpInside];
test.frame = CGRectMake(0, 0, 70, 70);
[self.view addSubview:test];
}
Some code like this:
int xOff = 10;
int yOff = 50;
int btnGap = 20;
int page = 0;
for (NSString *num in nums) {
xOff += page * _scrollView.width;
for (int row = 0; row < 3; row++) {
for (int col = 0; col < 3; col++) {
UIButton *test = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[test addTarget:self action:#selector(numPressed:) forControlEvents:UIControlEventTouchUpInside];
test.frame = CGRectMake(xOff+col*(70+btnGap) , yOff+row*(70+btnGap), 70, 70);
test.backgroundColor = [UIColor redColor];
[test setTitle:num forState:UIControlStateNormal];
[_scrollView addSubview:test];
}
}
page++;
}
You need to change the coordinates when invokint CGRectMake:
NSInteger i, x, y;
for(NSString *num in nums) {
...
i = i%3;
if (i==0)
{
x = 0;
y += 70;
}
x += 80;
test.frame = CGRectMake(x, y, 70, 70);
...
}
This should give you an idea on how to proceed. Also, don't forget to place the title to each button.
If you're creating and setting UIButton objects by frame then I, personally, would do it this way (surely it can be improved / optimized)
Note: This does not incorporate any page logic so you'll need to adapt it yourself.
-(void)createButtonGrid
{
int i_btnWidth = 70;
int i_btnHeight = 70;
int i_btnX = 0;
int i_btnY = -70; //offset (for first iteration in for loop) [1]
int i_btnPadding = 20;
//number of columns
int i_screenDivisions = 3;
//width of every column
int i_screenDivisionWidth = self.view.frame.size.width / i_screenDivisions;
int i_count = 40; //or, maybe, nums.count as per your logic
for (int i = 0; i < i_count; i++) {
//which column a button goes in
int i_index = (i+i_screenDivisions)%i_screenDivisions;
//increase Y position when new row begins
if (i_index == 0) { //[1]
i_btnY += i_btnHeight + i_btnPadding;
}
//calculate X position (which will be placed at the centre of every column)
i_btnX = (i_index*i_screenDivisionWidth) + (i_screenDivisionWidth/2) - (i_btnWidth/2);
//----Button creation logic----
UIButton *btnTemp = [UIButton buttonWithType:UIButtonTypeCustom];
[btnTemp setFrame:CGRectMake(i_btnX, i_btnY, i_btnWidth, i_btnHeight)];
NSString *strTitle = [NSString stringWithFormat:#"%d",i];
//or, maybe, as per your logic
//NSString *strTitle = nums[i];
[btnTemp setTitle:strTitle forState:UIControlStateNormal];
[btnTemp.titleLabel setTextColor:[UIColor yellowColor]];
//[btnTemp addTarget:self action:nil forControlEvents:UIControlEventTouchUpInside];
[btnTemp setTag:i]; //might need it later
[btnTemp setBackgroundColor:[UIColor colorWithRed:(float)(arc4random()%255)/255
green:(float)(arc4random()%255)/255
blue:(float)(arc4random()%255)/255
alpha:1.0f]];
[scrollView addSubview:btnTemp];
}
[scrollView setContentSize:CGSizeMake(self.view.frame.size.width, i_btnY + i_btnHeight)];
}

Custom UIPageControl dots are misplaced on load

I have a weird behavior with custom UIPageControl.
I subclassed it and in setCurrentPage method I draw custom dots.
In iOS 6 on load they just miss.
In iOS 7 the dots are misplaced.
In both iOS's dots are being positioned correctly only after I change the slide.
I tried the following methods without success:
[customPageControl updateCurrentPageDisplay];
[customPageControl updateConstraints];
[customPageControl sizeToFit];
[customPageControl.currentPage = 1];
The code:
#implementation ProfilePagesPageControl
#synthesize originalSubviews;
#synthesize dotsHeight;
- (void)setCurrentPage:(NSInteger)page
{
[super setCurrentPage:page];
[self updateDots];
}
- (void)updateDots
{
for (int i = 0; i < self.subviews.count; i++)
{
UIView* dotView = [self.subviews objectAtIndex:i];
for (int j = dotView.subviews.count - 1; j >= 0; j--)
{
UIView *view = [dotView.subviews objectAtIndex:j];
[view removeFromSuperview];
}
int widthForDots = [Utils getDeviceBounds].width - Constraints.Gap * 3;
int effectiveWidth = widthForDots / self.subviews.count - Constraints.Gap;
int effectiveGap = (widthForDots - (effectiveWidth * self.subviews.count) + Constraints.Gap * 3) / self.subviews.count;
int effectiveHeight = dotsHeight;
if (i == self.currentPage)
effectiveHeight = effectiveHeight + 3;
else
effectiveHeight = effectiveHeight - 3;
CGRect dotViewFrame = dotView.frame;
dotViewFrame.origin.x = effectiveWidth * i + Constraints.Gap + effectiveGap * i;
dotViewFrame.origin.y = self.frame.size.height / 2 - effectiveHeight / 2;
dotViewFrame.size.width = effectiveWidth;
dotViewFrame.size.height = effectiveHeight;
dotView.frame = dotViewFrame;
UIView *dotSubView = [[UIView alloc] initWithFrame:CGRectMake(0,
0,
dotView.frame.size.width,
dotView.frame.size.height)];
if (i == self.currentPage)
dotSubView.backgroundColor = [UIColor blackColor];
else
dotSubView.backgroundColor = [UIColor grayColor];
[UIUtils roundCorner:(UIRectCornerTopLeft | UIRectCornerTopRight | UIRectCornerBottomLeft | UIRectCornerBottomRight) forView:dotSubView];
ProfileSlideView *slideView = [self.originalSubviews objectAtIndex:i];
RevUILabel *label = [[RevUILabel alloc] initWithSize:13];
label.text = slideView.name;
label.frame = CGRectMake(dotSubView.frame.size.width / 2 - label.frame.size.width / 2,
dotSubView.frame.size.height / 2 - label.frame.size.height / 2,
label.frame.size.width,
label.frame.size.height);
[dotSubView addSubview:label];
[dotView addSubview:dotSubView];
}
}
#end
The iOS7 look:
The iOS6 look:
:
After slide look:
Make sure you call updateDots somewhere else (such as viewDidLoad, or viewWillAppear) so they can be set up before you switch any pages. If you only call updateDots in setCurrentPage it will only be called once you switch the page the first time.

How to add UIButtons programatically using for loop in iOS?

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;
}

Dynamic UIButton positioning?

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.

Resources