How to create buttons around circle with some radius - ios

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.

Related

Draw grid of circles

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

How to get UIButton position from UIScrollView

I have a scrollView with many buttons on it. I'm trying to get the Button position form the scroll so I can scroll it to that position. My issue is I always get the same value in _btnV.frame.origin.x once I click on each button. So please how I can resolve this issue?
- (void)scrollView{
segmentWidth = screenWidth / 5;
NSArray *images = #[#"Smiley-1.png",#"Smiley-2.png",#"Smiley-3.png",#"Smiley-4.png",#"Smiley-5.png",#"Smiley-5.png",#"Smiley-5.png",#"Smiley-4.png",#"Smiley-1.png",#"Smiley-2.png",#"Smiley-3.png",#"Smiley-4.png"];
long ScrollContentSize = ((images.count -1)*segmentWidth)+screenWidth;
_scrlView.contentSize = CGSizeMake(ScrollContentSize, _scrlView.frame.size.height);
float screenX2 = screenHeight/2 - segmentWidth/2;
__block float screenX = (screenWidth-segmentWidth)/2;
NSMutableArray *arr = [[NSMutableArray alloc] init];
for(int i=0; i<images.count; i++)
{
_btnV = [[UIButton alloc]init];
[_btnV setFrame:CGRectMake(screenX, screenX2, segmentWidth, segmentWidth)];
[_btnV setImage:[UIImage imageNamed:[NSString stringWithFormat:#"%#",[images objectAtIndex:i]]] forState:UIControlStateNormal];
[_btnV setBackgroundColor:[UIColor redColor]];
[_btnV addTarget:self action:#selector(scrollToMe:) forControlEvents:UIControlEventTouchUpInside];
[_btnV setTag:i];
[arr addObject:_btnV];
[_scrlView addSubview:_btnV];
screenX = screenX+segmentWidth;
}
_menuItems = arr;
[self.view addSubview:_scrlView];
}
-(void) scrollToMe:(id)sender{
int scrollX = _scrlView.contentOffset.x;
int mod = scrollX % segmentWidth;
int position = scrollX/segmentWidth;
float positionOffset = (float) mod / segmentWidth;
scrollX = position * segmentWidth;
NSLog(#"position:%f",_btnV.frame.origin.x);
//scrollX = ...
[_scrlView setContentOffset:CGPointMake(scrollX, scrollX) animated:YES];
}
Find the button using its tag value
-(void) scrollTo:(id)sender{
UIButton * button = (UIButton *)sender;
int position = button.tag;
scrollX = position * segmentWidth;
NSLog(#"position:%f",_btnV.frame.origin.x);
//scrollX = ...
[_scrlView setContentOffset:CGPointMake(scrollX, scrollX) animated:YES];
}
You are calling selector method of UIButton. so in this method, you can directly get UIButton position with respect to UIScrollView. like
-(void) scrollTo:(id)sender{
UIButton* btnClick = (UIButton*)sender;
NSLog(#"X position : %f",btnClick.frame.origin.x);
}
Hope this help you.
try this , it will log position of all your button correctly
-(void) scrollTo:(id)sender{
int scrollX = _scrlView.contentOffset.x;
int mod = scrollX % segmentWidth;
int position = scrollX/segmentWidth;
float positionOffset = (float) mod / segmentWidth;
scrollX = position * segmentWidth;
for(int i=0; i<images.count; i++)
{ if([[[_scrlView subviews] objectAtIndex:i] isKindOfClass:[UIButton class]]) {
Button btn = [[_scrlView subviews] objectAtIndex:i];
NSLog(#"position:%f",btn.frame.origin.x);
}
}
//scrollX = ...
[_scrlView setContentOffset:CGPointMake(scrollX, scrollX) animated:YES];
}

How to resize all subviews/sublayers when superview is resized?

This question relates to the project: https://github.com/FindForm/FFAngularPointilism
Currently, all the behavior is dictated by the dimensions of the original UIImage. Despite resizing, shrinking, and rotating, the drawing of the "double triangle squares" remains the same. The triangular blur is unchanged regardless of the bounds of the UIImageView to which it is applied.
In my UIImageView subclass, I initialize with a UIImage and call the following in the designated initializer:
- (void)loadMatrix
{
num = 12;
CGFloat width = self.bounds.size.width;
CGFloat height = self.bounds.size.height;
CGFloat theBiggestSideLength = MAX(width, height);
_array = [NSMutableArray array];
_array2 = [NSMutableArray array];
for(int i = 0; i < theBiggestSideLength; i += num)
{
[self.array addObject:[NSMutableArray array]];
[self.array2 addObject:[NSMutableArray array]];
}
for(int i = 0; i < self.array.count; i++)
{
for(int j = 0; j < self.array.count; j++)
{
[self.array[i] addObject:[self getRGBAsFromImage:self.image
atX:j * 2 * num
andY:i * 2 * num]];
int xIndex = ((j * 2 * num) - (num / 2.0));
int yIndex = ((i * 2 * num) + (num / 2.0));
xIndex %= (int)width * 2;
yIndex %= (int)width * 2;
NSLog(#"%d", xIndex);
[self.array2[i] addObject:[self getRGBAsFromImage:self.image
atX:xIndex
andY:yIndex]];
}
}
_imageGrayscaleView = [[UIImageView alloc] initWithImage:[self convertToGreyscale:self.image]];
_finalbwimage = self.imageGrayscaleView.image;
_imageGrayscaleView.frame = self.bounds;
[self insertSubview:_imageGrayscaleView atIndex:0];
_viewMask = [[UIView alloc] initWithFrame:self.frame];
_viewMask.center = CGPointMake(_viewMask.center.x,
_viewMask.center.y + _viewMask.frame.size.height / 2.0f);
_shapeLayer = [[CAShapeLayer alloc] init];
CGRect maskRect = CGRectZero;
CGPathRef path = CGPathCreateWithRect(maskRect, NULL);
_shapeLayer.path = path;
CGPathRelease(path);
self.imageGrayscaleView.layer.mask = _shapeLayer;
}
To draw these tiles, I add a timer and call the following method each interval. Num and row are updating as expected.:
- (void)drawTile
{
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(pixel * num, row * num, num, num)];
view.backgroundColor = [self.array[row] objectAtIndex:pixel];
[self addSubview:view];
[self.ksubviews addObject:view];
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(view.frame.origin.x , view.frame.origin.y + (view.frame.size.height))];
[path addLineToPoint:CGPointMake(view.frame.origin.x , view.frame.origin.y)];
[path addLineToPoint:CGPointMake(view.frame.origin.x + view.frame.size.width, view.frame.origin.y + view.frame.size.height)];
[path closePath];
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.path = path.CGPath;
shapeLayer.strokeColor = [[UIColor blackColor] CGColor];
shapeLayer.fillColor = [((UIColor *)[self.array2[row] objectAtIndex:pixel]) CGColor];
shapeLayer.lineWidth = 0;
[self.layer addSublayer:shapeLayer];
[self.ksublayers addObject:shapeLayer];
}
The following is the correct behavior:
When this image is resized via the nib, or its bounds set programmatically, the animatable triangular squares are unchanged.
You make all the subviews changes on the method Draw Rect inside your class, and every time you make a change, to the superview, you call the method setNeedDisplay.
I didn't understand you question very well, but i hope this helps!

CCScrollView does't receive touches (Cocos2d V 3.0)

I try to add CCScrollView with paging (cocos2d- iphone v3.0). But it's not working.
It doesn't call any delegate methods (for example scrollViewDidScroll:).
CCNode *cards = [CCNode node];
for (int i = 0 ; i < 3; i++) {
CCLabelTTF *label = [CCLabelTTF labelWithString:[NSString stringWithFormat:#"label %d", i] fontName:#"Arial" fontSize:24];
label.color = [CCColor redColor];
label.position = ccp(winSize.width * i + winSize.width * 0.5 , winSize.height * 0.5);
[cards addChild:label];
}
self.scrollView = [[CCScrollView alloc] initWithContentNode:cards];
self.scrollView.contentSizeType = CCSizeTypeNormalized;
self.scrollView.contentSize = CGSizeMake(3, 1);
self.scrollView.pagingEnabled = YES;
self.scrollView.delegate = self;
self.scrollView.position = CGPointZero;
self.scrollView.anchorPoint = CGPointZero;
[self addChild:self.scrollView];
You actually need to set the contentSize of the contentNode of the scrollView as opposed to the contentSize of the scrollView.
In CCScrollView.h
#property (nonatomic,strong) CCNode* contentNode;
So you should replace this part of the code:
self.scrollView.contentSizeType = CCSizeTypeNormalized;
self.scrollView.contentSize = CGSizeMake(3, 1);
With this:
self.scrollView.contentNode.contentSizeType = CCSizeTypeNormalized;
self.scrollView.contentNode.contentSize = CGSizeMake(3, 1);

CALayer breaks in landscape mode

I am coding a custom transition based on the Shutter transition tutorial. it's pretty simple, the first view controller is meant to divide into hundreds of pieces and then fade one at a time, problem however is that it doesn't work in landscape mode. apparently the "contentsRect" method of CALayer (which is supposed to work on the normalized image space) only works in the portrait mode. I have attached my file in here if anyone needs to have a look and please if you can help me.
http://tinyurl.com/88669oy
regards
here is also my trans code:
CALayer* viewLayer;
- (void)transitWithImageView:(UIImageView *)imgView inView:(UIView *)view withImage:(UIImage *)img
{
viewLayer = [imgView layer];
[view.layer addSublayer:viewLayer];
CGSize layerSize = viewLayer.bounds.size;
// BEGINING OF MAKE ARRAY OF TRANSITIONS
NSMutableArray* allTransitionsArr = [[NSMutableArray alloc] init];
for ( int i = 0; i < BLOCK_COUNT; i++ )
{
CABasicAnimation *fade = [CABasicAnimation animationWithKeyPath:#"opacity"];
fade.toValue = [NSNumber numberWithFloat:-1-sqrt(i)];
fade.autoreverses = NO;
fade.duration = DURATION;
[allTransitionsArr addObject: fade];
}
// END OF MAKE ARRAY OF TRANSITIONS
NSMutableArray *blocks = [[NSMutableArray alloc] init];
[viewLayer removeFromSuperlayer];
[CATransaction begin];
[CATransaction setCompletionBlock:^(void)
{
[blocks enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
{
[obj setDelegate:nil];
[obj removeFromSuperlayer];
}];
[view.layer addSublayer:viewLayer];
}];
CGFloat bandWidth = layerSize.width / sqrt(BLOCK_COUNT);
CGFloat bandHeight = layerSize.height / sqrt(BLOCK_COUNT);
int yVal = -1;
for(int i = 0; i < BLOCK_COUNT; i++)
{
CALayer *block = [[CALayer alloc] init];
block.masksToBounds = YES;
CGFloat xOffset = 1.f / sqrt(BLOCK_COUNT);
CGFloat yOffset = 1.f / sqrt(BLOCK_COUNT);
block.bounds = CGRectMake(0, 0, bandWidth, bandHeight);
block.bounds = CGRectMake(0.f, 0.f, bandWidth, bandHeight);
block.contents = (id)[img CGImage];
block.contentsGravity = kCAGravityCenter;
CGPoint bandOrigin = viewLayer.frame.origin;
bandOrigin.x = bandOrigin.x + (bandWidth * (i % (int)sqrt(BLOCK_COUNT)));
if (i % (int)sqrt(BLOCK_COUNT) == 0 )
yVal++;
bandOrigin.y = bandOrigin.y + (bandHeight * yVal);
// PROBLEM IS GOT TO BE HERE
block.contentsRect = CGRectMake(xOffset * (i % (int)sqrt(BLOCK_COUNT)) ,yOffset * yVal, xOffset, yOffset);
[block setValue:[NSValue valueWithCGPoint:bandOrigin] forKeyPath:#"frame.origin"];
[view.layer addSublayer:block];
[block addAnimation:[allTransitionsArr objectAtIndex: BLOCK_COUNT - i - 1] forKey:nil];
[blocks addObject:block];
[block release];
}
[CATransaction commit];
[blocks release];
}

Resources