I'm trying to move a UIView (let's call it viewA), which is located on top of another UIView (let's call it viewB). viewB has the size of the iPad screen, and view A is much much smaller.
I manage to move things, but the whole screen moves (viewA + viewB), not only viewA.
Here is my code for viewA class:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchLocation = [touch locationInView:self->view];
if (CGRectContainsPoint(self.window.frame, touchLocation)) {
dragging = YES;
oldY = touchLocation.y;
}
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchLocation = [touch locationInView:self->view];
if (dragging) {
CGRect frame = self.window.frame;
frame.origin.y = self.window.frame.origin.y + touchLocation.y - oldY;
self.window.frame = frame;
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
dragging = NO;
}
What I do not understand, is that, I implemented these methods in the viewA class. "Self" should concern this viewA, right? So why does the whole page move when my finger move on the screen?
You are moving the entire window, which contains all the views, you should only move the view you want, viewA in your case.
Related
I have a UIScrollview (With image) in UIView (Red color).
UIView - {0,0, 320, 236} UIScrollview - {0, 8, 300, 220}
In my uiview, I got touches.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{}
I need to transfer touch from UIView to UIScrollview. (e.g if user swipe from right side of uiview to left, uiscrollview should scroll to left in sync with user touch). May I know how to do?
The idea is to get a reference to your scrollView inside your UIView, calculate the x touches delta and adjust the contentOffset property of the scrollView accordingly.
So, in your UIView class:
#implementation MyView{
CGPoint _startPosition;
CGPoint _previousPosition;
}
Initialize the above variables in your
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
_startPosition = [touch locationInView:self];
_previousPosition = _startPosition;
}
Then in your touchesMoved:
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [touches anyObject];
CGPoint currentPosition = [touch locationInView:self.scrollView];
if(!CGPointEqualToPoint(_previousPosition, _startPosition)){
CGFloat deltaX = _previousPosition.x-currentPosition.x;
[UIView animateWithDuration:0.1 animations:^{
//
self.scrollView.contentOffset = CGPointMake(self.scrollView.contentOffset.x +
deltaX, self.scrollView.contentOffset.y);
}];
}
_previousPosition = currentPosition;
}
The scrollView.contentOffset is adjusted in an animation block to make the scroll smooth.
Link to a working project: https://github.com/sliaquat/stack_overlfow_answer_28036976
hey guys i was wondering if there was away to make an object like a UIImageView draggable. I am aware of the UITouch and touches i.e.
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *drag=[[event allTouches] anyObject];
player.center=[drag locationInView:self.view];
}
but in this way it is possible for the user to make the object jump across the screen to where he or she touches the screen but i want the user to have to manually drag the object across the screen.
please explain with code and let me know if i have to be more specific or clear...
You can do this:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *aTouch = [touches anyObject];
CGPoint location = [aTouch locationInView:self.view];
if(CGRectContainsPoint(self.playerView.frame,location)) {
[UIView beginAnimations:#"Dragging A DraggableView" context:nil];
self.playerView.center = location;
[UIView commitAnimations];
}
}
This should give you a smooth animation.
if you want your user to drag&drop, first you have to check if the touch is inside the imageview rect frame. To improve the user experience, you can detect the touch offset from the imageview center; a good place to do this is inside the touchesBegan:withEvent:. After that, you have to change the position of the imageview, like this:
CGPoint touchOffset; //insert this inside your interface private iVars
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *drag=[[event allTouches] anyObject];
CGPoint touchLocation = [drag locationInView:self.view];
touchOffset = CGPointMake(player.center.x-touchLocation.x,player.center.y-touchLocation.y)
if(CGRectContainsPoint(player.frame,touchLocation)
player.center = CGPointMake(touchLocation.x+touchOffset.x,touchLocation.y+touchOffset.y);
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *drag=[[event allTouches] anyObject];
CGPoint touchLocation = [drag locationInView:self.view];
if(CGRectContainsPoint(player.frame,touchLocation)
player.center = CGPointMake(touchLocation.x+touchOffset.x,touchLocation.y+touchOffset.y);
}
P.S. - Next time try to search similar questions...
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch* aTouch = [touches anyObject];
UIView* aView = [aTouch view];
if (aView != self.view) {
[self.view bringSubviewToFront:aView];
}
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch* aTouch = [touches anyObject];
UIView* aView = [aTouch view];
if (aView != self.view) {
aView.center = [aTouch locationInView:self.view];
}
}
I created a very simple app that contains a draggable UIImageView but I faced a problem that the image can be dragged without touching it. I'm sure that the hole issue is from anyObject but I have no idea how to replace it I tried self.view.image but it failed. So here's my code
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:touch.view];
lineView.center = location;
}
-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
[self touchesBegan:touches withEvent:event];
}
any ideas?
Consider using a pan gesture recogniser. Add it only to the image view (and enable user interaction on the view). Now you will only get action method callbacks from the gesture when the view has actually been touched, your code becomes simpler, and you can move the view with that position.
Also, in your current code, it's weird to call touchesBegan: from touchesMoved:. If you keep that code (because you don't want to use a gesture), you should refactor the code that moves the view out into a different method and have both touchesBegan: and touchesMoved: call that method.
Try the following
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:touch.view];
if ([lineView pointInside:location withEvent:event])
lineView.center = location;
}
I would like to be able to retrieve info on a tap, about all the different subviews that are placed in that tap spot. For example, if there was a background, and in front of it was a game character, I would like to be able to tap on that character, and it will retrieve the info saying that both the character and the background are in that tap spot.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//retrieve info about what other subviews lie behind at this point
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch=[touches anyObject];
CGPoint p=[touch locationInView:self.view];
NSLog(#"Coordiantes of Tap Point:(%f,%f)", p.x, p.y);
NSArray *anArrayOfSubviews = [self.view subviews];
NSMutableArray *requiredSubviewArray = [NSMutableArray array];
for (UIView *aSubView in anArrayOfSubviews){
if(CGRectContainsPoint(aSubView.frame, p)) {
//aSubView is there at point 'p'
[requiredSubviewArray addObject:aSubView];
}
}
// requiredSubviewArray contains all the Subviews at the Tap Point.
}
try this.it maybe helpful to you..
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//retrieve info about what other subviews lie behind at this point
NSLog(#"subviews--%#",[self.view subviews]); //it prints all subviews as Array
NSLog(#"superview--%#",[self.view superview]); //it prints superview of your view
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject]; // here you get all subviews on ur touchpoint
if ([touch view] == imageView) {
CGPoint location = [touch locationInView: self.view];
imageView.center = location;
}
}
/// To check both views are in one spot, use this
// CGRectContainsRect() and CGRectIntersectsRect().
You can try this one..
You can get all subviews if you use [self.view subviews]. You can compare those views frames with touch location.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
CGPoint touchLocation = [touch locationInView:self.view];
startX = touchLocation.x;
startY = touchLocation.y;
for (UIView *view in [self.view subviews]){
//Here you can compare each view frame with touch location
}
}
The code below is based on the idea of how to make a UIImageView be able to be dragged around the ViewController. When I use this code however, I click on a different location instead of pressing on the Image and it teleports to that location instead of requiring me to always drag the image. I want the code below to only work when pressing on that specific image. Please Help-
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:touch.view];
image.center = location;
[self ifCollided];
}
-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
[self touchesBegan:touches withEvent:event];
}
It's teleporting simply because you don't have any check for whether the user has in fact touched the image, so any touch causes the image to jump to that location. What you need to do is check if the user has touched the image, then move it only if they have. Try the following code in the ViewController, assuming 'image' is the draggable view:
You'll need to create a variable/property on your ViewController to track if the view is being dragged. If you need just one image, you can use a BOOL (the code below assumes you've done this, called isDragging).
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:image];
if([image pointInside:location withEvent:event]) {
isDragging = YES;
}
}
-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesMoved:touches withEvent:event];
if(isDragging)
{
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:self.view];
image.center = location;
[self ifCollided];
}
}
-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesEnded:touches withEvent:event];
isDragging = NO;
}
This code basically does a check in touchesBegan and sets the property to true if you touch inside the image, moves it in touchesMoved if your initial touch was on the image, and finally unsets the check in touchesEnded.