Define a rectangle of locations in objective-C - ios

I have an Image in an Iphone App, I would like when a user taps a location within a defined area (range of locations or an area defined by the rectangle), it triggers another event. I know how to get a single location, But I don't know how to define a rectangular area. I am looking for a simple way to implement it. Thank you

If you want to make the rectangle visible you can add image view to your view and set up the tap recogniser. But if you don't want to make the rectangle visible you can override touchesBegan:withEvent: method and use CGRectContainsPoint:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchLocation = [touch locationInView:self.view];
CGRect rect = CGRectMake(0.0, 0.0, 100, 100); //<- this is the rectangle you do check on
if (CGRectContainsPoint(rect, touchLocation)) {
NSLog(#"You tapped inside rectangle");
}
else {
NSLog(#"You missed rectangle");
}
}

Define your area as a CGRect and get the CGPoint of the touch. Then use CGRectContainsPoint to check for a hit.
If you need to create the CGRect from a list of points then you need to iterate the points and find the max and min x and y values, then you can create the CGRect with:
CGRectMake(minX, minY, maxX - minX, maxY - minY);

Maybe you can create a UIView and add a gesture recognizer like this:
UIView *customView = [UIView new];
customView.frame = CGRectMake(....); // as Wain suggest
[self.view addSubview:customView];
UITapGestureRecognizer *tapGesture =
[[UITapGestureRecognizer alloc] initWithTarget: self
action: #selector(someMethod)];
[customView addGestureRecognizer:tapGesture];

Related

iOS: Change alpha of image view with gestures

I want to change the alpha of image with the gestures like up and down or right and left.
I don't want to use slider for that.
Is it possible to do this if yes then please tell me how or i have to use slider for that?
Thank you.
You can implement method on view or view controller
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:self];
NSLog(#"location: %#",NSStringFromCGPoint(location));
// Example:
// alpha depends on location.x related to view bounds width
CGFloat alpha = (self.bounds.size.width - location.x) / self.bounds.size.width;
NSLog(#"alpha: %#",#(alpha));
}
where you can check location.x or location.y.
Try to do like following :
First attach tap GestureRecognizer to view:
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(yourTapMethod:)];
tap.numberOfTapsRequired = 1;
tap.numberOfTouchesRequired = 1;
[imageView addGestureRecognizer:tap];
Then, in gesture recognizer handler do what do you want:
-(void)yourTapMethod{
[UIView animateWithDuration:0.5 animations:^(void){
imageView.alpha = //add any value (like 0.2f);
}

Add an image to touch location iOS

I have an app that connects points in an array with lines, what I want to do next is to add a marker to every line's end points, I chose a red dot for that. But I can't figure out how to even start. The image should appear every time the user taps the screen, because that's when a new point is created. Thanks.
The simplest solution would be to add a UITapGestureRecognizerto your view with the following method as the GR's action. Supposing you're using e.g an image asset for your dot it would be:
-(void)screenTapped:(UITapGestureRecognizer*)tap {
CGPoint tapLocation = [tap locationInView:self.view];
UIImageView *redDotImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"redDot"]];
redDotImageView.center = tapLocation;
[self.view addSubview:redDotImageView];
}
For example you can add gesture recognized to your view:
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(addDotToTapPoint:)];
[view addGestureRecognizer:tapGesture];
then implement method addDotToTapPoint: to find point of tap:
- (void)addDotToTapPoint:(UITapGestureRecognizer *)sender {
CGPoint pointOfTouch = [sender locationInView:sender.view];
//... draw circle or something
}
Second approach.
You can create your own subclass of UIView and implement method touchesBegan:withEvent:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
CGPoint pointOfTouch = [(UITouch *)[touches anyObject] locationInView:self];
//... draw circle or something
}
In both cases You will get location of touch and can draw something in that point

Is it possible to get the x and y coordinates of a touch?

is it possible to get the x and y coordinates of a touch? If so could someone please provide a very simple example where the coordinates are just logged to the console.
Using touchesBegan Event
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchPoint = [touch locationInView:self.view];
NSLog(#"Touch x : %f y : %f", touchPoint.x, touchPoint.y);
}
This event is triggered when touch starts.
Using Gesture
Register your UITapGestureRecognizer in viewDidLoad: Method
- (void)viewDidLoad {
[super viewDidLoad];
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapGestureRecognizer:)];
[self.view setUserInteractionEnabled:YES];
[self.view addGestureRecognizer:tapGesture];
}
Setting up the tapGestureRecognizer function
// Tap GestureRecognizer function
- (void)tapGestureRecognizer:(UIGestureRecognizer *)recognizer {
CGPoint tappedPoint = [recognizer locationInView:self.view];
CGFloat xCoordinate = tappedPoint.x;
CGFloat yCoordinate = tappedPoint.y;
NSLog(#"Touch Using UITapGestureRecognizer x : %f y : %f", xCoordinate, yCoordinate);
}
Sample Project
First you need to add a gesture recognizer to the view you want.
UITapGestureRecognizer *myTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(myTapRecognizer:)];
[self.myView setUserInteractionEnabled:YES];
[self.myView addGestureRecognizer:myTap];
Then in the gesture recognizer method you make a call to locationInView:
- (void)myTapRecognizer:(UIGestureRecognizer *)recognizer
{
CGPoint tappedPoint = [recognizer locationInView:self.myView];
CGFloat xCoordinate = tappedPoint.x;
CGFloat yCoordinate = tappedPoint.y;
}
You may want to take a look at apple's UIGestureRecognizer Class Reference
Here's a very basic example (place it inside your view controller):
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self.view];
NSLog(#"%#", NSStringFromCGPoint(currentPoint));
}
This triggers every time the touch moves. You can also use touchesBegan:withEvent: which triggers when a touch starts, and touchesEnded:withEvent: which triggers when a touch ends (i.e. a finger is lifted).
You can also do this using a UIGestureRecognizer, which in many cases is more practical.

Displaying a view over an imageview which is moveable

I currently have an application where a user takes a photo or chooses from their library.
On the next controller it will show the image that was selected/taken.
What I would like to do now is show a view of some sort on top of the image view. The view would be translucent round the edges and have a circle which would show the image beneath (not transulcent). Basically this is selected a part of the image.
I then need to save some how where the view is on screen, as it should also be moveable by the user.
What is the best way to approach this?
I need an overlay view which can be moved. The circle would be a fixed size always the inside shows the imageview beneath and the outside would be a 0.5 translucency so you can still see the image but not completely. Then to save the location of the moved around circle?
---- EDIT -----
This is the example image I have created.
I have a view which has a photo as the UIImageView (bottom layer). On top of this I am trying to add a view (like the picture above). Note, the picture above is actually a png as suggested. However, this overlay is moveable. The circle is transparent (0) so you can completely see the photo below it. The outer (grey) is transparent partially (0.5) so you can still see just not completely.
The top view (circle part) would be moved around on the photo to mark a specific point on the photo. In this example if the circle is moved the side (grey) ends on screen, therefore I would need to make a huge image which takes into account the moving of the view -- which is not the best way to do this surely?
EDIT 2 ----
I now have one UIImageView over the top of the photoView (another UIImageView). The overlay is 4 times the screen with a circle in the middle of it.
When the item is moved I have a gesture recognizer that runs:
-(void)handlePan:(UIPanGestureRecognizer *)gesture {
NSLog(#"Pan Gesture");
gesture.view.center = [gesture locationInView:self.view];
}
At present from the above the UIImageView is moved from the middle point, that way the circle is what looks to be moving when the finger moves.
That is all great, but how do I implement the suggested answers into my handlePan method. So I need to check that the middle point is not too close the edge. Ideally I would like a 50 margin around the screen so the circle does not look to go completely (or mostly) off screen?
I understand from the question that you know how to do the movement of the overlay, so what I meant is just that you can simply use image views big enough to make sure that their border isn't visible.
Let's say the UIImageView would be called
UIImageView *photoImageView;
And the overlay with translucent and semi-translucent areas would be
UIImageView *imageOverlayView;
The way I see it, you need 3 different images for that imageOverlayView, depending on the device it's running on - 1 for iPad, 1 for iPhone 5 and 1 for other iPhones.
Width of that image should be equal to (screen width - circle radius) * 2, height should
CGFloat circleRadius; //this would be the radius of translucent circle
So if you set the frame of the overlay properly:
CGRect imageFrame = photoImageView.frame;
imageOverlayView.frame = CGRectMake(circleRadius - imageFrame.size.width/2, circleRadius - imageFrame.size.height/2, (imageFrame.size.width - circleRadius)*2, (imageFrame.size.height - circleRadius)*2); //origin is set to the middle of the image.
you'd never see the edge of the grey area. MZimmerman6's answer for implementation of the movement is good, but you should also make sure you block the circle from getting out of the borders of underlying image.
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint new = [touch locationInView:imageOverlayView];
delX = new.x - prevPoint.x;
delY = new.y - prevPoint.y;
CGRect overFrame = imageOverlayView.frame;
overFrame.origin.x += delX;
if (overFrame.origin.x < -imageFrame.size.width) {
overFrame.origin.x = -imageFrame.size.width;
}
else if (overFrame.origin.x > 0) {
overFrame.origin.x = 0;
}
overFrame.origin.y += delY;
if (overFrame.origin.y < -imageFrame.size.height) {
overFrame.origin.y = -imageFrame.size.height;
}
else if (overFrame.origin.y > 0) {
overFrame.origin.y = 0;
}
[overlayView setFrame:overFrame];
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint new = [touch locationInView:imageOverlayView];
delX = new.x - prevPoint.x;
delY = new.y - prevPoint.y;
CGRect overFrame = imageOverlayView.frame;
overFrame.origin.x += delX;
if (overFrame.origin.x < -imageFrame.size.width) {
overFrame.origin.x = -imageFrame.size.width;
}
else if (overFrame.origin.x > 0) {
overFrame.origin.x = 0;
}
overFrame.origin.y += delY;
if (overFrame.origin.y < -imageFrame.size.height) {
overFrame.origin.y = -imageFrame.size.height;
}
else if (overFrame.origin.y > 0) {
overFrame.origin.y = 0;
}
[overlayView setFrame:overFrame];
}
EDIT
With your pan gesture recognizer, checking if you aren't going too far needs a little change to the handlePan: method.
-(void)handlePan:(UIPanGestureRecognizer *)gesture {
CGPoint newCenter = [gesture locationInView:self.view];
if (newCenter.x < 50) {
newCenter.x = 50;
}
else if (newCenter.x > self.view.frame.size.width - 50) {
newCenter.x = self.view.frame.size.width - 50;
}
if (newCenter.y < 50) {
newCenter.y = 50;
}
else if (newCenter.y > self.view.frame.size.height - 50) {
newCenter.y = self.view.frame.size.height - 50;
}
gesture.view.center = newCenter;
}
If that 50 points margin is equal to circle radius, this will make sure your circle able to touch the edges of the screen, but unable to go beyond them.
I would first initialize some UIImageView with a png image in it that will easily handle this moving frame with a hole in the center. You can the add this to your screen. Once this is done, use the touchesBegan, touchesMoved and other touch commands to find whether a user is touching that box and from that determine how far the user has moved from the previous point. Use this difference to then add or subtract values from the images current frame origin or center, and voila you have a moving box.
EDIT
In View.h
CGPoint prevPoint;
float delX;
float delY;
UIView *overlayView;
In View.m
-(void) viewDidLoad {
overlayView = [UIView alloc] initWithFrame:CGRectMake(100,100,100,100)];
[overlayView setBackgroundColor:[UIColor clearColor]];
[self.view addSubview:overlayView];
UIImageView *circImage = [[UIImageView alloc] initWithFrame:CGRectMake(0,0,overlayView.frame.width,overlayView.frame.height)];
[circImage setImage:[UIImage imageNamed:#"SomeImage.png"]];
[overlayView addSubview:circImage];
[self.view setNeedsDisplay];
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
prevPoint = [touch locationInView:overlayView];
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint new = [touch locationInView:overlayView];
delX = new.x - prevPoint.x;
delY = new.y - prevPoint.y;
CGRect overFrame = overlayView.frame;
overFrame.x += delX;
overFrame.y += delY;
[overlayView setFrame:overFrame];
[self.view setNeedsDisplay];
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint new = [touch locationInView:overlayView];
delX = new.x - prevPoint.x;
delY = new.y - prevPoint.y;
CGRect overFrame = overlayView.frame;
overFrame.x += delX;
overFrame.y += delY;
[overlayView setFrame:overFrame];
[self.view setNeedsDisplay];
}

Why a subView won't stay in the parent frame?

I have a view and inside it there's a UIImage. The image isn't static and I can move it around if I drag my finger around (using drag events) The problem is that sometimes the picture moves outside of the UIView frame. What's the appropriate way to keep it inside the parent frame bounds?
--UIViewA
--------UIViewB
--------------UIImage
--------------UIButton
I want to keep UIImage inside UIViewB
- (IBAction)myButtonSingleTap:(UIButton *)sender {
imDragging = YES;
[_myButton addTarget:self action:#selector(dragBegan:withEvent:) forControlEvents: UIControlEventTouchDown];
}
- (IBAction)myButtonDragInside:(UIButton *)sender
{
[_myButton addTarget:self action:#selector(draging:withEvent:) forControlEvents: UIControlEventTouchDragInside];
}
- (void)dragBegan:(UIControl *)c withEvent:ev {
UITouch *touch = [[ev allTouches] anyObject];
startingTouchPoint = [touch locationInView:self.view];
}
- (void)draging:(UIControl *)c withEvent:ev {
UITouch *touch = [[ev allTouches] anyObject];
currentTouchPoint = [touch locationInView:self.view];
_movingPic.frame = CGRectMake(currentTouchPoint.x, currentTouchPoint.y, 28, 23);
}
You will need to check the location of the view during the dragging.
At some point you will be setting the frame of the image depending on the user's drag direction, etc...
During this you should have a logic check like...
If new location x value is less than 0 then set new location x = 0.
If new location x value plus image width is greater than view width then set new location x = view width - image width.
etc...
Then use the new location as the point to move the image to.
Try adding the touch recogniser to the parent view and not the entire view
Before setting the new frame, make sure it is contained by the moving view's superview's bounds.
- (void)draging:(UIControl *)c withEvent:ev
{
UITouch *touch = [[ev allTouches] anyObject];
currentTouchPoint = [touch locationInView:self.view];
CGRect newFrame = CGRectMake(currentTouchPoint.x, currentTouchPoint.y, 28, 23);
newFrame.x = MAX(newFrame.x, 0);
newFrame.y = MAX(newFrame.y, 0);
newFrame.x = MIN(newFrame.x, _movingPic.superview.bounds.size.width - 28);
newFrame.y = MIN(newFrame.y, _movingPic.superview.bounds.size.height - 23);
_movingPic.frame = newFrame;
}

Resources