iOS - How To Draw Point On A Line In Which The User Touches When Dragging - ios

I have a rectangular view which contains vertical thin lines in which I drew programatically.
This is the code I used to draw the lines:
- (void)drawLines
{
CGFloat spacing = _bgView.frame.size.width / 11.0f;
for(int i = 1; i < 11; i++)
{
UIView *line = [[UIView alloc] initWithFrame:CGRectMake((CGFloat)(i * spacing), 0, 1, _bgView.frame.size.height)];
line.backgroundColor = [UIColor whiteColor];
line.tag = i;
[_bgView addSubview:line];
}
}
The lines are separated by equally distributed spaces calculated from the width of the rectangular view(_bgView).
Here's an overview of what it looks like:
When the user performs a drag in the rectangular view, and when his/her finger passes through or touches a line, a dot will be drawn on that specific point.
Here's the code that detects the point of touch of the user on the line, and draws a dot on that point.
- (IBAction)drawDots:(id)sender
{
UIPanGestureRecognizer *pan = (UIPanGestureRecognizer *)sender;
CGPoint pannedPoint = [pan locationInView:_bgView];
for (UIView *subview in _bgView.subviews)
{
if (CGRectContainsPoint(subview.frame, pannedPoint) && subview.tag > 0)
{
NSLog(#"Point x:%.2f y:%.2f TAG:%i", pannedPoint.x, pannedPoint.y, subview.tag);
UIView *point = [[UIView alloc] initWithFrame:CGRectMake(pannedPoint.x - 2.5, pannedPoint.y - 2.5, 5, 5)];
point.backgroundColor = [UIColor redColor];
[_bgView addSubview:point];
}
}
}
Now, if the user pans really fast, this will be the result:
As can be seen, only some points are drawn, that's why there are a lot of missing dots on the other lines.
This should be expected result:
But, this happens only when the user pans super slow.
How can I draw the points in the lines intercepted by the touch of the user even if his finger moved really fast?
Thanks!

Instead of pan gestures you should use UIResponder methods to detect user touches:
- touchesBegan:withEvent:
- touchesMoved:withEvent:
- touchesEnded:withEvent:
- touchesCancelled:withEvent:
The second method - touchesMoved:withEvent: calls when user keeps moving its finger through the screen, so you can get its finger location:
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchLocation = [touch locationInView:touch.view];
Then just add your detection logic.
Check the docs for more details:
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIResponder_Class/

please refer this code
for your requirement
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
// NSLog(#"DEBUG: Touches moved" );
[super touchesMoved:touches withEvent:event];
if ([[event allTouches] count] > 1) {
} else {
UITouch *touch = [[event allTouches] anyObject];
UIView *view = touch.view;
NSLog(#"DEBUG: Touches Moved");
CGPoint location = [touch locationInView:self.bgView];
for (UIView *subview in _bgView.subviews)
{
if (CGRectContainsPoint(subview.frame, location) && subview.tag > 0) {
NSLog(#"Point x:%.2f y:%.2f TAG:%i", location.x, location.y, subview.tag);
UIView *point = [[UIView alloc] initWithFrame:CGRectMake(location.x - 2.5, location.y - 2.5, 5, 5)];
point.backgroundColor = [UIColor redColor];
[_bgView addSubview:point];
}
}
}
}
Will help you

Related

How to move array of UIImageViews smoothly?

Am working on kind of seating arrangement application. Where the app allows the admin to arrange the seatings by click and move the each seat and then save the seating arrangement with frame sizes of each seat. I tried by loading 5 UIImageView on custom view and move the imageview but, only one imageview is getting moved. Rest of the imageviews not getting moved. Can you please help me on this?
- (void) addSeatsToTheView {
for (int i=0; i<5; i++) {
self.hotelImage = [[UIImageView alloc] initWithFrame:CGRectMake(5, 5, 50, 50)];
self.hotelImage.image = [UIImage imageNamed:#"DiningIcon"];
self.hotelImage.userInteractionEnabled = YES;
[self.hotelImage setUserInteractionEnabled:YES];
self.hotelImage.tag = i;
[self.hotelView addSubview:self.hotelImage];
}
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
if (touch.view == self.hotelImage) {
CGPoint location = [touch locationInView:self.hotelView];
NSLog(#"Begen Touch Location: %#", NSStringFromCGPoint(location));
self.hotelImage.frame=CGRectMake(location.x, location.y, 50, 50);
}
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
if (touch.view == self.hotelImage) {
CGPoint location = [touch locationInView:self.hotelView];
NSLog(#"Begen Touch Location: %#", NSStringFromCGPoint(location));
self.hotelImage.frame=CGRectMake(location.x, location.y, 50, 50);
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
if (touch.view == self.hotelImage) {
CGPoint location = [touch locationInView:self.hotelView];
NSLog(#"Begen Touch Location: %#", NSStringFromCGPoint(location));
self.hotelImage.frame=CGRectMake(location.x, location.y, 50, 50);
}
}
Once the admin arranged the seatings we have to save all the visible uiimageview framesizes. Thanks.
Edited:
I tried the using UIPanGestureRecognizer but, only one imageview getting moved. Don't know where am doing wrong? Can you please help me? Thanks.
- (void) addSeatsToTheView {
for (int i=0; i<5; i++) {
self.hotelImage = [[UIImageView alloc] initWithFrame:CGRectMake(5, 5, 50, 50)];
self.hotelImage.image = [UIImage imageNamed:#"DiningIcon"];
self.hotelImage.userInteractionEnabled = YES;
[self.hotelImage setUserInteractionEnabled:YES];
self.hotelImage.tag = i;
UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(gestureRecognizerMethod:)];
[self.hotelImage addGestureRecognizer:panGestureRecognizer];
[self.hotelView addSubview:self.hotelImage];
}
}
- (void)gestureRecognizerMethod:(UIPanGestureRecognizer *)recogniser
{
if (recogniser.state == UIGestureRecognizerStateBegan || recogniser.state == UIGestureRecognizerStateChanged)
{
CGPoint touchLocation = [recogniser locationInView:self.hotelView];
self.hotelImage.frame = CGRectMake(touchLocation.x, touchLocation.y, 50, 50);
}
}
Don't use touches methods for this; you'll go insane. Make each image view user-interactive and give it a UIPanGestureRecognizer. There is standard code for the pan gesture recognizer's action handler for following a finger, i.e. making the view draggable.
Once you've done that, everything stems from your misuse of self.hotelImage. Get rid of it entirely. In your for loop, just use a local variable, UIImageView* hotelImage = .... In the gesture recognizer method, use [recogniser view] to refer to the image view to which this gesture recognizer is attached. Everything will sort itself out after that!

Slide out viewcontroller from right of screen

I want to create a slide out menu from the right of my main view controller. However I want the slide out menu to appear on top of the main view and not push it to one side.
I've looked at ECSlidingViewController 2 and it allows sliding out from either side, however the slide out menus appear cut off on the exposed edges. It creates the effect of the top view controller moving left or right to reveal the hidden menu under it. I want it to appear that the hidden menu sliding out is going onto of the main view controller and that we can see its left edge so no content is cut off.
Is this at all possible and would ECSlidingViewController 2 work for this?
Edit
This is what I have tried:
To detect the touch started:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
BBAppDelegate *myAppDelegate = (BBAppDelegate*)[UIApplication sharedApplication].delegate;
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchLocation = [touch locationInView:self.view];
NSArray *myViewArray = [[NSBundle mainBundle] loadNibNamed:#"FilterView" owner:self options:nil];
self.filterView = myViewArray[0];
[myAppDelegate.window addSubview:self.filterView];
if (CGRectContainsPoint(self.filterView.frame, touchLocation)) {
dragging = YES;
oldX = touchLocation.x;
oldY = touchLocation.y;
}
}
And then dragging:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchLocation = [touch locationInView:self.view];
if (dragging) {
CGRect frame = self.filterView.frame;
frame.origin.x = self.filterView.frame.origin.x + touchLocation.x;
frame.origin.y = self.filterView.frame.origin.y + touchLocation.y;
self.filterView.frame = frame;
}
}
However, when I start a touch, the filterView replaces all views and doesn't slide or animate in anyway. I though it was due to not providing a starting point - so I instated self.filterView like so:
self.filterView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 120, 564)];
However changing these values have no effect on the position / size of the view when its displayed.
Edit 2
Okay, I started a new project for testing and managed to get a view on screen to move around by following my touches.
I am using UIPanGestureRecognizer
Like so:
viewDidLoad
- (void)viewDidLoad
{
[super viewDidLoad];
NSArray *myViewArray = [[NSBundle mainBundle] loadNibNamed:#"View" owner:self options:nil];
UIView *myView = myViewArray[0];
self.filterView = myView;
self.filterView.frame = CGRectMake(100, 100, 200, 200);
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget:self
action:#selector(dragging:)];
pan.delegate = self;
[self.filterView addGestureRecognizer:pan];
[self.view addSubview:self.filterView];
}
Then in the dragging method:
-(void)dragging:(UIPanGestureRecognizer *)gesture
{
if(gesture.state == UIGestureRecognizerStateBegan)
{
NSLog(#"Received a pan gesture");
self.panCoord = [gesture locationInView:gesture.view];
}
CGPoint newCoord = [gesture locationInView:gesture.view];
float dX = newCoord.x-self.panCoord.x;
gesture.view.frame = CGRectMake(gesture.view.frame.origin.x+dX, gesture.view.frame.origin.y, gesture.view.frame.size.width, gesture.view.frame.size.height);
}
This allows the view to move horizontally only.
Almost there - what I am trying to figure out now is getting it to snap to a location when the user lifts their finger. And how to move this view when its start position is off screen.
Edit 3
Okay, so I wanted to control the speed and velocity of the view coming out onto screen. If the user swipes quickly, the view goes into place at the speed they swipe. If they swipe slowly, it goes into place slowly. However I also set the lowest time - so if they take a long time - it defaults to the min amount.
Here is the code:
{
float start;
float end;
NSDate *methodStart;
NSDate *methodEnd;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
methodStart = [NSDate date];
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:touch.view];
start = location.x;}
-(void)dragging:(UIPanGestureRecognizer *)gesture{
if(gesture.state == UIGestureRecognizerStateBegan)
{
self.panCoord = [gesture locationInView:gesture.view];
}
CGPoint newCoord = [gesture locationInView:gesture.view];
float dX = newCoord.x-self.panCoord.x;
gesture.view.frame = CGRectMake(gesture.view.frame.origin.x+dX, gesture.view.frame.origin.y, gesture.view.frame.size.width, gesture.view.frame.size.height);
if (gesture.state == UIGestureRecognizerStateEnded){
methodEnd = [NSDate date];
NSTimeInterval executionTime = [methodEnd timeIntervalSinceDate:methodStart];
double time = executionTime;
float distance = start - end;
int distanceOverTime = distance / time;
float veloticty = distanceOverTime / 100;
double miniTimeToUse = 0.5;
double newMinTime;
if (time < miniTimeToUse){
newMinTime = miniTimeToUse;
}else {
newMinTime = time;
}
if (gesture.view.frame.origin.x+dX >= 180){
[UIView animateWithDuration:newMinTime
delay:0
usingSpringWithDamping:0.9
initialSpringVelocity:veloticty
options:0
animations:^{
self.filterView.frame = CGRectMake(300, 100, 200, 200);
} completion:nil];
}
if (gesture.view.frame.origin.x+dX <= 181){
[UIView animateWithDuration:newMinTime
delay:0
usingSpringWithDamping:0.9
initialSpringVelocity:veloticty
options:0
animations:^{
self.filterView.frame = CGRectMake(50, 100, 200, 200);
} completion:nil];
}
}
}
Now just to get it to work on pulling the view off from the side.

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];
}

Detect objects, touchesmoved and UITouch

I have a UIView on where i add balls with a ID. When i touch the ball with the ID 1 i draw a dashed line follows my finger.
The problem if when i move the finger to the other balls, i don't know how to detect these balls and check the ID they have. The what i need to happen is when i touch the next ball with the ID 2, the line finish draw and stay from ball 1 to ball 2, and create new one from 2 to finger, next.. 3 etc...
The code:
#import "DrawView.h"
#implementation DrawView
- (id)init
{
self = [super initWithFrame:CGRectMake(0, 0, 1024, 768)];
if (self) {
self.backgroundColor = [UIColor clearColor];
self.opaque = YES;
checkPointCircle = [[CheckPointCircle alloc] initWithPosX:315 posY:138 andNumber:1];
checkPointCircle.userInteractionEnabled = YES;
[self addSubview:checkPointCircle];
checkPointCircle = [[CheckPointCircle alloc] initWithPosX:706 posY:138 andNumber:2];
checkPointCircle.userInteractionEnabled = YES;
[self addSubview:checkPointCircle];
checkPointCircle = [[CheckPointCircle alloc] initWithPosX:315 posY:526 andNumber:3];
checkPointCircle.userInteractionEnabled = YES;
[self addSubview:checkPointCircle];
checkPointCircle = [[CheckPointCircle alloc] initWithPosX:706 posY:526 andNumber:4];
checkPointCircle.userInteractionEnabled = YES;
[self addSubview:checkPointCircle];
}
return self;
}
- (Line *)drawLine {
return drawLine;
}
- (void)setDrawLine:(Line *)line
{
drawLine = line;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CheckPointCircle * checkTouch = (CheckPointCircle *)touch.view;
if (touch.view.class == checkPointCircle.class) {
if ([checkTouch getObjectID] == 1) {
startTouchPoint = CGPointMake([checkTouch center].x, [checkTouch center].y);
endTouchPoint = [touch locationInView:self];
}
}
self.drawLine = [[Line alloc] initWithPoint:[touch locationInView:self]];
[self setNeedsDisplay];
}
-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(#"Cancelado");
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
UITouch *secondaryTouch = (UITouch *)[[[event touchesForView:checkPointCircle] allObjects] objectAtIndex: 0];
NSLog(#"Que toco: %# ", secondaryTouch.view);
if (touch.view.class == checkPointCircle.class) {
CheckPointCircle * checkTouch = (CheckPointCircle *)touch.view;
if ([checkTouch getObjectID] == 1) {
endTouchPoint = [touch locationInView:self];
}
}
[self setNeedsDisplay];
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CheckPointCircle * checkTouch = (CheckPointCircle *)touch.view;
if (touch.view.class == checkPointCircle.class) {
if ([checkTouch getObjectID] == 1) {
endTouchPoint = [touch locationInView:self];
}
}
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect
{
[drawLine drawLineFrom:startTouchPoint to:endTouchPoint];
}
#end
How to detect the other balls to get the ID.
Can anybody help me?
Thanks!
The Apple documentation of class UIView (https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/UIView/UIView.html#//apple_ref/occ/instm/UIView/hitTest:withEvent:) lists two methods which will determine which view contains a hit/point:
– hitTest:withEvent:
– pointInside:withEvent:
Probably hitTest will help most: Its description reads "Returns the farthest descendant of the receiver in the view hierarchy (including itself) that contains a specified point.", so it even converts coordinates as needed.
If you check [self hitTest: [touch.locationInView self] withEvent: event] (or similar, no code completion here ;-)= in your touchesMoved: method, you should be able to detect when the finger is over any of the other circles.
Hope this helps, nobi

draw a vertical line where the screen was tapped

I want to draw a vertical line on the place where the screen was tapped. Because the average finger is wider than 1 pixel wide I want to do this "in steps". So basically, the line can only be drawn every 25px. And I want to figure out the nearest location where I could draw a line.
For example if the finger tapps 30 pixels from the left side of my upper view, I want to draw a vertical line 25 pixels from the left side of the view. If the screen is tapped 40 pixels from the left, i want the line drawn 50 pixels from the left side. (So there can only be one line every 25 pixels and and I want to draw the nearest one.
Any idea how I could do this?
Drawing the line is easy:
UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(100.0, 0.0, 1, 320.0)];
lineView.backgroundColor = [UIColor whiteColor];
[parentView addSubview:lineView];
But I have no idea how to find where the user tapped the screen.
To choose the nearest vertical line aligned to 25-point boundaries use this to calculate the correct x-value:
CGFloat spacing = 25.0f;
NSInteger lineNumber = (NSInteger)((touchPoint.x + (spacing / 2.0f)) / spacing);
CGFloat snapX = spacing * lineNumber;
Here's what happens in the code above:
Add half of the spacing value onto the touch point - this is because the 'snap' process in the next step will always find the previous line, so by adding half of the spacing value we ensure it will 'snap' to the nearest line.
Calculate the line number by dividing by the spacing and casting the value into an integer. This truncates the fractional part of the result so we now have the integer line number (0, 1, 2, 3, etc.).
Multiply by the original spacing to get the actual x-value of the line you want to draw (0, 25, 50, 75, etc.).
Create a transparent custom UIView that covers the whole screen (except the status bar) and override its (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event.
You can get the touch point with:
UITouch *touch = [touches anyObject];
CGPoint touchPoint = [touch locationInView:self];
You can use ssteinberg code:
UITouch *touch = [touches anyObject];
CGPoint touchPoint = [touch locationInView:self];
or adding a UITapGestureRecognizer to your view, which it is probably easier:
UITapGestureRecognizer* tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
[yourParentView addGestureRecognizer:tapRecognizer];
[tapRecognizer release];
...
- (IBAction)handleTap:(UITapGestureRecognizer *)recognizer {
CGPoint touchPoint = [recognizer locationInView:self.view];
...
And in addition, draw your line at every 25px by adding something like this:
CGFloat padding = 25.0;
NSInteger xPosition = round(touchPoint.x / padding) * padding;
[self drawLineAt:xPosition];
Refer This if you find it suitable :
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if (lineView) {
[lineView removeFromSuperview];
NSSet *allTouchesSet = [event allTouches];
NSArray *allTouches = [NSArray arrayWithArray:[allTouchesSet allObjects]];
int count = [allTouches count];
if (count == 1) {
UITouch *touch = [[event allTouches] anyObject];
tapPoint = [touch locationInView:self];
NSLog(#"tapPoint: %#",NSStringFromCGPoint(tapPoint));
UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(tapPoint.x, 0.0, 1, 320.0)];
lineView.backgroundColor = [UIColor whiteColor];
[parentView addSubview:lineView];
}
}
}

Resources