i want to show up images in my view and add the tap gesture to do some stuff.
My code looks like this for the image creation
for(int i = 0; i < 5; i++) {
UIImageView *imageToMove =
[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"icon1.png"]];
imageToMove.frame = CGRectMake(((float)rand() / RAND_MAX) * 1024, ((float)rand() / RAND_MAX) * 768 , 95, 95);
[imageToMove setUserInteractionEnabled:YES];
[imageToMove addGestureRecognizer:singleTap];
[self.view addSubview:imageToMove];
}
and this simple function to get some feedback when a image is tapped
- (void)tapDetected {
NSLog(#"single Tap on imageview");
}
My Problem is, only one (IMHO the last one added) image is touchable. The other images "behind" can't be accessed.
Is there a possibility to solve this?
It is not entirely clear what you would like to do when tapping on stacked images (I mean, the natural thing would be that the image you touch can move, and this is should be accomplished by your code); in any case, try with:
singleTap.cancelsTouchesInView = NO;
This will make your gesture recognizers not cancel the tap they handle, so the holding view will also receive the events. If this does not help, have a look at the UIGestureRecognizerDelegate protocol and specifically at the method
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer*)otherGestureRecognizer
which should allow to fine-control how your gesture recognizers co-exist.
Related
I have searched a lot but not able to find anything fruitful.Here is my scenario:
I am making a horizontal Image Slider(UIScrollView) which consist of multiple images.
The slider is working fine.
But the problem arises when I implement Pinch-In Zoom-In-Out`.
I am using this delegate method to zoom a particular Image:
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return imgView;
}
Whenever I zoom-In any image the Image next to it changes its position and the image which I am zooming after I leave my finger the image slighly shift to left and top . It not stoping where I want to stop.
What I have Done: Programatically created image and added them to scrollView.
xPointer = 0;
for(i=0;i<[imgArr count];i++)
{
UIImageView *imgToZoom= [[UIImageView alloc]init];
imgToZoom.image = [imgArr objectAtIndex:i];
imgToZoom.tag = i+100;
imgToZoom.frame = CGRectMake(xPointer, _imagesScrollView.frame.origin.y-10, self.view.frame.size.width,_imagesScrollView.frame.size.height/2);
[imgToZoom setUserInteractionEnabled:YES];
[imgToZoom setMultipleTouchEnabled:YES];
[_imagesScrollView addSubview:imgToZoom];
xPointer = xPointer+self.view.frame.size.width;
}
_imagesScrollView.contentSize = CGSizeMake(xPointer, _imagesScrollView.frame.size.height);
How can I implement Pinch In zoom. As When I done it using apple Doc My other images are changing there position.And Zoom in also not to the point.
I have multiple controllers in my PageViewController and in one controller I have a few sliders. Now there is a problem that user must touch exactly slider circle (I am not sure about right expression, thumb? - that moving part) and I would like to increase area in which reacts slider and not the whole PageViewController. I tried these solutions but it doesn't help:
thumbRectForBounds:
- (CGRect)thumbRectForBounds:(CGRect)bounds trackRect:(CGRect)rect value:(float)value
{
return CGRectInset ([super thumbRectForBounds:bounds trackRect:rect value:value], 15, 15);
}
Increase hitTest area:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
if (CGRectContainsPoint(CGRectInset(self.frame, 200, 200), point) || CGRectContainsPoint(CGRectInset(self.frame, 200, 200), point)) {
return self;
}
return [super hitTest:point withEvent:event];
}
I have these methods in my custom slider class because I would like to reuse this. Last thing what I found and not tried yet is create some object layer over slider which "takes" gesture and disable PageViewController but I am not sure how to do it and I am not sure if it's good/best solution.
I am not a big fan of the UISlider component because as you noticed, it is not trivial to increase the hit area of the actual slider. I would urge you to replicate the UISlider instead using a pan gesture for a much better user experience:
i. create a slider background with a seperate UIImageView with a slider image.
ii. create the PanGesture:
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePan:);
[imageView addGestureRecognizer:pan];
iii. implement handlePan Method:
- (IBAction)handlePan:(UIPanGestureRecognizer *)recognizer {
//pan (slide) begins
CGPoint translation = [recognizer locationInView:self.view];
translation.y = self.slideImage.center.y;
self.slideImage.center = translation;
if(recognizer.state == UIGestureRecognizerStateEnded) {
LTDebugLog(#"\n\n PAN, with spot: %f\n\n", self.slideImage.center.x);
//do something after user is done sliding
}
}
The big benefit of this method is that you will have a much better user experience as you can make the responsive UIImageView as big as you want.
Alternatively, you could subclass a UISlider and increase the hit space there, although in my experience this gives mixed results.
Hope this helps
In your CustomSlider class override thumbRectForBounds method:
Simply return rect value as you required:
- (CGRect)thumbRectForBounds:(CGRect)bounds trackRect:(CGRect)rect value:(float)value
{
return CGRectMake (bounds.origin.x, bounds.origin.y, yourWidthValue, yourHeightValue );
}
Change yourWidthValue and yourHeightValue as per your requirement. And then while using
Create object like below:
CustomSlider *slider = [[CustomSlider alloc] initWithFrame:CGRectMake(0, 0, 300, 20)];
[slider thumbRectForBounds: slider.bounds trackRect:slider.frame value:15.f]; // change values as per your requirements.
Hope this helps.
Create a custom thumb image which has a large empty margin and set that on your slider, like this:
[theSlider setThumbImage:[UIImage imageNamed:#"slider_thumb_with_margins"] forState:UIControlStateNormal];
To make the image, get a copy of the system thumb image using any one of a number of UIKit artwork extractors (just search the web for one). Open the thumb image in Photoshop and increase the canvas size by twice the margin you want to add. Make sure you change the canvas size and not the image size, as the image size will stretch the image to fill the new size. This will put empty space around the thumb which will be part of the hit-test area but since it is all transparent it won't change the look of the slider.
I'm working on an app in which you add different images from gallery to the view you can drag them around and if you press long on an image it should delete it. The new imported image is placed in a CGRect and then the functionality of drag and longpress is applied to it.
My question is from my delete code, deletion is working but it only delete the last inserted image.
self.myImageView = [[Draggable alloc]initWithFrame:cellRectangle];
[self.myImageView setImage:self.myImage];
[self.myImageView setUserInteractionEnabled:YES];
[self.myImageView setTranslatesAutoresizingMaskIntoConstraints:YES];
[self.myImageView setPreservesSuperviewLayoutMargins:YES];
[self.customCam addSubview:self.myImageView];
This code is allocating draggable class to a UIImageView which is used to drag the image around the screen. Below is the long press gesture code:
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(activateDeletionMode:)];
longPress.delegate = self;
longPress.minimumPressDuration = 1.0;
[self.myImageView addGestureRecognizer:longPress];
and activateDeletionMode code is below
- (void)activateDeletionMode:(UILongPressGestureRecognizer *)sender
{
if (sender.state == UIGestureRecognizerStateBegan)
{
[self.myImageView removeFromSuperview];
NSLog(#"This Runs");
}
}
With only one image inserted it works fine. But if I insert 2 images at the same time it delete the latest inserted image and didn't perform the removeFromSuperviewon second image.
You should add a new longpress gesture for every imageView.
In iPad when you put your finger outside top or bottom edge of screen and then drag it on screen a menu is revealed. How can I implement that?
There is specifically a Gesture Recogniser class for this, introduced in iOS 7. It's the UIScreenEdgePanGestureRecognizer. The documentation for it is here. Check it out.
To test this in the simulator, just start the drag from near the edge (~15 points).
Also, you will have to create a gestureRecognizer for each edge. You can't OR edges together, so UIRectEdgeAll won't work.
There is a simple example here. Hope this helps!
Well you can do something like this, this example is the case where you want you pan gesture to work only when the user swipes 20px inside from the right hand side of the screen
First of all add the gesture to your window
- (void)addGestures {
if (!_panGesture) {
_panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePanGesture:)];
[_panGesture setDelegate:self];
[self.view addGestureRecognizer:_panGesture];
}
}
After adding the check whether the touch you recieved is a pan gesture and then perform your action accordingly
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
CGPoint point = [touch locationInView:self.view];
if (gestureRecognizer == _panGesture) {
return [self slideMenuForGestureRecognizer:gestureRecognizer withTouchPoint:point];
}
return YES;
}
Here is how you can check whether your touch is contained in the region where you want it to be
-(BOOL)isPointContainedWithinBezelRect:(CGPoint)point {
CGRect leftBezelRect;
CGRect tempRect;
//this will be the width between CGRectMaxXEdge and the screen offset, thus identifying teh region
CGFloat bezelWidth =20.0;
CGRectDivide(self.view.bounds, &leftBezelRect, &tempRect, bezelWidth, CGRectMaxXEdge);
return CGRectContainsPoint(leftBezelRect, point);
}
I have a UIView with two gesture recognizers. Both recognize tap with two fingers: one for the upper half of the screen, the other for the bottom of the screen.
In that UIView, I have 4 buttons that cover the entire screen (each button is a quarter of the screen).
I'm using the gesture recognizer to detect when the user presses 2 buttons at the same time, and I still want to recognize the normal touches on the buttons.
I've setup everything, and it works fine. However, when pressing with just one finger the shadow on the button appears on Touch Up, and not on Touch Down. And it feels weird. I've tried to change delaysTouchesBegan with no success.
Is there a way to have both behaviours? Detect the touches with two fingers, but have a "normal behaviour" when there's only one finger? Otherwise, can I force the pressed state of a UIbutton?
Here's how I setup my gestures :
-(void)initGestureRecognition{
handClapTapGestureRecognizer = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(handClapDetected:)];
handClapTapGestureRecognizer.numberOfTouchesRequired = 2;
handClapTapGestureRecognizer.numberOfTapsRequired = 1;
handClapTapGestureRecognizer.cancelsTouchesInView = YES;
[self.gestureRecognitionView addGestureRecognizer:handClapTapGestureRecognizer];
handClapTapGestureRecognizer.delegate = self;
jumpTapGestureRecognizer = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(jumpDetected:)];
jumpTapGestureRecognizer.numberOfTouchesRequired = 2;
jumpTapGestureRecognizer.numberOfTapsRequired = 1;
jumpTapGestureRecognizer.cancelsTouchesInView = YES;
[self.gestureRecognitionView addGestureRecognizer:jumpTapGestureRecognizer];
jumpTapGestureRecognizer.delegate = self;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
return NO;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
if ([gestureRecognizer isEqual:handClapTapGestureRecognizer] && [touch locationInView:self.view].y > self.view.frame.size.height/2)
return NO;
if ([gestureRecognizer isEqual:jumpTapGestureRecognizer] && [touch locationInView:self.view].y < self.view.frame.size.height/2)
return NO;
return YES;
}
I know my problem is similar to that one : UIButton inside a view that has a UITapGestureRecognizer but the difference is that in my case, the behaviour is ok, and I'm just trying to get the shadow on the button on Touch DOwn, rather than on Touch Up.
Thanks
Could you manually set [button setHighlighted:YES] when the tap gesture is first recognized and its location matches that of the button's, and then to NO when the gesture ends?