How to Detect Some Portion in View - ios

I have made a Custom Circle View, How to Detect Some Portion or Part of Circle.I have Tried this using touches
- (BOOL)validatePoint:(CGPoint)myPoint
{
// calculate how far from centre we are with Pythagorean
// √ a2 + b2
CGFloat a = abs(myPoint.x - (self.bounds.size.width/2));
CGFloat b = abs(myPoint.y - (self.bounds.size.height/2));
CGFloat distanceFromCentre = sqrt(pow(a,2) + pow(b,2));
if((distanceFromCentre > self.minRadiusSize) && (distanceFromCentre < radius)){
return YES;
}else{
// not inside doughnut
return NO;
}
}
But its Detecting Entire my View.

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
BOOL transparent=NO;
CGPoint touchLocation = [event locationInView:yourViewName];
if(CGRectContainsPoint(yourViewName.frame, touchLocation))
{
NSLog(#"Found =%d",i);
transparent=YES;
}
return transparent;
}
This will return you whether you have tapped in view or not.

Related

Allow and Disallow Move Touch on some Angles in Circular Slider

I am using EVARoundSlider, which has Slider Arc with start Point and End point. Which makes user to rotate on slider clockwise and anticlockwise.
On touchesMoved method I am able to get First Angle, Last Angle and Current Angle position in Slider View. I want user to stop at End point handler, when it reaches at 360 degree and when start Point handler reaches at 0 degree.
// Working Code on circular Slider View
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:self];
CGFloat fAngle = [self handleAngleByIndex:0];
CGFloat lAngle = [self handleAngleByIndex:1];
int a = AngleFromNorth(_centerPoint, location, SLIDER_FLIPPED);
NSLog(#"First_Angle :%.02f",fAngle);
NSLog(#"last_Angle :%.02f",lAngle);
NSLog(#"Current_Angle :%d",a);
[super touchesMoved:touches withEvent:event];
_dragging = NO;
if (!self.isDragging)
{
if ([self.delegate respondsToSelector:#selector(sliderDraggin:)])
{
[self.delegate sliderDraggin:self];
}
//return;
}
if ([self.delegate respondsToSelector:#selector(sliderDraggin:)])
{
[self.delegate sliderDraggin:self];
}
NSUInteger nearestHandleIndex = [self indexOfNearesPointForTouch:touch];
_nearesHandle = (nearestHandleIndex != NSNotFound) ? _handles[#(nearestHandleIndex)] : nil;
CGFloat d = [_math distanceBetweenPoint:_centerPoint andPoint:location];
CGFloat inOff = _radius - _sliderWidth - _offset.inside;
CGFloat outOff = _radius + _offset.outside;
if (d < inOff || d > outOff)
{
if (self.isNeedToRevoke)
{
_dragging = YES;
return;
}
}
[self.delegate slider:self touchValue:YES atIndex:nearestHandleIndex];
dispatch_async(dispatch_get_main_queue(), ^{
int a = AngleFromNorth(_centerPoint, location, SLIDER_FLIPPED);
[self moveView:_nearesHandle toAngle:a];
[self drawArc];
});
[self informDelegateAboutHandles];
}
If i try to put some condition for StartAngle and End Angle. At a particular points. it is get hanged and nothing slides further.

Make a sprite only jump once

Working with Xcode, Spritebuilder and Cocos2d, I am trying to let the players sprite only jump 1 single time. So when the player taps the screen, the sprite jumps, and only when it has landed, the player should again be able to jump again. I haven't found any clear explanations so far, so hence my question.
Here's my code
Edit so that the code only lets the sprite jump once:
static const CGFloat scrollSpeed = 0.4;
BOOL isInAir;
#implementation GameScene
{
CCSprite *player1;
CCPhysicsNode *physicsNode1;
CCNode *ground1;
CCNode *ground2;
}
- (void)didLoadFromCCB
{
self.userInteractionEnabled = TRUE;
grounds = #[ground1, ground2]
}
- (void)update:(CCTime)delta
{
// moves the player to the right
player1.position = ccp(player1.position.x + delta * scrollSpeed, player1.position.y);
// move the camera with the player
physicsNode1.position = ccp(physicsNode1.position.x - (scrollSpeed *delta), physicsNode1.position.y);
// loop the ground
for (CCNode *ground in grounds)
{
// get the world position of the ground
CGPoint groundWorldPosition = [physicsNode1 convertToWorldSpace:ground.position];
// get the screen position of the ground
CGPoint groundScreenPosition = [self convertToNodeSpace:groundWorldPosition];
// if the left corner is one complete width off the screen, move it to the right
if (groundScreenPosition.x <= (-1 * ground.contentSize.width))
{
// puts the ground piece that is about to leave the screen behind the last one
ground.position = ccp(ground.position.x + 600, ground.position.y);
//NSLog(#"player1 pos: %#", NSStringFromCGPoint(ground.position));
}
}
// clamp velocity
float yVelocity = clampf(player1.physicsBody.velocity.y, -1 * MAXFLOAT, 200.f);
player1.physicsBody.velocity = ccp(0, yVelocity);
}
- (void)touchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
if (isInAir == NO)
{
[player1.physicsBody applyImpulse:ccp(0, 150)];
isInAir = YES;
}
}
- (BOOL) ccPhysicsCollisionBegin:(CCPhysicsCollisionPair *)pair player1:(CCNode *)player1 ground: (CCNode *)ground
{
NSLog(#"player is touching the ground");
isInAir = NO;
return YES;
}
#end
You can use a BOOL. Here is my code for a jump on touch:
BOOL isInAir;//Make this global.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
/* Called when a touch begins */
UITouch *touch = [touches anyObject];
SKSpriteNode *node = [self nodesAtPoint:[touch locationInNode:self]];
if (isInAir == NO)
{
CGFloat impulseX = 0.0f;
CGFloat impulseY = 600.0f;
[node.physicsBody applyImpulse:CGVectorMake(impulseX, impulseY) atPoint:node.position];
isInAir = YES;
//other stuff
}
}
Then when you contact ground, set isInAir to NO.

Is there a way to detect closest UIButton to tap location?

Is there a way to easily detect the closest UIButton to a tap location? I've currently subclasses a pan gesture, but am just having trouble figuring out how to approach this. In the past I've resized every button's frame so that there isn't empty space in between buttons, but that won't be possible in my current case.
At the moment I've successfully looped through my subviews and can detect when I am / am not on top of a button. But how can I detect the closest button when I'm not on a button?
Thanks!
Here's my code for identifying my UIButtons:
- (UIView *)identifySubview:(NSSet *)touches {
CGPoint tapLocation = [[touches anyObject] locationInView:self.view];
for (UIView *view in [self.view viewWithTag:1000].subviews) {
for (UITableViewCell *cell in view.subviews) {
for (UIView *contentView in cell.subviews) {
for (UIButton *button in contentView.subviews) {
if ([button isKindOfClass:[UIButton class]]) {
CGRect trueBounds = [button convertRect:button.bounds toView:self.view];
if (CGRectContainsPoint(trueBounds, tapLocation)) {
return button;
} else {
//How would I detect the closest button?
}
}
}
}
}
}
return nil;
}
Failing a direct hit, you could find the minimum distance to the centers of the buttons like this:
// this answers the square of the distance, to save a sqrt operation
- (CGFloat)sqDistanceFrom:(CGPoint)p0 to:(CGPoint)p1 {
CGFloat dx = p0.x - p1.x;
CGFloat dy = p0.y - p1.y;
return dx*dx + dy*dy;
}
- (UIView *)nearestViewIn:(NSArray *)array to:(CGPoint)p {
CGFloat minDistance = FLT_MAX;
UIView *nearestView = nil;
for (UIView *view in array) {
CGFloat distance = [self sqDistanceFrom:view.center to:p];
if (distance < minDistance) {
minDistance = distance;
nearestView = view;
}
}
return nearestView;
}
// call ...
[self nearestViewIn:view.subviews to:tapLocation];
You may try to write in - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event

Pass touch to nearest UIButton?

I am trying to create a view with multiple UIButtons where any tap would be registered as a tap on the nearest UIButton. I have been unsuccessful so far, and I am hoping you guys/gals have some knowledge on standard approaches/methods used to do what I am trying to do.
You could use the Touches Began method:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// Get the CGPoint of the touch:
UITouch touch = [touches anyObject];
CGPoint touchPoint = [touch locationInView:self.view];
// Loop through an array containing your buttons and see if we tapped
// one of these buttons, if so, do nothing and let the button handle the tap
for (UIButton button in MyButtonsArray){
if(CGRectContainsPoint(button.frame, touchPoint)) {
return;
}
}
// if the loop completes without returning, you tapped something other than a button
// so add code here that uses the mathematical distance formula to
// calculate which button is the closest to the tap point.
}
You have all the necessary "data" in terms of coordinates of the button and coordinates of the touch point to calculate the closest button to the touch point.
that's why I am assuming that simply passing the touch to the nearest UIButton would be more practical.
No, you should place rectangle buttons next to each other and do the hit testing to determine if the touch was within the irregular shaped area.
See my blog post Hit Testing Done Right how to test with a shaped layer. There it uses a UIView, but as UIButton inherits from UIView, it would work the same, if you subclass like
#interface MyButton : UIButton
#implementation MyButton
//
// ...
//
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
CGPoint p = [self convertPoint:point toView:[self superview]];
if(self.layer.mask){ // a layer's mask is found. Mask can be any CGPath
if (CGPathContainsPoint([(CAShapeLayer *)self.layer.mask path], NULL, p, YES) )
return YES;
}else {
if(CGRectContainsPoint(self.layer.frame, p))
return YES;
}
return NO;
}
#end
If you want to work with partially transparent images, have a look at OBShapedButton, where alpha of a certain threshold will determine if the button was hit or not. But as mine path based approach it does so by overwriting -pointInside:withEvent:
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
// Return NO if even super returns NO (i.e., if point lies outside our bounds)
BOOL superResult = [super pointInside:point withEvent:event];
if (!superResult) {
return superResult;
}
// Don't check again if we just queried the same point
// (because pointInside:withEvent: gets often called multiple times)
if (CGPointEqualToPoint(point, self.previousTouchPoint)) {
return self.previousTouchHitTestResponse;
} else {
self.previousTouchPoint = point;
}
BOOL response = NO;
if (self.buttonImage == nil && self.buttonBackground == nil) {
response = YES;
}
else if (self.buttonImage != nil && self.buttonBackground == nil) {
response = [self isAlphaVisibleAtPoint:point forImage:self.buttonImage];
}
else if (self.buttonImage == nil && self.buttonBackground != nil) {
response = [self isAlphaVisibleAtPoint:point forImage:self.buttonBackground];
}
else {
if ([self isAlphaVisibleAtPoint:point forImage:self.buttonImage]) {
response = YES;
} else {
response = [self isAlphaVisibleAtPoint:point forImage:self.buttonBackground];
}
}
self.previousTouchHitTestResponse = response;
return response;
}

Custom Gesture for Increase the size of the view

How can i write custom gesture for increase the size of the view in all the direction (i.e) in origin side and size of the view.
Example:
the user should touch the view in any one of the corner. either near to origin side or view end side.
Example: View frame size is (100,100,200,200). and minimum touch distance is 15 pixel from any side.
so, if the user touch location is (X=15,Y=40) in
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
method means that touch near to the origin side.
same if the user touch location is (X=15, Y=190) in
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
method means the touch is near to the size side.
My code:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesBegan:touches withEvent:event];
if([touches count] != self.touchMinimumCount ||
[[touches anyObject] tapCount] > self.tapMinimumCount)
{
self.state = UIGestureRecognizerStateFailed;
return;
}
self.startPoint = [[touches anyObject] locationInView:self.view];
self.viewFrame = self.view.frame;
if(((self.startPoint.x - self.view.bounds.origin.x) <= self.minimumTouchDistance) ||
((self.startPoint.y - self.view.bounds.origin.y) <= self.minimumTouchDistance) ||
((ABS(self.startPoint.x - self.view.bounds.size.width)) <= self.minimumTouchDistance) ||
((ABS(self.startPoint.y - self.view.bounds.size.height)) <= self.minimumTouchDistance))
{
self.state = UIGestureRecognizerStatePossible;
if(((self.startPoint.x - self.view.bounds.origin.x) <= self.minimumTouchDistance) ||
((self.startPoint.y - self.view.bounds.origin.y) <= self.minimumTouchDistance) )
{
self.currentTouchPosition = touchPositionIsOrigin;
}
else if(((ABS(self.startPoint.x - self.view.bounds.size.width)) <= self.minimumTouchDistance) ||
((ABS(self.startPoint.y - self.view.bounds.size.height)) <= self.minimumTouchDistance))
{
self.currentTouchPosition = touchPositionIsSize;
}
}
else
{
self.state = UIGestureRecognizerStateFailed;
}
}
My gesture possible state setting if the touch in side the touch distance only.
Now i want to resize the view frame according to the user finger move.
if the user touch the origin side and move towards the left direction means, want to change the origin.x of the view and the width also want to increase.
if the user touch the origin side and move towards the top direction means, want to change the origin.y of the view and the width also want to increase.
if the user touch the origin side and move towards the right direction means, want to change the origin.x of the view.
if the user touch the origin side and move towards the bottom direction means, want to change the origin.y of the view.
if the user touch the size side and move towards the left direction means, want to reduce the width of the view.
if the user touch the size side and move towards the top direction means, want to reduce the height of the view.
if the user touch the size side and move towards the right direction means, want to increase the width of the view.
if the user touch the size side and move towards the bottom direction means, want to increase the height of the view.
this all change according tho the user finger in that view while moving.
My code:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesMoved:touches withEvent:event];
if(self.state == UIGestureRecognizerStateFailed) return;
direction currentDirection;
CGPoint currentLocation = [[touches anyObject] locationInView:self.view];
if(self.state == UIGestureRecognizerStatePossible ||
self.state == UIGestureRecognizerStateChanged)
{
if((currentLocation.x - self.startPoint.x) > 0)
{
currentDirection = directionRight;
self.state = UIGestureRecognizerStateChanged;
if(self.currentTouchPosition == touchPositionIsOrigin)
{
distanceInOriginX = // need to implement.
distanceInSizeX = // need to implement.
}
else if(self.currentTouchPosition == touchPositionIsSize)
{
distanceInSizeX = // need to implement.
}
}
else if((currentLocation.x - self.startPoint.x) < 0)
{
currentDirection = directionLeft;
self.state = UIGestureRecognizerStateChanged;
if(self.currentTouchPosition == touchPositionIsOrigin)
{
distanceInOriginX = // need to implement.
distanceInSizeX = // need to implement.
}
else if(self.currentTouchPosition == touchPositionIsSize)
{
distanceInSizeX = // need to implement.
}
}
else if((currentLocation.y - self.startPoint.y) >= 0)
{
currentDirection = directionBottom;
self.state = UIGestureRecognizerStateChanged;
if(self.currentTouchPosition == touchPositionIsOrigin)
{
distanceInOriginY = // need to implement.
distanceInSizeY = // need to implement.
}
else if(self.currentTouchPosition == touchPositionIsSize)
{
distanceInSizeY = // need to implement.
}
}
else if((currentLocation.y - self.startPoint.y) < 0)
{
currentDirection = directionTop;
self.state = UIGestureRecognizerStateChanged;
if(self.currentTouchPosition == touchPositionIsOrigin)
{
distanceInOriginY = // need to implement.
distanceInSizeY = // need to implement.
}
else if(self.currentTouchPosition == touchPositionIsSize)
{
distanceInSizeY = // need to implement.
}
}
else
{
currentDirection = directionUnknown;
}
self.originPoint = CGPointMake(distanceInOriginX, distanceInOriginY);
self.sizePoint = CGPointMake(distanceInSizeX, distanceInSizeY);
}
}
i mentioned the // need to implement. where ever i want the code for to achieve the functionality which i mentioned in that points. so, kindly help to go ahed.
if my was is wrong means, share the best way to do the same type of gesture.
any example is there also kindly share here. thanks in advance....
If you want to scale the size of a view, then use UIPinchGestureRecognizer. An example code is given here
UIPinchGestureRecognizer *pinchRecognizer = [[UIPinchGestureRecognizer alloc]initWithTarget:self action:#selector(scale:)];
pinchRecognizer.delegate = self;
[self addGestureRecognizer:pinchRecognizer];
handler method is
#pragma mark - Gesture handling functions
-(void)scale:(UIPinchGestureRecognizer*)recognizer {
if ([recognizer state] == UIGestureRecognizerStateBegan) {
_lastScale = 1.0;
}
CGFloat scale = 1.0 - (_lastScale - [recognizer scale]);
CGAffineTransform currentTransform = self.imgView.transform;
CGAffineTransform newTransform = CGAffineTransformScale(currentTransform, scale, scale);
self.imgView.transform = newTransform;
_lastScale = [recognizer scale];
}

Resources