Trying to move UIImageView, moving whole Screen View - ios

I want my UIViewImages to be movable with touch. I'm trying to use code implemented in my ViewController:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
if ([touches count]==1) {
UITouch *touch = [touches anyObject];
CGPoint p0 = [touch previousLocationInView:self.view];
CGPoint p1 = [touch locationInView:self.view];
CGPoint center = self.view.center;
center.x += p1.x - p0.x;
center.y += p1.y - p0.y;
self.view.center = center;
}
}
When I try to drag an UIImageView, I'm dragging whole screen, which is incorrect.
Need help!
Karol

You create a gesture recognizer and add it to a view like this:
UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(gestureRecognizerMethod:)];
[self.imageView addGestureRecognizer:panGestureRecognizer];
you can adjust the position of the image view
- (void)gestureRecognizerMethod:(UIPanGestureRecognizer *)recogniser
{
if (recognizer.state == UIGestureRecognizerStateBegan || recognizer.state == UIGestureRecognizerStateChanged)
{
CGPoint touchLocation = [recognizer locationInView:self.view];
self.imageView.center = touchLocation;
}
}
read this article.

If I read your code right self.view actually IS the whole screen.
Maybe you mean self.yourImageView instead?

Related

How to pan without touch action getting executed in Sprite Kit?

In touchesBegan I have my logic for single touch. And I'm trying to add ability to change camera position with pan. For pan I use touchesMoved. Everything is kind of okay, but once I pan, action for touch gets executed too.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
for (UITouch *touch in touches) {
CGPoint location = [touch locationInNode:self];
NSArray *sprites = [self nodesAtPoint:location];
for (SKSpriteNode *sprite in sprites)
{
//*
//* How to stop executing this block when panning?
//*
}
}
}
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint positionInScene = [touch locationInNode:self];
CGPoint previousPosition = [touch previousLocationInNode:self];
CGPoint translation = CGPointMake((-1)*(positionInScene.x - previousPosition.x), (-1)*(positionInScene.y - previousPosition.y));
CGPoint cameraPos = [self camera].position;
[self camera].position = CGPointAdd(cameraPos, translation);
}
Look at how to use the Pan Gesture that is built into IOS, with it you will have to option to allow it to also execute the touch event or not.
I will give you an answer using the view controller, you may use it somewhere else though
Objective C:
Open up ViewController.h and add the following declaration:
#interface ViewController : UIViewController<UIGestureRecognizerDelegate>
...
- (IBAction)handlePan:(UIPanGestureRecognizer *)recognizer;
Then implement it in ViewController.m as follows:
- (IBAction)handlePan:(UIPanGestureRecognizer *)recognizer {
CGPoint translation = [recognizer translationInView:self.view];
recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x,
recognizer.view.center.y + translation.y);
[recognizer setTranslation:CGPointMake(0, 0) inView:self.view];
}
http://www.raywenderlich.com/6567/uigesturerecognizer-tutorial-in-ios-5-pinches-pans-and-more
At this point you can link it via UI like in the tutorial above, or declare somewhere in the beginning
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePan:)];
[self.view addGestureRecognizer:pan];
Swift:
class ViewController : UIViewController, UIGestureRecognizerDelegate
... then in your code
#IBAction func handlePan(recognizer:UIPanGestureRecognizer) {
let translation = recognizer.translationInView(self.view)
if let view = recognizer.view {
view.center = CGPoint(x:view.center.x + translation.x,
y:view.center.y + translation.y)
}
recognizer.setTranslation(CGPointZero, inView: self.view)
}
http://www.raywenderlich.com/76020/using-uigesturerecognizer-with-swift-tutorial
At this point you can link it via UI like in the tutorial above, or declare somewhere in the beginning stages like init:
let pan = UIPanGestureRecognizer(target: self, action: "handlePan:")
self.view.addGestureRecognizer(pan);

Using collision on bounds of UIView

I have an ImageView that moves around the UIView, is it possible to detect collision of the ImageView and the view its self? For example the ImageView hits the side of the view I want it to run an action. -(void)restart {}
If this is possible can you detect which side it has collided with?
You can create a custom UIImageVIew and implement the methods touchBegan and touchMoved (don't forget to add [self setUserInteractionEnabled:YES] in your init method). Then set the rect you want to interact with :
customImageView.interactRect = myView.frame;
And in your customImageView you can add something like:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [[event allTouches] anyObject];
lastPosition = [touch locationInView: self.superview];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [[event allTouches] anyObject];
CGPoint position = [touch locationInView:self.superview];
CGRect currentFrame = self.frame;
currentFrame.origin = CGPointMake(currentFrame.origin.x + position.x - lastPosition.x, currentFrame.origin.y + position.y - lastPosition.y);
if (CGRectIntersectsRect(currentFrame, interactRect) && !CGRectIntersectsRect(self.frame, interactRect))
{
NSLog(#"I'm in for the first time");
if(self.frame.origin.x + self.frame.size.width <= interactRect.origin.x && currentFrame.origin.x + currentFrame.size.width > interactRect.origin.x)
{
NSLog(#"Coming from the left");
}
if(self.frame.origin.x >= interactRect.origin.x + interactRect.size.width && currentFrame.origin.x < interactRect.origin.x + interactRect.size.width)
{
NSLog(#"Coming from the right");
}
}
self.frame = currentFrame;
lastPosition = position;
}

TouchesMoved with UITouch

I'm trying to create a simple application where you can move your UIImageView by touching him and dragging him around.
my UIImageView is called imv
-(void ) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch * touch = [touches anyObject];
if([touch view] == self.imv){
CGPoint location = [touch locationInView:self.view];
self.imv.center = location;
}
}
-(void ) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch * touch = [touches anyObject];
if([touch view] == self.imv){
CGPoint location = [touch locationInView:self.view];
self.imv.center = location;
}
}
i'am trying to solve this like whole day and i don't know what is wrong. If i disable if statement it's working else not. What can i do?
Thanks for the answers
Unless you've subclassed UIImageView (unlikely), your view is receiving the touch events.
These days it's simpler & more usual to use a UIGestureRecognizer for this kind of thing, in this case a UIPanGestureRecognizer.
e.g.
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(dragImageView:)];
[self.imv addGestureRecognizer:pan];
- (void)dragImageView:(UIPanGestureRecognizer *)dragImageView {
if(UIGestureRecognizerStateBegan == state) {
originalCenter = self.imv.center; // add CGPoint originalCenter; member
} else if(UIGestureRecognizerStateChanged == state) {
CGPoint translate = [pan translationInView:self.imv.superview];
self.imv.center = CGPointMake(originalCenter.x + translate.x, originalCenter.y + translate.y);
}
}
From a bit of experimenting, it seems that the [touch view] is returning the main UIView and not your subview, hence the problem with the if statement not working (I added the UIImageView in a storyboard xib). EDIT- it's because UIImageViews don't handle touch events by default - see here . When adding a regular UIView in the viewDidLoad seems to work as you would expect.
Anyway, this adapted version of your code works for me
-(void)moveImageForTouches:(NSSet*)touches
{
UITouch * touch = [touches anyObject];
CGPoint location = [touch locationInView:self.view];
if(CGRectContainsPoint(self.imv.frame, location))
{
self.imv.center = location;
}
}
-(void ) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
[self moveImageForTouches:touches];
}
-(void ) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self moveImageForTouches:touches];
}

How to find out what view a touch event ended at?

I wish to drag a UIImage on to one of several UIButtons and have it repositioned based on which button I drag it to.
The problem I've ran in to is that UITouch only records the view where my touch began, I'd like to access the view my touch ends at. How can I do this?
Code:
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:self.view];
dealerBtnOrigin = [touch locationInView:self.view];
//NSLog(#"%u %u",touch.view.tag, ((UIView *)[dealerBtns objectAtIndex:[table getButtonSeat]]).tag);
//CHECK TO SEE WHICH BUTTON WAS TOUCHED
if (touch.view == ((UIView *)[dealerBtns objectAtIndex:[table getButtonSeat]]))
{
((UIView *)[dealerBtns objectAtIndex:[table getButtonSeat]]).center = location;
}
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:self.view];
if (touch.view == ((UIView *)[dealerBtns objectAtIndex:[table getButtonSeat]]))
{
((UIView *)[dealerBtns objectAtIndex:[table getButtonSeat]]).center = location;
}
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:self.view];
UIView *endView = [self.view hitTest:location withEvent:nil];
if (touch.view == ((UIView *)[dealerBtns objectAtIndex:[table getButtonSeat]]))
{
NSLog(#"%u %u",endView.tag, touch.view.tag);
if([buttons containsObject:(UIButton *)endView])
{
[[dealerBtns objectAtIndex:[table getButtonSeat]] setHidden:YES];
[table passButton:touch.view.tag];
[[dealerBtns objectAtIndex: touch.view.tag] setHidden:NO];
}
((UIView *)[dealerBtns objectAtIndex:[table getButtonSeat]]).center = dealerBtnOrigin;
}
}
Use hit-testing. You know the location of this point as a CGPoint in terms of the ultimate superview, self.view. Then you can ask self.view which of its subviews that point is in:
CGPoint location = [touch locationInView:self.view];
UIView* v = [self.view hitTest:location withEvent:nil];
The UIView v is the view you're looking for.
It is very easy to detect your finally touched view, try this code
-(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);
}
}
}
In general, you need to take the point where the touch ended, and determine whether it lies within the view you're interested in. I do this using code similar to the following:
CGPoint newCenter = dragView.center;
for (UIView *v in dropTargets)
{
CGRect convertedTargetFrame = [v.superview convertRect:v.frame toView:nil];
if (CGRectContainsPoint(convertedTargetFrame, newCenter))
{
activeTargetIndex = idx;
}
}
(this code was edited on the fly to take out a lot of irrelevant stuff, but I keep a list of potential drop targets in dropTargets, and this is just looking at that list to see which of the potential UIViews might contain the point).
The essential thing is that if you know the view or views you're potentially dragging the item to, then you can determine whether that view's frame contains the point using CGRectContainsPoint. The important thing is to keep in mind they may lie in different coordinate systems and it may be necessary to convert from one to the other before your comparison.
Assuming there is a #property of the target view in your container, and the target view is added to the container:
#property (nonatomic, strong) UIView* targetView;
// ...
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
NSSet* touchesForTargetView = [event touchesForView:self.targetView];
if (touchesForTargetView.allObjects.count != 0) {
// touch was at target view
}
else {
// touch was somewhere else
}
}
swift 4:
override func touchesEnded(_ touches: Set, with event: UIEvent?) {
if let touch = touches.first{
let location = touch.location(in: self.view)
let v = touch.view
// go on..
}
}

iOS: Drag Effect not working well

I have implemented the drag effect on an image but during my test I see that the image is moving only on the click mouse event.
I cannot move my image with the mouse on my screen through the drag event. But when I click on a side of my screen the image take the place where I have clicked.
I followed many topics on youtube but finally, I haven't the same behavior.
This my code:
ScreenView1.h
IBOutlet UIImageView *image;
ScreenView1.m
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:touch.view];
image.center = location;
[self ifCollision];
}
-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
[self touchesBegan:touches withEvent:event];
}
If you want to drag an image view, you will be so much happier using a UIPanGestureRecognizer. It makes this sort of thing trivial. Using touchesBegan is so iOS 4!
UIPanGestureRecognizer* p =
[[UIPanGestureRecognizer alloc] initWithTarget:self
action:#selector(dragging:)];
[imageView addGestureRecognizer:p];
// ...
- (void) dragging: (UIPanGestureRecognizer*) p {
UIView* vv = p.view;
if (p.state == UIGestureRecognizerStateBegan ||
p.state == UIGestureRecognizerStateChanged) {
CGPoint delta = [p translationInView: vv.superview];
CGPoint c = vv.center;
c.x += delta.x; c.y += delta.y;
vv.center = c;
[p setTranslation: CGPointZero inView: vv.superview];
}
}
You're not doing the right thing in the touchesMoved:withEvent:, which is why the drag won't work. Here's a little code that works:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:self];
[CATransaction begin];
[CATransaction setDisableActions:YES];
[image setCenter:location];
[CATransaction commit];
}
For the others, I have implemented my issue in that way:
- (IBAction)catchPanEvent:(UIPanGestureRecognizer *)recognizer{
CGPoint translation = [recognizer translationInView:self.view];
recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x,
recognizer.view.center.y + translation.y);
[recognizer setTranslation:CGPointMake(0, 0) inView:self.view];
}
thank you again Matt!

Resources