Slide textview horizontal without using paging - iphone

I`m using a simple Textview in an tabbased application to display some text :) I figerd out how to change the text animated using the following code:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint currentTouchPosition = [touch locationInView:self];
// To be a swipe, direction of touch must be horizontal and long enough.
if (fabsf(startTouchPosition.x - currentTouchPosition.x) >= HORIZ_SWIPE_DRAG_MIN &&
fabsf(startTouchPosition.y - currentTouchPosition.y) <= VERT_SWIPE_DRAG_MAX)
{
// It appears to be a swipe.
if (startTouchPosition.x < currentTouchPosition.x){
NSString *string = [[NSString alloc]initWithFormat:#"..."];
self.text = string;
}
else{
CGContextRef context = UIGraphicsGetCurrentContext();
[UIView beginAnimations:nil context:context];
//[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:[self superview] cache:YES];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:[self superview] cache:YES];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:0.5];
[[self superview] exchangeSubviewAtIndex:0 withSubviewAtIndex:1];
[UIView commitAnimations];
[self displayNewText];
}
}
However there is now "slide transition" defined in UIViewAnimationTransition. I know about paging, but I don`t want to use this. Is there an other possibility to have an horizontal slide animation when detecting a horizontal swipe?

I think you are almost there. Intercept touchesMoved:withEvent method just like in your current code and update the visible area of the UIScrollView object.

I hope you don't have to detect touches for your requirement use UIScrollView as parent view for UITextView.
scroll=[[UIScrollView alloc]initWithFrame:CGRectMake(0,40, 320,200)];
[scroll setContentSize:CGSizeMake(640, 200)];
Or if you want to animate the view you can use affine transforms.
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1];
someview.transform=CGAffineTransformMakeTranslation(-100, 0);
[UIView commitAnimations];

Related

Swiping A View with Gestures

I am trying to develop an application to Iphone; but i am new-bee so i have got a lot of problems.
My application has got a default view and another small view in the main view that name is flashcard.
I want to add capability this view swiping (or sliding) like Photos in Iphone. For example if user swipes view until the inner view's center reaches bounds of main view there will be two possibilities,
1- if user finish swiping before reach inner view will return to original position.
2- if user don't stop swiping, inner view will go out at screen from swipe direction and return the screen from the opposite direction.
So i declare UIPanGestureRecognizer at viewDidLoad like below
UIPanGestureRecognizer *panFlashCard = [[UIPanGestureRecognizer alloc]
initWithTarget:self action:#selector(handlePanFlashCard:)];
[flashcard addGestureRecognizer:panFlashCard];
[panFlashCard release];
handPanFlashCard action:
UIView *piece = [recognizer view];
CGPoint center = piece.center;
CGFloat x = 160; // the original x axis of inner view
if ([recognizer state] == UIGestureRecognizerStateChanged) {
CGPoint translation = [recognizer translationInView:piece ];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.55];
[piece setCenter:CGPointMake(piece.center.x + translation.x, center.y)];
[UIView commitAnimations];
CGFloat totalX;
totalX= x + translation.x;
if(translation.x <0)
{
if (totalX <= 0)
{
[self showNextCard];
}
else
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.55];
[piece setCenter:CGPointMake(self.view.center.x, center.y)];
[UIView commitAnimations];
}
}
else
{
if (totalX >= self.view.bounds.size.width)
{
[self showPreviousCard];
}
else
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.55];
[piece setCenter:CGPointMake(self.view.center.x, center.y)];
[UIView commitAnimations];
}
}
}
showNextCard action:
[flashcard setCenter:CGPointMake(self.view.bounds.size.width + flashcard.bounds.size.width, flashcard.center.y)];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.55];
[flashcard setCenter:CGPointMake(self.view.center.x, flashcard.center.y)];
[UIView commitAnimations];
showPreviousCard action:
[flashcard setCenter:CGPointMake(0 - flashcard.bounds.size.width, flashcard.center.y)];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.55];
[flashcard setCenter:CGPointMake(self.view.center.x, flashcard.center.y)];
[UIView commitAnimations];
When i run this application, it builds and runs successfully but there is something wrong with animations, some frame mistakes i think.
Please help me to correct this code and run fluent animations while swiping.
If I understand what you are trying to do then you can just use built in controls for this. Take a look at the pagingEnabled property on the UIScrollView class. There is also a sample project called PhotoScroller that may help.
http://developer.apple.com/library/ios/#samplecode/PhotoScroller/Introduction/Intro.html

Iphone SDK: move and rotate to touch

I have an image of a fish - If the user touches the screen I want the fish to "look" at the touched point and move there. If the touch has been moved i want the fish constantly following the touch.
How can I do that?
would be something like this:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *tap = [touches anyObject];
CGPoint pointToMove = [tap locationInView:self.view];
CGFloat xdiff = pointToMove.x-myFish.center.x;
CGFloat ydiff = pointToMove.y-myFish.center.y;
if (!CGRectContainsPoint(myFish.frame, pointToMove)) {
CGFloat angle = 0;
if (xdiff) {
if (xdiff>0) {
angle = atanf(ydiff/xdiff);
} else {
angle = M_PI + atanf(ydiff/xdiff);
}
}
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3f];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
myFish.transform = CGAffineTransformMakeRotation(angle);
[UIView commitAnimations];
}
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.0f];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
myFish.center = pointToMove;
[UIView commitAnimations];
}
and you probably want to implement these too:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
EDIT: updated code, now the rotation is done in a separate animation, so that the fish rotates faster than he swims.

How can I present a UIView from the bottom of the screen like a UIActionSheet?

I'd like a UIView to slide up from the bottom of the screen (and stay mid-screen) like a UIActionSheet. How can I accomplish this?
UPDATE:
I am using the following code:
TestView* test = [[TestView alloc] initWithNibName:#"TestView" bundle:nil];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.4];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
test.view.center = CGPointMake(160,100);
//test.view.frame = CGRectMake(0, 0, 160, 210);
[[[UIApplication sharedApplication] keyWindow] addSubview:test.view];
[UIView commitAnimations];
The view seems to be animating from the corner and appearing in the corner. How can I make it slide up from the bottom? Getting close!
Do what Matt did here, but just change the values and direction. I have code at home to do this from the bottom if you need it later (I'll update this post).
Link: http://cocoawithlove.com/2009/05/intercepting-status-bar-touches-on.html
Also, don't forget to take out the bit of code that shifts the main view downward (so instead the UIView just pops over top like an ActionSheet)
Updated with code:
This is what I use in one of my apps to show/hide a little "options" view:
- (void)toggleOptions:(BOOL)ViewHidden
{
// this method opens/closes the player options view (which sets repeat interval, repeat & delay on/off)
if (ViewHidden == NO)
{
// delay and move view out of superview
CGRect optionsFrame = optionsController.view.frame;
[UIView beginAnimations:nil context:nil];
optionsFrame.origin.y += optionsFrame.size.height;
optionsController.view.frame = optionsFrame;
[UIView commitAnimations];
[optionsController.view
performSelector:#selector(removeFromSuperview)
withObject:nil
afterDelay:0.5];
[optionsController
performSelector:#selector(release)
withObject:nil
afterDelay:0.5];
optionsController = nil;
}
else
{
optionsController = [[PlayOptionsViewController alloc] init];
//
// Position the options at bottom of screen
//
CGRect optionsFrame = optionsController.view.frame;
optionsFrame.origin.x = 0;
optionsFrame.size.width = 320;
optionsFrame.origin.y = 423;
//
// For the animation, move the view up by its own height.
//
optionsFrame.origin.y += optionsFrame.size.height;
optionsController.view.frame = optionsFrame;
[window addSubview:optionsController.view];
[UIView beginAnimations:nil context:nil];
optionsFrame.origin.y -= optionsFrame.size.height;
optionsController.view.frame = optionsFrame;
[UIView commitAnimations];
}
}
One way would be to use the present modal view controller on the view controller:
presentModalViewController:(UIViewController *)modalViewController animated:(BOOL)animated
For more info take a look at the UIViewController documentation.
EDIT: If you want a mid-screen view you'll need to animate it into position as #jtbandes has pointed out. I suggest also adding some candy to UIView animation block:
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.4];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
myView.center = CGPointMake(x,y);
[UIView commitAnimations];
You can then move it again if you need to go full screen or dismiss it.
You'll have to move the view yourself, by setting its center or frame. I'll let you figure out what to set those to. But for the animation:
// set the view to its initial position here...
[UIView beginAnimations:nil context:NULL];
// move the view into place here...
[UIView commitAnimations];
Check out this post: http://blog.yetanotherjosh.com/post/33685102199/3-ways-to-do-a-vertical-transition-with
I'm going with the modal window approach.
Try this solution.... it works
#pragma mark - Date Selector View PresentModelView with Transparent ViewController
- (void) showModal:(UIView*) modalView {
CGRect rect=modalView.frame;
rect.origin=CGPointMake(0, 0);
self.tutorialView.frame=rect;
UIWindow *mainWindow = [(AppDelegate *)[UIApplication sharedApplication].delegate window];
CGPoint middleCenter;
middleCenter = CGPointMake(modalView.center.x, modalView.center.y);
CGSize offSize = [UIScreen mainScreen].bounds.size;
CGPoint offScreenCenter = CGPointMake(offSize.width / 2.0, offSize.height * 1.5);
modalView.center = offScreenCenter;
if ([[mainWindow subviews] containsObject:modalView]) {
[modalView removeFromSuperview];
}
[mainWindow addSubview:modalView];
[mainWindow bringSubviewToFront:modalView];
// Show it with a transition effect
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3];
// animation duration in seconds
modalView.center = middleCenter;
[UIView commitAnimations];
}
// Use this to slide the semi-modal view back down.
- (void) hideModal:(UIView*) modalView {
CGSize offSize = [UIScreen mainScreen].bounds.size;
CGPoint offScreenCenter = CGPointMake(offSize.width / 2.0, offSize.height * 1.5);
[UIView beginAnimations:nil context:(__bridge void *)(modalView)];
[UIView setAnimationDuration:0.3];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(hideModalEnded:finished:context:)];
modalView.center = offScreenCenter;
[UIView commitAnimations];
}
- (void) hideModalEnded:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
UIView *modalView = (__bridge UIView *)context;
[modalView removeFromSuperview];
}

View rotation in touchesMoved

I rotate a view by 45 degree on every dragging. Here is my code. Problem here is that the view is rotated only once. After that there is no rotation. What will be the reason? Any help
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
CGContextRef context = UIGraphicsGetCurrentContext();
[UIView beginAnimations:nil context:context];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:0];
dialView.transform = CGAffineTransformMakeRotation(45* M_PI/180);
[UIView commitAnimations];
}
You can also use CGAffineTransformRotate to rotate from its present transform, as in:
dialView.transform = CGAffineTransformRotate(dialView.transform, 45 * M_PI / 180);
The rotation is always relative to 0. If you rotate to x several times it will rotate only the first time.
If you want to rotate 45 everytime you call that code, you will need to have counter and it would look like this:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
step++;//You are supposed to keep this variable global.
CGContextRef context = UIGraphicsGetCurrentContext();
[UIView beginAnimations:nil context:context];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:0];
dialView.transform = CGAffineTransformMakeRotation(45*step* M_PI/180);
[UIView commitAnimations];
}

change counterclockwise to clockwise with CGAffineTransformIdentity

I have a telephone wheel. On the touchend, it goes to his position with an animation.
Until the angle is less than 180°, it returns clockwise. No problem, with this code :
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView beginAnimations:nil context:NULL];
[UIViewsetAnimationDuration:0.5];
wheel.transform = CGAffineTransformIdentity;
[UIView commitAnimations];
}
But It goes wrong after that and continue to rotate for a complet turn.
I tried to make to animations like this :
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.2];
wheel.transform = CGAffineTransformRotate(wheel.transform, degreesToRadians(-130));
[UIView commitAnimations];
[self performSelector:#selector(animatewheelViewToCenter) withObject:nil afterDelay:0.3];
}
- (void)animatewheelViewToCenter{
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView beginAnimations:nil context:NULL];
[UIViewsetAnimationDuration:0.3];
wheel.transform = CGAffineTransformIdentity;
[UIView commitAnimations];
}
It works, but the animation isn't fluid ; the change is visible.
I'm not sure what the state is when touchesEnded (in terms of rotation) and I'm assuing you chose degreesToRadians(-130) to try and do it partially and expect the next method to do the rest. This should be a better solution that hopefully yields the result you're expecting. I'm not sure what cadran is or why you're rotating that, so I'll just rotate the wheel.
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.2];
wheel.transform = CGAffineTransformMakeRotation(degreesToRadians(-130));
// I would recommend that the degrees you rotate be half of whatever your rotation is.
// this would make the wheel rotate to the home position more evenly
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animatewheelViewToCenter:finished:context:)];
[UIView commitAnimations];
}
- (void)animatewheelViewToCenter:(NSString *)animationID finished:(NSNumber *)finished context:(id)context {
[UIView setAnimationBeginsFromCurrentState:YES]; // you might need to make this NO
[UIView beginAnimations:nil context:NULL];
[UIViewsetAnimationDuration:0.2];
wheel.transform = CGAffineTransformIdentity;
[UIView commitAnimations];
}
EDIT: Actually, I would probably make the rotation (in the example -130 degrees) slightly more than what half would be, because CGAffineTransformIdentity is gonna take the shortest path to go back to regular, so if you go exactly 1/2 way, it may not go the correct direction (clockwise or counter-clockwise) that you want.