need UIButton inside custom UIView respond to touches - iphone

I have a custom UIView with some buttons as subviews. I am using touchesBegan/Moved/Ended to rotate the view with the user's finger. The problem is, when I try to drag/rotate the view from a button, the touches methods aren't called. I need the buttons to respond to the UIControlEventTouchUpInside event, but if it is dragged with the view, then to make my view rotate. I have looked at this question and this question, but couldn't get either solution to work for me.
Here is my custom view code:
- (id)initWithFrame:(CGRect)frame andRadius:(float)Radius andViews:
(NSMutableArray *)AllViews
{
self = [super initWithFrame:frame];
if (self) {
radius = Radius;
allViews = AllViews;
for(int i = 0; i < [allViews count]; i++){
//the "currentView" is a UIButton
UIView *currentView = (UIView *)[allViews objectAtIndex:i];
[currentView setFrame:CGRectMake(frame.size.width / 2 - 25 + radius * cos((2 * M_PI / [allViews count]) * i), frame.size.height / 2 - 25 + radius * sin((2 * M_PI / [allViews count]) * i), 50, 50)];
[self addSubview:currentView];
}
[self setBackgroundColor:[UIColor redColor]];
[self setAlpha:.5];
}
return self;
}
//- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
//{
// for (UIView * view in [self subviews]) {
// if ([view pointInside:[self convertPoint:point toView:view] withEvent:event]) {
// return YES;
// }
// }
// return NO;
//}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self];
x = point.x;
y = point.y;
NSLog(#"touchesBegan");
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self];
float X = point.x;
float Y = point.y;
float a = sqrt(X * X + Y * Y);
float b = sqrt(x * x + y * y);
float c = sqrt((x - X) * (x - X) + (y - Y) * (y - Y));
float alpha = acos((a * a + b * b - (c * c)) / (2 * a * b));
if(alpha == NAN)
alpha = 0;
alpha = -alpha;
[UIView beginAnimations:#"rotate" context:nil];
[UIView setAnimationDuration:0];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
self.transform = CGAffineTransformRotate(self.transform, alpha);
[UIView commitAnimations];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self];
float X = point.x;
float Y = point.y;
float a = sqrt(X * X + Y * Y);
float b = sqrt(x * x + y * y);
float c = sqrt((x - X) * (x - X) + (y - Y) * (y - Y));
float alpha = acos((a * a + b * b - (c * c)) / (2 * a * b));
alpha = -alpha;
[UIView beginAnimations:#"rotate" context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
self.transform = CGAffineTransformRotate(self.transform, alpha);
[UIView commitAnimations];
NSLog(#"touchesEnded");
}
- (void)dealloc
{
[allViews release];
[super dealloc];
}
Any suggestions?

Maybe not the answer you're looking for, but:
I'm not sure why you'd want "finger down on button then drag finger outside of button" activity to be picked up by the view behind the button as a dragging/rotating motion. As far as I'm concerned, if you put your finger down inside a button, you are interacting with the button, not the view behind; and if you move your finger off the button while still touching the screen, you're doing that to abort the button press (i.e. you've "armed" it but not "triggered" it), not to interact with the view behind.
So what I'm saying is: why would you want to do this? Maybe you need to rethink your UI design.
If you absolutely want to do this, you may want to look at using UIGestureRecognizers instead of touchesBegan etc. - you can set up more complicated scenarios more easily when using them. But the gesture recognizers are not available on all versions of iOS.
Alternatively, implement something that looks like a button or whatever it is you want, and handle the touching of it (and the view dragging etc.) using touchesBegan etc. - i.e. don't use an actual button.

Just incase someone comes across a similar issue, I'll post the solution I used. I overrode another UIView class that I used as a button. In each of the touchedBegan/Moved/Ended, I implemented the code I need for the button click, then passed the touch up the chain of command to the next custom UIView, like so:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.nextResponder touchesBegan:touches withEvent:event];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.nextResponder touchesMoved:touches withEvent:event];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self];
if (point.x < self.frame.size.width && point.y < self.frame.size.height) {
NSDictionary *userInfo = [[NSDictionary alloc] initWithObjectsAndKeys:[NSString stringWithFormat:#"%d", self.tag], #"tag", nil];
[[NSNotificationCenter defaultCenter] postNotificationName:#"ChangeFilter" object:self userInfo:userInfo];
}
[self.nextResponder touchesEnded:touches withEvent:event];
}
Notice that I use NSNotifications to send the action to my ViewController that contains the overridden view.

Related

How to restrict uilabel to be dragged within a particular frame only?

I have added one label in imageview and added Pangesture for dragging label.With this code label is dragged within the whole.but i want to restrict the label drag within the frame of uiimageview only.
How can i achieve this? The code for adding lable and gesture is as below.
lblQuote=[[UILabel alloc]init];
lblQuote.frame=CGRectMake(130,380, 400,100);
lblQuote.userInteractionEnabled=TRUE;
lblQuote.backgroundColor=[UIColor clearColor];
lblQuote.userInteractionEnabled=TRUE;
lblQuote.lineBreakMode=UILineBreakModeWordWrap;
lblQuote.font=[UIFont systemFontOfSize:40.0];
lblQuote.tag=500;
lblQuote.text=#"";
CGSize maximumLabelSize = CGSizeMake(296,9999);
CGSize expectedLabelSize = [strQuote sizeWithFont:lblQuote.font
constrainedToSize:maximumLabelSize
lineBreakMode:lblQuote.lineBreakMode];
//adjust the label the the new height.
int nooflines=expectedLabelSize.height/16.0;
lblQuote.numberOfLines=nooflines;
// CGRect newFrame = lblQuote.frame;
//newFrame.size.height = expectedLabelSize.height;
// yourLabel.frame = newFrame;
lblQuote.textAlignment=UITextAlignmentCenter;
UIPanGestureRecognizer *gesture = [[[UIPanGestureRecognizer alloc]
initWithTarget:self
action:#selector(labelDragged:)] autorelease];
[lblQuote addGestureRecognizer:gesture];
- (void)labelDragged:(UIPanGestureRecognizer *)gesture
{
UILabel *label = (UILabel *)gesture.view;
CGPoint translation = [gesture translationInView:label];
// move label
label.center = CGPointMake(label.center.x + translation.x,
label.center.y + translation.y);
// reset translation
[gesture setTranslation:CGPointZero inView:label];
}
I tried moving label on touches event.code is as below:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint pointMoved = [touch locationInView:imgView2];
lblQuote.frame=CGRectMake(pointMoved.x, pointMoved.y, lblQuote.frame.size.width, lblQuote.frame.size.height);
}
But movement is not as smooth as pan gesture recognizer.sometimes touch is in another direction and label movement in some other direction and sometimes more or less movement than touch.
Well this is totally depends on your logics although i wrote a code for you, hope this will help you!!
Make sure your UILabel UserIntraction is set to be YES; and use touch began and touch moved methods instead of pangesture.... see this now
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches]anyObject];
if([touch view] == lblName)
{
NSLog(#"touch on label");
CGPoint pt = [[touches anyObject] locationInView:lblName];
startLocation = pt;
// startLocation is a CGPoint declare globaly in .h..and lblName is your UILabel
}
}
- (void) touchesMoved:(NSSet *)touches withEvent: (UIEvent *)event
{
UITouch *touch = [[event allTouches]anyObject];
if([touch view] == lblName)
{
CGPoint pt = [[touches anyObject] previousLocationInView:lblName];
CGFloat dx = pt.x - startLocation.x;
CGFloat dy = pt.y - startLocation.y;
CGPoint newCenter = CGPointMake(lblName.center.x + dx, lblName.center.y + dy);
//now put if condition for dragging in specific area
CGFloat min_X = lblName.center.x + dx - lblName.frame.size.width/2.0;
CGFloat max_X = lblName.center.x + dx + lblName.frame.size.width/2.0;
CGFloat min_Y = lblName.center.y + dy - lblName.frame.size.height/2.0;
CGFloat max_Y = lblName.center.y + dy + lblName.frame.size.height/2.0;
if((min_X >= imageView.frame.origin.x && max_X <= imageView.frame.origin.x + imageView.frame.size.width) && (min_Y >= imageView.frame.origin.y && max_Y <= imageView.frame.origin.y + imageView.frame.size.height))
{
lblName.center = newCenter;
}
}
}

iphone - how to scroll uiscrollview from event touched by uibutton in scrollview

structure
UIViewController
- UIScrollview
- UIButton
I'm going to make scrollview can receive button event. So whenever user do scrolling(dragging) on the button, the scrollview react as scrolling itself.
I made button down and moved handler with event forwarding like below
- (IBAction)buttonTouchedMove:(id)sender withEvent:(UIEvent *)event {
[[sender nextResponder] touchesMoved:[event allTouches] withEvent:event];
}
- (IBAction)buttonTouchedDown:(id)sender withEvent:(UIEvent *)event {
[[sender nextResponder] touchesBegan:[event allTouches] withEvent:event];
}
and to move scrollview as touches change, I made below codes
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
self.oldPoint = [touch locationInView:self.view];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
CGPoint offset = self.scrollView1.contentOffset;
UITouch *touch = [touches anyObject];
self.newPoint = [touch locationInView:self.view];
int diffX = newPoint.x - oldPoint.x;
offset.x = offset.x - diffX;
[scrollView1 setContentOffset:offset animated:YES];
self.oldPoint = self.newPoint;
}
but, scrollview react strange.. not move enough as I touch moved.
// get the button width
CGFloat buttonWidth = self.theButton.frame.size.width;
// replace your button name here
// now get the view width
CGFloat viewWidth = self.view.frame.size.width;
// replace your view name here
// now get the multiplier which i said u as 10
CGFloat mult = viewWidth / buttonWidth;
// and now use it in your code
.
.
.
diffX = mult*(newPoint.x - oldPoint.x);
.
.
.
Final answer, Using UIView animation, I got what i want.
- (IBAction)buttonTouchedDown:(id)sender withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
self.oldPoint = [touch locationInView:self.view];
self.velocity = 0;
isButtonTouchedDown = YES;
}
- (IBAction)buttonTouchedMove:(id)sender withEvent:(UIEvent *)event {
CGPoint offset = self.scrollView1.contentOffset;
UITouch *touch = [[event allTouches] anyObject];
self.newPoint = [touch locationInView:self.view];
int diffX = self.newPoint.x - self.oldPoint.x;
velocity = diffX;
offset.x = offset.x - diffX;
[self.scrollView1 setContentOffset:offset animated:NO];
self.oldPoint = self.newPoint;
}
There is a trick..I calculated velocity by differentiating moved distance in TouchedMove function.
In Button TouchUp event handler, I controlled Scrollview with velocity value and CurveEaseout animation to scroll more. By offering very short duration of animation and repeating it if there is no event(button touched down). It becomes very similar with scrollview's animation.
- (IBAction)buttonTouchedUp:(id)sender withEvent:(UIEvent *)event {
CGPoint offset = self.scrollView1.contentOffset;
amountX = (self.velocity)*(abs(self.velocity));
dX = amountX;
isButtonTouchedDown = NO;
if (offset.x - amountX < 0) {
offset.x = 0;
[scrollView1 setContentOffset:offset animated:YES];
}
else if (abs(dX) < 70) { // 70: content item size
offset.x = roundf(offset.x/70)*70;
[scrollView1 setContentOffset:offset animated:YES];
}
else {
[self endScrollAnimation];
}
- (void)startAnimation:(float)x moveAmount:(float)moveAmount
{
CGPoint offset = self.scrollView1.contentOffset;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:duration];
offset.x = x < 0 ? offset.x + moveAmount : offset.x -moveAmount;
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(endScrollAnimation)];
[scrollView1 setContentOffset:offset animated:NO];
[UIView commitAnimations];
}
- (void)endScrollAnimation
{
CGPoint offset = self.scrollView1.contentOffset;
float slowMoveAmount = abs(amountX) * 0.05;
float fastMoveAmount = abs(amountX) * 0.1;
if (isButtonTouchedDown) {
return;
}
else if (abs(dX) > abs(amountX)*0.35 && offset.x > 0) {
[self startAnimation:dX moveAmount:fastMoveAmount];
dX = dX < 0 ? dX + fastMoveAmount : dX -fastMoveAmount;
}
else if (abs(dX) > slowMoveAmount && offset.x > 0) {
[self startAnimation:dX moveAmount:slowMoveAmount];
dX = dX < 0 ? dX + slowMoveAmount : dX - slowMoveAmount;
}
else {
offset.x = roundf(offset.x/70)*70;
[scrollView1 setContentOffset:offset animated:YES];
}
}

iPhone - Inertial dragging

I have an object that the user has to drag around the screen. This is a regular UIImageView. Currently, the image can be dragged around but when you release it, it stops where your finger lifted the image. What I want is to create momentum, so I can give an impulse to the image and it scrolls until it bounces the screen edge.
I don't want nothing very complex like adding physics libraries and stuff like that. I want to keep it as minimum as possible.
How do I do that? Can you guys point me to some tutorial or in the right direction?
thanks.
Well one way of doing this without using any physics library is this:
First in your class create 4 instance variables like this:
CFTimeInterval startTime;
CGPoint startPoint;
CGPoint oldPoint;
BOOL imageViewTouched;
Than in your - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event method have this code:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouched] anyObject];
// Test to see if the touched view is your image view. If not just return.
if (touch.view != <#yourImageView#>) {
return;
}
startPoint = [touch locationInView:self.view];
oldPoint = startPoint;
startTime = CACurrentMediaTime();
imageViewTouched = YES;
}
For - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event do this:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
// Fingers were moved on the screen but your image view was not touched in the beginning
if (!imageViewTouched) {
return;
}
UITouch *touch = [[event allTouches] anyObject];
CGPoint newPoint = [touch locationInView:self.view];
<#yourImageView#>.frame = CGRectOffset(<#yourImageView#>.frame, newPoint.x - oldPoint.x, newPoint.y - oldPoint.y);
oldPoint = newPoint;
}
Now for - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event try this:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
// Fingers were removed from the screen but your image view was not touched in the beginning
if (!imageViewTouched) {
return;
}
imageViewTouched = NO;
UITouch *touch = [[event allTouches] anyObject];
CGPoint endPoint = [touch locationInView:self.view];
CFTimeInterval endTime = CACurrentMediaTime();
CFTimeInterval timeDifference = endTime - startTime;
// You may play with this value until you get your desired effect
CGFloat maxSpeed = 80;
CGFloat deltaX = 0;
CGFloat deltaY = 0;
if (timeDifference < 0.35) {
deltaX = (endPoint.x - startPoint.x) / (timeDifference * 10);
deltaY = (endPoint.y - startPoint.y) / (timeDifference * 10);
}
if (deltaX > maxSpeed) { deltaX = maxSpeed; }
else if (deltaX < -maxSpeed) { deltaX = -maxSpeed; }
else if (deltaX > -5 && deltaX < 5) { deltaX = 0; }
if (deltaY > maxSpeed) { deltaY = maxSpeed; }
else if (deltaY < -maxSpeed) { deltaY = -maxSpeed; }
else if (deltaY > -5 && deltaY < 5) { deltaY = 0; }
[UIView begginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5f];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
<#yourImageView#>.frame = CGRectOffset(<#yourImageView#>.frame, deltaX, deltaY);
[UIView commitAnimations];
}
Please let me know if this makes sense and/or works for you. Cheers!

iPhone - Wheel tracking finger jumps to same starting position?

I am trying to implement a selection wheel in an iphone application. I have got the wheel to track the users finger but now for some reason when the user touches the screen the wheel jumps so the same section of the wheel tracks the finger each time.
How would I get it so the wheel rotates like the user is dragging it from any point?
-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
NSSet *allTouches = [event allTouches];
int tInput = [allTouches count]-1;
UITouch *touch =[[allTouches allObjects] objectAtIndex:tInput];
CGPoint location = [touch locationInView:self.view];
float theAngle = atan2( location.y-imageX.center.y, location.x-imageX.center.x );
CGAffineTransform cgaRotate = CGAffineTransformMakeRotation(theAngle);
imageX.transform = cgaRotate;
}
Any suggestion?
Right - that makes perfect sense - this is indeed what your code does.
What you need to add is the initial value where you started your drag as a relative rotation -- or track your last rotation.
A very elaborate way is shown below - but this should help get the point across.
#interface UntitledViewController : UIViewController {
CGPoint firstLoc;
UILabel * fred;
double angle;
}
#property (assign) CGPoint firstLoc;
#property (retain) UILabel * fred;
#implementation UntitledViewController
#synthesize fred,firstLoc;
- (void)viewDidLoad {
[super viewDidLoad];
self.fred = [[UILabel alloc] initWithFrame:CGRectMake(100,100,100,100)];
fred.text = #"Fred!"; fred.textAlignment = UITextAlignmentCenter;
[self.view addSubview:fred];
angle = 0; // we aint have rotated just yet...
};
// make sure we get them drag events.
- (BOOL)isFirstResponder { return YES; }
-(void)handleObject:(NSSet *)touches
withEvent:(UIEvent *)event
isLast:(BOOL)lst
{
UITouch *touch =[[[event allTouches] allObjects] lastObject];
CGPoint curLoc = [touch locationInView:self.view];
float fromAngle = atan2( firstLoc.y-fred.center.y,
firstLoc.x-fred.center.x );
float toAngle = atan2( curLoc.y-fred.center.y,
curLoc.x-fred.center.x );
// So the angle to rotate to is relative to our current angle and the
// angle through which our finger moved (to-from)
float newAngle = angle + (toAngle - fromAngle);
CGAffineTransform cgaRotate = CGAffineTransformMakeRotation(newAngle);
fred.transform = cgaRotate;
// we only 'save' the current angle when we're done with the drag.
//
if (lst)
angle = newAngle;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch =[[[event allTouches] allObjects] lastObject];
// capture where we started - so we can later work out the
// rotation relative to this point.
//
firstLoc = [touch locationInView:self.view];
};
-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
[self handleObject:touches withEvent:event isLast:NO];
};
-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[self handleObject:touches withEvent:event isLast:YES];
}
Obviously you can do this a lot more elegant - and above misses a bit of 0 .. 2xPI capping you need.
Because the view itself is still the old one. You may want to fetch the zip example file in:
http://bynomial.com/blog/?p=77
and in PuttyView.m change the:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
....
else {
self.center = CGPointMake(self.center.x + touchPoint.x - touchStart.x,
self.center.y + touchPoint.y - touchStart.y);
into
else {
NSSet *allTouches = [event allTouches];
int tInput = [allTouches count]-1;
UITouch *touch =[[allTouches allObjects] objectAtIndex:tInput];
CGPoint location = [touch locationInView:self];
float theAngle = atan2( location.y-self.center.y, location.x-self.center.x );
CGAffineTransform cgaRotate = CGAffineTransformMakeRotation(theAngle);
self.transform = cgaRotate;
}
where you thus stay within the view and its relative angle. Alternatively - in your code - keep the relative angle itself.

UITableView: scrolling programmatically the content view

Hi i'm trying to forward the touches I receive from an UIView which is in front of an UITableView. But doins so I can't make the table scroll anymore (see here).
So now I'm trying to make tha tableview scroll programmatically and I am looking at setContentOffset:animated: and scrollRectToVisible:animated: with having success only with the first.
Here is my code in a class that subclasses the UITableView:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(#"BEGTB");
//previousXPan = 0.0;
UITouch * touch = [touches anyObject];
CGPoint tPoint = [touch locationInView:self];
previousYPan = tPoint.y;
[super touchesBegan:touches withEvent:event];
//
//[super touchesShouldBegin:touches withEvent:event inContentView:self];
//[[self nextResponder] touchesBegan:touches withEvent:event];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch * touch = [touches anyObject];
CGPoint tPoint = [touch locationInView:self];
NSLog(#"MOVTB");
NSLog(#"BOUNDZ %f, %f, %f, %f", self.bounds.origin.x, self.bounds.origin.y, self.bounds.size.height, self.bounds.size.width);
NSLog(#"CONTENT SIZE %f, %f", self.contentSize.height, self.contentSize.width);
CGRect rc = [self bounds];
NSLog(#"%f %f", rc.size.height, rc.size.width);
CGRect newRect = CGRectMake(rc.origin.x, rc.origin.y + self.contentSize.height, self.contentSize.width, fabs(tPoint.y - previousYPan));
NSLog(#"BOND RECT %f, %f, %f, %f", rc.origin.x, rc.origin.y, rc.size.height, rc.size.width);
NSLog(#"NEW RECT %f, %f, %f, %f", newRect.origin.x, newRect.origin.y, newRect.size.height, newRect.size.width);
//[self scrollRectToVisible:newRect animated:YES];
NSLog(#"Content OFFSET %f",tPoint.y - previousYPan);
[self setContentOffset:CGPointMake(rc.origin.x,(tPoint.y - previousYPan) *2.0 )animated:YES];
previousYPan = tPoint.y;
//[super touchesMoved:touches withEvent:event];
//[[self nextResponder] touchesMoved:touches withEvent:event];
}
But the result is really laggy and buggy. Any better idea?
I almost found a suitable solution (it is not like a normal scrolling but...).
First I determine the mamimum and minimum amount of pixels in the content area of the table view on the Y axis ( the height of the contentSize when the view has been fully loaded).
The I check the movement done incrementally but not referencing the position of the touch in the table view! I have to check it on a top layered UIView that covers it, because when you alter the content offset of the table you change dynamically its dimensions and you can end you having an acceleration effect .
Here is some code:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch * touch = [touches anyObject];
CGPoint tPoint = [touch locationInView:[viewController draggableAreaView]];
CGRect rc = [self bounds];
float totalOS = tPoint.y - previousYPan;
if ((contentOffSetY >= minY && contentOffSetY <= maxY) ||
(contentOffSetY < minY - 5 && totalOS < 0) ||
(contentOffSetY > maxY + 5 && totalOS > 0))
{
if (totalOS > 0)
totalOS += OFFSET;
else if (totalOS < 0)
totalOS -= OFFSET;
[self setContentOffset:CGPointMake(rc.origin.x,self.contentOffset.y + totalOS)animated:NO];
}
else /*if (contentOffSetY < minY - 5 && totalOS < 0) */
{
[self resetOffset];
}
previousYPan = tPoint.y;
}
- (void)resetOffset{
CGRect rc = [self bounds];
if(contentOffSetY < minY)
{
[self setContentOffset:CGPointMake(rc.origin.x, minY + 50)animated:YES];
}
else if (contentOffSetY > maxY)
{
[self setContentOffset:CGPointMake(rc.origin.x, maxY - 50)animated:YES];
}
}
Some more tips:
here draggableAreaView is the top UIView from which I get an "absolute" position
OFFSET is a constant defined to increment linearly the speed of the scroolling (without it the touchesMoved: , called many times, gives a relative movement of just one pixel each time)
,minY and maxY are the precalculated limit values (in order to compute them I calculated the height of all the cells in the table for max and the height of the visible content view for min)
I added some displacement to minY and maxY in order to have a more visible animation