I'm currently in development of a card game of sorts, and when a user plays a card, I want that card to move from its current location in the players hand to the "face up" pile on the screen.
Edit: To answer some questions, and make the question/answers clean, here is some of my code.
+(id)card:(NSString*)suit :(int) value {
HHCard *card = [HHCard new];
card.value = value;
card.suit = suit;
//used for selection of cards during human turn
card.isSelected = false;
return card;
}
Your card has to be associated with an UIView of some kind. Why not use:
[UIView animateWithDuration:animations:]
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/#//apple_ref/occ/clm/UIView/animateWithDuration:animations:
Then in your animations block you just change the x and y coordinates to where you want the card to go. It will animate it for you.
I apologize for not answering the question sooner, however the answer is quite simple. In order to move an object, in this example a 'card' to the desired location on the screen, create a CGPoint that contains the point where you wish your object to move, and then have your object run the SKAction moveTo:(CGPoint)duration:(NSTimeInterval).
CGPoint newPosition = {newX,newY};
[yourObject runAction:[SKAction moveTo:newPosition duration:lengthOfAnimation]];
Their are 4 methods that has been provided to us, through which we can track the touch made to a view. the methods are below :
(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
You just need to apply these methods in your controller class and then can track the location of your view in these method accordingly.
Hope this may help.
Related
I am beginner in ios and I have done basic functionality with UISlider , changing its value on dragging thumb. But now in my app I want to move the thumb of slider gradually in same direction where I am touching slider's track without dragging the thumb of slider. Thumb must reach to exact touched position on the track in 2 or more steps.
I know it requires involvement of UITouch but unable to understand HOW?
You need to subclass UISlider to add this functionality. After subclassing, you need to implement touchesBegan and touchedMoved in your subclass. Well, here how i did
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [touches anyObject];
CGFloat maxX = CGRectGetMaxX(self.frame);
CGFloat minX = CGRectGetMinX(self.frame);
int value = (maxX - minX) /(self.maximumValue - self.minimumValue);
[self setValue:([touch locationInView:self].x - minX) / value animated:YES];
[self beginTrackingWithTouch:touch withEvent:event];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
[self continueTrackingWithTouch:[touches anyObject] withEvent:event];
}
You need more work to stabilise a little bit more when user first tap, but i hope you get the idea.
I'm trying to implement a uitableview that its rows can be dragged to right and left (and show something behind them).
The code works fine, I've implemented it using the following methods:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
My problem is that the rows also contain UIButtons that when clicking them- should be clicked but when dragging - should drag the entire cell.
I've found this solution. Basically to bubble up the events when clicking on the UIButtons:
[super touchesBegan:touches withEvent:event];
[self.nextResponder touchesBegan:touches withEvent:event];
But, it seems taht the event touchesMoved only bubbles once.
I've seen all sort of questions in this area. Example. But I don't see any solution or responses.
Any help, suggestion or creative workaround would be appreciated!
Instead of implementing touchesBegan, etc. why not use a UIPanGestureRecognizer? I tested this with just a simple rectangular view which was mostly covered by a UIButton. The view was dragged, no matter where I touched, and the button method fired if I clicked over the button.
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePanGesture:)];
[self.theView addGestureRecognizer:panGesture]; //theView is IBOutlet for small view containing a button
}
-(void)viewDidAppear:(BOOL)animated {
self.currentViewFrame = self.theView.frame;
}
- (IBAction)handlePanGesture:(UIPanGestureRecognizer *)sender {
CGPoint translate = [sender translationInView:self.view];
CGRect newFrame = self.currentViewFrame;
newFrame.origin.x += translate.x;
newFrame.origin.y += translate.y;
sender.view.frame = newFrame;
if (sender.state == UIGestureRecognizerStateEnded)
self.currentViewFrame = newFrame;
}
-(IBAction)doClick:(id)sender {
NSLog(#"click");
}
Just check to see which one was touched using the tag system.
I have made a UISlider work just like the "slide to unlock" slider.
What I need to do is determine the point at which lifting your finger off is classed as touchUpOUTSIDE and not touchUpINSIDE. This is the point where you slide your finger past the end of the slider too far.
I guess it's the same as with a UIButton, you can press the button then slide your finger off the button and depending how far you go, it can still be classed as touchUpInside.
If possible, i'd like to mark the target area with a circle.
Once i've managed to find where this point is, is it possible to change it? So I could have a bigger target area?
I really don't know where to start with this. Thanks
According to the docs, the UIControlEventTouchUpOutside event is triggered when the finger is outside the bounds of the control. If you're trying to change that area, the slider will scale with it. Why not just tie the action for UIControlEventTouchUpOutside to the same as UIControlEventTouchUpInside?
It's taken me a few hours, but i've managed to sort this.
I've done a lot of testing overriding touchesMoved, touchesEnded and sendAction:action:target:event and it seems that any touch within 70px of the frame classes as a touch INSIDE. So for a UISlider that's 292x52 any touch from x:-70 to x:362 or y:-70 to 122 will count as an inside touch, even though it's outside the frame.
I have come up with this code that will override a custom class to allow a bigger area of 100px around the frame to count as an inside touch:
#import "UICustomSlider.h"
#implementation UICustomSlider {
BOOL callTouchInside;
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
callTouchInside = NO;
[super touchesMoved:touches withEvent:event];
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
CGPoint touchLocation = [[touches anyObject] locationInView:self];
if (touchLocation.x > -100 && touchLocation.x < self.bounds.size.width +100 && touchLocation.y > -100 && touchLocation.y < self.bounds.size.height +100) callTouchInside = YES;
[super touchesEnded:touches withEvent:event];
}
-(void)sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event
{
if (action == #selector(sliderTouchOutside)) { // This is the selector used for UIControlEventTouchUpOutside
if (callTouchInside == YES) {
NSLog(#"Overriding an outside touch to be an inside touch");
[self sendAction:#selector(UnLockIt) to:target forEvent:event]; // This is the selector used for UIControlEventTouchUpInside
} else {
[super sendAction:action to:target forEvent:event];
}
} else {
[super sendAction:action to:target forEvent:event];
}
}
With a little bit more tweaking I should be able to use it for the opposite also. (Using a closer touch as an outside touch).
I'm trying to call these Methods on some event:
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
But i don't know how to fill the parameters :
1 - (NSSet *)touches
2 - withEvent:(UIEvent *)event
Can any one provide me with a sample parameters do call to (void)touchesEnded and (void)touchesMoved: (and
- (void)touchesBegan
There's no public constructors for UITouch and UIEvent, so you cannot generate the parameters required by the touch method.
As dasblinkenlight said, there could be surely another approach to your problem. But, the current approach is absolutely not possible.
Those methods are called automatically by the system. You never call them directly.
What you should do, well that depends on your goal. If you just want to "simulate" touches, just have helper methods. Then, have touchesXXXX call those directly.
We do not get an API to create UITouch objects, so you have to mirror them if you want to keep their information around. Something like...
#interface MyTouch : NSObject {
UITouchPhase phase
NSUInteger tapCount
NSTimeInterval timestamp
UIView *view
UIWindow *window
CGPoint locationInView;
CGPoint locationInWindow;
#end
Then, you could have a method like this...
- (void)handleTouches:(NSSet*)touches {
}
Where touches was a set of MyTouch objects.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
// For UITouch in touches, create a MyTouch, and add it to your own
// collection of touches.
[self handleTouches:myTouches];
}
If you did this for each touchesXXXX method, each one of them pass off handling to your own method.
Now, by doing this, you have control over creating your own touch objects. You can make them be configured for any view, or pattern you want. Then, in any other piece of code, you can create a collection of MyTouch objects, and call handleTouches: with them.
As long as the touchesXXXX methods just create your special objects, and pass them on to your method, you can have the exact same behavior whether the system generates the touches, or you simulate them.
Now, what you DO NOT get is automatic generation of system events.
If you are getting killed by the performance of that, there are simple ways to avoid the creation of the extra set and objects, but that's not your question.
So, I'm capturing multiple touches and determining the number and where each of the touches occurred and I'm seeing different behavior between a UIView UIViewController.
Basically, the event handler is coded below: (in this case the touchesEnded, but it really doesn't matter). What happens in the View, is that I get the entire collection of touches, but in the controller, I get only one touch at a time, that is there is never a collection of touches, but the TouchesEnded gets executed for each touch that occurred in the same moment.
I add the subviews as identically as possible...
Can someone 'spain to me what's going on? Why doesn't the controller version give me the collection?
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
int total = 0;
for (UITouch *touch in touches)
{
for(UIView *myView in [contentView subviews])
{
if (CGRectContainsPoint([myView frame], [touch locationInView:self.view]))
total++; // this is always 1 for the UIViewController
// but I get the full number within the UIView version
}
}
}
I suspect you are getting the touches but that the views are different. Check that contentView is the same and has the same subviews.
I am not sure that I am right but this thing always work for me.
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
If(touch.view==your view)
{
NSLog("do your task here");
}
}