i really got stuck in a week about this case.
i have a UIBarButtonItem inside UINavigationItem, the hierarchy is like this
The BarButtonItem is a wrapper of segmentedControl. The UIBarbuttonitem and UIsegmentedControl are made programmatically, but the others are made in IB.
in this case, i want to show a view after pressing or touching the barbuttonitem. In several thread i read in this forum, i knew that UIBarbuttonItem didn't inherit UIResponder, so i choose the NavigationBar to get the touch, and i define a frame for it.
this is the code i made :
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
navBar = self.navigationController.navigationBar;
int index = _docSegmentedControl.selectedSegmentIndex;
NSLog(#"index di touches began : %d", index);
CGFloat x;
if (index == 0) {
x = 0.0;
}else if (index == 1) {
x = widthSegment + 1;
}else if (index == 2) {
x = 2*widthSegment + 1;
}else if (index == 3) {
x = 3*widthSegment+ 1;
}else if (in dex == 4) {
x = 4*widthSegment + 1;
}
CGRect frame = CGRectMake(x, 0.00, widthSegment, 46.00);
UITouch *touch = [touches anyObject];
CGPoint gestureStartPoint = [touch locationInView:navBar];
NSLog(#"gesturestart : %f, %f", gestureStartPoint.x, gestureStartPoint.y);
if (CGRectContainsPoint(frame, gestureStartPoint)) {
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:#selector(segmentItemTapped:) object:[self navBar]];
NSLog(#"cancel popover");
}
}
the navBar was declare in myViewController.h and i set it as an IBOutlet.
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
int index = _docSegmentedControl.selectedSegmentIndex;
NSLog(#"index di touches ended : %d", index);
navBar = self.navigationController.navigationBar;
CGFloat x;
if (index == 0) {
x = 0.0;
}else if (index == 1) {
x = widthSegment + 1;
}else if (in dex == 2) {
x = 2*widthSegment + 1;
}else if (index == 3) {
x = 3*widthSegment+ 1;
}else if (index == 4) {
x = 4*widthSegment + 1;
}
CGRect frame = CGRectMake(x, 0.00, widthSegment, 46.00);
UITouch *touch = [touches anyObject];
CGPoint gestureLastPoint = [touch locationInView:navBar];
NSLog(#"lastPOint : %d", gestureLastPoint);
if (CGRectContainsPoint(frame, gestureLastPoint)) {
if (touch.tapCount <= 2) {
[self performSelector:#selector(segmentItemTapped:) withObject:nil afterDelay:0.0];
}
}
}
touchesBegan and touchesEnded was detected when i tap at the toolbar, NOT in the navbar.
i did implemented the hitTest method like this :
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UIView *touchedView = [super hitTest:point withEvent:event];
NSSet* touches = [event allTouches];
// handle touches if you need
return touchedView;
}
but it still nothing get better.
Somebody can decribe why this is happen?
Regards
-Risma-
you can simply add an action to the barbutton item like
[self.mybarbutton setAction:#selector(barButtonTapped:)];
[self.mybarbutton setTarget:self];
Related
I have a game where a fireball UIImage falls from the screen, and the user moves the player object with the touch screen to avoid them. After 8 points, the playAgainButton pops up. However, this playAgainButton button isn't working. It doesn't execute any of the code in the ResetGame method, and it actually resets the position of my character object "Dustin", which I don't want to happen. I have a referencing outlet attached to the button. How can I get the code in ResetGame to work? My ViewController code is below.
int theScore;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self initializeTimer];
}
- (IBAction)ResetGame:(id)sender { //only thing that actually happens right now is that Dustin resets for some reason.
theScore = 0;
[self updateScore];
_Fireball.center = CGPointMake(64, 64);
_endLabel.hidden = true;
_playAgainButton.hidden = true;
[self gameLogic:theTimer];
}
- (void)updateScore {
_score.text = [[NSString alloc] initWithFormat:#"%d",theScore];
}
- (void) initializeTimer {
if(theTimer == nil)
{
theTimer = [CADisplayLink displayLinkWithTarget:self selector:#selector(gameLogic:)];
}
theTimer.frameInterval = 1;
[theTimer addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}
- (void) gameLogic:(CADisplayLink *) theTimer {
if((!CGRectIntersectsRect(_Fireball.frame, _Dustin.frame)) && (theScore < 8)){
if(_Fireball.center.y >600){
int num = arc4random() % 3;
if(num == 0){
_Fireball.center = CGPointMake(64, 64);
}
else if(num == 1){
_Fireball.center = CGPointMake(192, 64);
}
else if(num == 2){
_Fireball.center = CGPointMake(320, 64);
}
theScore = theScore + 1;
[self updateScore];
}
_Fireball.center = CGPointMake(_Fireball.center.x, _Fireball.center.y+12); }
else if(theScore == 8){
_Fireball.center = CGPointMake(_Fireball.center.x, _Fireball.center.y);
_endLabel.text = #"You Win!";
_endLabel.hidden = false;
_playAgainButton.hidden = false;
}
}
- (void) touchesBegan:(NSSet *) touches withEvent:(UIEvent *) event {
UITouch *touch = [touches anyObject];
_firstTouch = [touch locationInView:self.view];
_lastTouch = [touch locationInView:self.view];
_Dustin.center = CGPointMake(_firstTouch.x, _Dustin.center.y);
}
-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [touches anyObject];
_firstTouch = [touch locationInView:self.view];
_lastTouch = [touch locationInView:self.view];
_Dustin.center = CGPointMake(_firstTouch.x, _Dustin.center.y);
}
-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [touches anyObject];
_firstTouch = [touch locationInView:self.view];
_lastTouch = [touch locationInView:self.view];
_Dustin.center = CGPointMake(_firstTouch.x, _Dustin.center.y);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
Your touchesBegan etc. methods are not calling super and thus all touches are being captured by your app and cannot get through to your button.
Add a call to super to each of these methods.
I have a character in my game that I can move left/right and jump. I am using touchesBegan to do that. But when I move left ( keep touching the screen -> makes character faster and faster ), it only jumps when i release it. I would like to jump and move left at the same time.
Here is some of my code :
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self.view];
if((point.x < moveLeftButton.frame.size.width))
{
if((point.y > JumpButton.frame.size.height))
{
leftSide = YES;
sanchez.image = [UIImage imageNamed:#"characterL2"];
}
}
if((point.x) > (backGround.frame.size.width - moveRightButton.frame.size.width))
{
if((point.y > JumpButton.frame.size.height))
{
rightSide = YES;
sanchez.image = [UIImage imageNamed:#"characterR2"];
}
}
if( notJumping && (point.y < JumpButton.frame.size.height) && (sanchezStopAll == NO))
{
AudioServicesPlaySystemSound(jump);
sanchezJumping = 5.5;
notJumping = NO;
}
[self animation];
}
I am not using buttonPressed because they are hidden and I think you can't click hidden buttons.
This is how it looks like if its not hidden:
Thanks for any Help.
You'll only get a single touch by default unless you set multipleTouchEnabled = YES. Then your code should work as expected.
For example:
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.multipleTouchEnabled = YES;
}
I'm trying to resizing an imageview using these functions:
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch* mTouch = [touches anyObject];
if (mTouch.view == [self Logo_01]) {
CGPoint cp = [mTouch locationInView:[self view]];
[[mTouch view]setCenter:CGPointMake(cp.x-xd, cp.y-yd)];
NSLog(#"questo รจ x");
NSLog(#"lalal %f", cp.y);
if (cp.y > 390) {
[_Logo_01 setHidden:YES];
}
if (cp.y < 130) {
[_Logo_01 setHidden:YES];
}
if (cp.x > 290) {
[_Logo_01 setHidden:YES];
}
if (cp.x < 40) {
[_Logo_01 setHidden:YES];
}
}
when i resize my Logo on the app the image resizes correctly but my center point is wrong
I'm sorry i wronged to post code
this is the code that i use to scale my images:
- (IBAction)ScaleImage1:(UIPinchGestureRecognizer *)recognizer
{
recognizer.view.transform = CGAffineTransformScale(recognizer.view.transform, recognizer.scale, recognizer.scale);
recognizer.scale = 1;
CGFloat height = _Logo_01.frame.size.height;
NSLog(#"SIZE ===== %f", height);
if (height > 600) {
[_Logo_01 setHidden:YES];
}
}
try to write same style everywhere (brackets written randomly, spaces, newlines) - it's easier to read and shows that the dev is better.
Logo_01 is just horrible name for UI element. It's good for asset name. Refactor and rename it to eg startingLogoImageView.
Comparing views with == and isEqual works in a different way. One compares pointers, other one objects. Please read about it, as that's a serious bug if that's unintended.
What is xd in setCenter: line? Where is it from?
We try not to use shortcuts in Objective-C. You should name cp touchPoint as it's more obvious what it is in fact. That's the way recommended by Apple and used by devs.
So the code:
// extern NSUInteger const kViewOffsetY; // uncomment this line if you want it accessible via other classes, delete otherwise
NSUInteger const kViewOffsetY = 1;
NSUInteger const kViewOffsetX = 1;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
if ([touch.view isEqual:startingLogoImageView]) {
UIView *touchedView = touch.view;
CGPoint touchPoint = [touch locationInView:self.view];
[touchedView setCenter:CGPointMake(CGRectGetMidX(touchedView.frame) - kViewOffsetX, CGRectGetMidY(touchedView.frame) - kViewOffsetY)];
// where are these values from? you probably should calculate it more dynamically
BOOL shouldHideView = touchPoint.y > 390 || touchPoint.y < 130 || touchPoint.x > 290 || touchPoint.x < 40;
if (shouldHideView) {
[touchedView setHidden:YES];
}
}
}
Why was it working wrong? Because in setCenter: method you were using top left corner (x and y values of view are in top left corner not in the center), while you should use the center point.
I have an NSArray whit 15 UIImageViews:
#interface ViewController : UIViewController{
NSArray *ArrayImages1;
NSArray *ArrayImages2;
}
in viewDidLoad:
ArrayImages1 = [[NSArray alloc] initWithObjects: a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, nil];
Where a1, a2... are the outlets of the UIImageViews
And the same for ArrayImages2
TouchesBegan and TouchesMoved:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self.view];
UIImageView *posible;
int imagen;
if (point.x < 161) {
imagen = Contador1;
if (Contador1 > 14) {imagen = Contador1 - 15;}
imagen--;
posible = [ArrayImages1 objectAtIndex:imagen];
}
else if (point.x > 159) {
imagen = Contador2;
if (Contador2 > 14) {imagen = Contador2 - 15;}
imagen--;
posible = [ArrayImages2 objectAtIndex:imagen];
}
if ([touch view] != posible) { return; }
original2 = posible.center;
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self.view];
UIImageView *posible;
int imagen;
if (point.x < 161) {
imagen = Contador1;
if (Contador1 > 14) {imagen = Contador1 - 15;}
imagen--;
posible = [ArrayImages1 objectAtIndex:imagen];
}
else if (point.x > 159) {
imagen = Contador2;
if (Contador2 > 14) {imagen = Contador2 - 15;}
imagen--;
posible = [ArrayImages2 objectAtIndex:imagen];
}
if ([touch view] != posible) { return; }
posible.center = point;
}
I have to know if the touch was in one of the two posible UIImageViews, and if it was, move it.
The Contador1 and Contador2 ints, are counters that counts how many UIImageView are visible, the user only can move the last 2 of them.
It works, the thing is when i touch outside, it makes the app crash.
If i change in touchesBegan and TouchesMoved, the index of "posible = [ArrayImage..", for 0, it only works for the first UIImageView (i understand why), but it doesent crash.
Any ideas?
I have to know if the touch was in one of the two possible UIImageViews
I can't follow your code very well but it seems like you could simplify things if you first check if the point is within the rect of a view. Then base your logic off of the result. Something like
Using CGRectContainsPoint:
bool CGRectContainsPoint (
CGRect rect,
CGPoint point
);
UIImageView *foundView
for(UIImageView* theView in ArrayImages1){
if (CGRectContainsPoint(theView.frame, touchPoint){
foundView = theView;
break;
}
}
Then...
if (foundView != nil){
// do some logical thing
}
Or...
if ([foundView isEqual:someOtherView]){
// I may have the syntax wrong on the above
}
I want to detect a two-finger diagonal swipe that starts from the bottom right of the screen to the middle. I tried adding UISwipeGestureRecognizer with direction set as "UISwipeGestureRecognizerDirectionUp | UISwipeGestureRecognizerDirectionLeft" but to no vail as the handler is getting invoked even if I start the swipe from the middle of the screen to the top left.
Do I need to sub-class UIGestureRecognizer or can I handle this using touchesBegan and touchesMoved ?
You need to subclass it to use touchesBegan and touchesMoved anyway. I'd do UISwipeGestureRecognizerDirectionUp | UISwipeGestureRecognizerDirectionLeft like you said, then set up two CGRects, one for acceptable starting points, one for acceptable end points. Then use the UIGestureRecognizerDelegate method gestureRecognizer:shouldReceiveTouch:, and check if the touch point is in the acceptable start rect by using CGRectContainsPoint(). Then (I think) in your UISwipeGestureRecognizer subclass, override touchesEnded:withEvent:, and check if the end touch is in the acceptable rect. If it's not, set the state to UIGestureRecognizerStateCancelled (or however you're supposed to cancel a gesture). Also make sure the view it's attached to has its multipleTouchEnabled property set. I haven't actually tried this, but something of the sort should do it. Good luck!
EDIT
Actually, if you didn't want to have to worry about specific rect values for the acceptable start/end points, and make it device independent, you could do this:
//swap in whatever percentage of the screen's width/height you want in place of ".75f"
//set the origin for acceptable start points
CGFloat startRect_x = self.view.frame.size.width * .75f;
CGFloat startRect_y = self.view.frame.size.height * .75f;
//set the size
CGFloat rectWidth = self.view.frame.size.width - startRect_x;
CGFloat rectHeight = self.view.frame.size.height - startRect_y;
//make the acceptable start point rect
CGRect startRect = CGRectMake(startRect_x, startRect_y, rectWidth, rectHeight);
//set the origin for the accepable end points
CGFloat endRect_x = self.view.center.x - rectWidth/2;
CGFloat endRect_y = self.view.center.y - rectHeight/2;
//make the acceptable end point rect
CGRect endRect = CGRectMake(endRect_x, endRect_y, rectWidth, rectHeight);
the touches method of cause can do every Gesture, the Gesture is supported since ios3.2.
i can give you a simple code , you maybe modify by yourself.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
isTwoFingersBegin = NO;
isTwoFingersEnd = NO;
UITouch *touch = [touches anyObject];
UIView *touchView = [touch view];
if ([touches count] == 2)
{
isTwoFingersBegin = YES;
}
touchStartPoint = [touch locationInView:self.view];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
isSwip = YES;
}
#define TOUCH_MOVE_EFFECT_DIST 30
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [touches anyObject];
UIView *touchView = [touch view];
touchEndPoint = [touch locationInView:self.view];
if ([touches count] == 2)
{
isTwoFingersEnd = YES;
}
CGPoint deltaVector = CGPointMake(touchEndPoint.x - touchStartPoint.x, touchEndPoint.y - touchStartPoint.y);
if (fabsf(deltaVector.x) > TOUCH_MOVE_EFFECT_DIST
&&fabsf(deltaVector.y) > TOUCH_MOVE_EFFECT_DIST
&& isSwip &&isTwoFingersBegin&&isTwoFingersEnd) {
theSwipGesture=RightUpGesture;
}
else if (fabsf(deltaVector.x) <- TOUCH_MOVE_EFFECT_DIST
&& fabsf(deltaVector.y) <- TOUCH_MOVE_EFFECT_DIST
&& isSwip&&isTwoFingersBegin&&isTwoFingersEnd) {
theSwipGesture=LeftDownGesture;
}
isSwip = NO;
}
You can use a UIPanGestureRecognizer
- (void)viewPanned:(UIPanGestureRecognizer *)panGR
{
CGPoint translation = [panGR translationInView:self];
CGFloat threshold = self.bounds.size.width/2;
// Detect
Direction direction = DirectionUnknown;
if (translation.x > threshold) {
if (translation.y > threshold) {
direction = DirectionBottomRight;
} else if (translation.y < -threshold) {
direction = DirectionTopRight;
} else {
direction = DirectionRight;
}
} else if (translation.x < -threshold) {
if (translation.y > threshold) {
direction = DirectionBottomLeft;
} else if (translation.y < -threshold) {
direction = DirectionTopLeft;
} else {
direction = DirectionLeft;
}
} else {
if (translation.y > threshold) {
direction = DirectionBottom;
} else if (translation.y < -threshold) {
direction = DirectionTop;
}
}
}
One possible solution would be to map off a group of coordinates on the iPhone's screen where the swipe could potentially start, and another where it could potentially end. Then in the touchesBegan: and touchesMoved: methods, you could compare the starting and ending points of the swipe and determine whether it qualified as diagonal.
Thanks Guys!
I ended up writing custom code in touchesBegan, touchesMoved and touchesEnded and ot works like charm.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if ([touches count] == 2) {
CGPoint nowPoint = [[touches anyObject] locationInView:self];
if( nowPoint.x >= ALLOWED_X)
swipeUp = YES;
}
[super touchesBegan:touches withEvent:event];
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesMoved:touches withEvent:event];
if ([touches count] == 2 && swipeUp) {
CGPoint nowPoint = [[touches anyObject] locationInView:self];
CGPoint prevPoint = [[touches anyObject] previousLocationInView:self];
if( nowPoint.x <= prevPoint.x && nowPoint.y <= prevPoint.y){
}
else {
swipeUp = NO;
}
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesEnded:touches withEvent:event];
CGPoint nowPoint = [[touches anyObject] locationInView:self];
if ([touches count] == 2 && swipeUp && nowPoint.x <= DELTA_X && nowPoint.y <= DELTA_Y) {
NSLog(#"Invoke Method");
}
swipeUp = NO;
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesCancelled:touches withEvent:event];
swipeUp = NO;
}