Hide and show scrollview with animation - objective-c

In my app I have a scrollview and when I press a button it is hidden when I press again it shows up.
I use scrollview.hidden = YES (or NO) to do it.
But I want to do it with an animation. For example, it may disappear from the bottom of the screen by moving and shows up with the same way. How can I do that?
edit:
[UIView beginAnimations:#"myAnimation" context:nil];
CGRect Frame = bottomScroller.frame;
if(Frame.origin.y == 380){
Frame.origin.y = 460;
}else{
Frame.origin.y = 380;
}
bottomScroller.frame = Frame;
[UIView commitAnimations];
This solved my problem...

You may check UIView animations. It's pretty easy. For example to animate translation you may use something like:
[UIView beginAnimations:#"myAnimation" context:nil];
CGRect Frame = yourView.frame;
Frame.origin.y = 0;
yourView.frame = Frame;
[UIView commitAnimations];
Then to move it back:
[UIView beginAnimations:#"myAnimation" context:nil];
CGRect Frame = yourView.frame;
Frame.origin.y = 100;
yourView.frame = Frame;
[UIView commitAnimations];
Changes in frame, alpha and some other parameters will be automatically animated.

You can use animations like so:-
[UIView animateWithDuration:2.0 animations:^{
[scrollview setframe:CGRectMake(xpos, ypos, width, height)];
}];
If you want to slide the scrollview on or off the screen set its y position - the bottom of the view is you want to hide it, the normal y position if you want to show it.
The 2.0 is an animation length, this can be changed to whatever you need it to be!

You can do this by using simple view animations. Here's an example of how you might do this:
// myScrollView is your scroll view
-(void)toggleShow{
CGFloat targetAlpha = myScrollView.alpha == 1 ? 0 : 1;
CGFloat yPosition = targetAlpha == 1 ? 0 : self.view.frame.size.height;
[UIView animateWithDuration:1.0 animations:^{
myScrollView.frame = CGRectMake(myScrollView.frame.origin.x, yPosition, myScrollView.frame.size.width, myScrollView.frame.size.height);
myScrollView.alpha = targetAlpha;
}];
}
targetAlpha will always be the opposite of the current state (1 or 0), and if it's 0 then the y position will be set to the bottom of the parent view. Using the new-school UIView animations API with blocks we can execute these changes to the scroll view over 1 second (in my example).

ScrollView appers from down side of screen with animation. I think this up-animation is what you want.
// ScrollView appearing animation
- (void)ScrollViewUpAnimation
{
// put the scroll view out of screen
CGRect frame = ScrollView.frame;
[self.view addSubview:ScrollView];
ScrollView.frame = CGRectMake(0, 460, frame.size.width, frame.size.height);
// setting for animation
CGPoint fromPt = ScrollView.layer.position;
CGPoint toPt = CGPointMake(fromPt.x, fromPt.y - frame.size.height - 44);
CABasicAnimation* anime =
[CABasicAnimation animationWithKeyPath:#"position"];
anime.duration = 0.2;
anime.fromValue = [NSValue valueWithCGPoint:fromPt];
anime.toValue = [NSValue valueWithCGPoint:toPt];
// change the position of Scroll View when animation start
[ScrollView.layer addAnimation:anime forKey:#"animatePosition"];
ScrollView.layer.position = toPt;
}

Related

animate or just update constraints works on only half of the views I changed

I have a container view with 4 buttons ( see drawing )
I want to animate the button 3 and 4 ( both have 90 hight )
And make the container view change accordingly
So I make both buttons height to be 0, by changing its frame.
And change container hight constraint constant change from 200 to 100
and then call layoutIfNeeded.
I made a button for testing that dose that code.
the problem is that only one of the changes happen !
- (IBAction)testButton:(UITapGestureRecognizer *)sender {
CGRect frame = button3.frame;
frame.size.height = 0;
button3.frame = frame;
CGRect frame1 = button4.frame;
frame1.size.height = 0;
button4.frame = frame1;
buttonContainerHeightConstraint.constant = 100;
[UIView animateWithDuration:0.2 animations:^{
[self.view layoutIfNeeded];
}];
when I click the test button only the container changes it size ! button 3 and 4 are still in the same place but because the container is 100 in height now they are "outside" of it.
only if I click the testButton again only then button 3 and 4 disappears as well
I suppurated it so it will look the way I probably would use it.
- (void)showButton3:(Boolean)show {
CGRect frame = button3.frame;
frame.size.height = show ? 90 : 0;
button3.frame = frame;
[UIView animateWithDuration:0.2 animations:^{
[self.view layoutIfNeeded];
}];
}
- (void)showButton4:(Boolean)show {
CGRect frame1 = button4.frame;
frame1.size.height = show ? 90 : 0;
button4.frame = frame1;
[UIView animateWithDuration:0.2 animations:^{
[self.view layoutIfNeeded];
}];
}
- (void)shrinkBtnContainer:(Boolean)shrink {
buttonContainerHeightConstraint.constant = shrink ? 100 : 200;
[UIView animateWithDuration:0.2 animations:^{
[self.view layoutIfNeeded];
}];
}
- (IBAction)testButton:(UITapGestureRecognizer *)sender {
[self showButton3:false];
[self showButton4:false];
[self shrinkBtnContainer:true];
}
and same thing happens after I click the button it first hides the container, and If I click again it hides the buttons.
So what I am doing wrong here ?
Side notes:
*I work on ios7 so no stackViews and no anchors :(
*I tried to do it without the animation block and I get the same effect.
EDIT*
in the end I deleted buttonContainer hight constraint, made both bottom buttons to have constraint to the buttonContainer and when the 2 button height become 0 ( via height constraint, not frame change ) the container automatically shrinks with them to maintain bottom constraint.
I still want to know why it didn't work at the first place tho

How to Generate a Shockwave Effect

I would like to generate a shockwave effect when I tap on a circular UIView. The effect I'm looking for is very similar to 'Circadia' on the App Store.
(source: mzstatic.com)
Note the circular line that is expanding from the centre view. I couldn't find any kind of tutorial, so I tried the effect using a cheat:
-(void)startShockwave:(UIView *)target
{
// Replace the view tapped with one that will expand
UIView *wave = [[UIView alloc]initWithFrame:target.frame];
wave.backgroundColor = target.backgroundColor;
wave.alpha = 0.5;
wave.layer.masksToBounds = YES;
wave.layer.cornerRadius = wave.frame.size.width / 2;
// Hide it below the original view
[self.view insertSubview:wave belowSubview:target];
CGRect frame = wave.frame;
// Create a view that is the same colour as self.view to make it look like a hole
UIView *center = [[UIView alloc]initWithFrame:CGRectMake(frame.origin.x + 10, frame.origin.y + 10, frame.size.width - 20, frame.size.height - 20)];
center.backgroundColor = self.view.backgroundColor;
center.layer.masksToBounds = YES;
center.layer.cornerRadius = center.frame.size.width / 2;
[self.view insertSubview:center aboveSubview:wave];
// Hide the original view
target.alpha = 0;
// IMPORTANT: I send these views behind the others so that center does not overlap them
[self.view sendSubviewToBack:center];
[self.view sendSubviewToBack:wave];
[UIView animateWithDuration:0.4 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
CGAffineTransform waveTransform = wave.transform;
CGAffineTransform centerTransform = center.transform;
// Expand the views to look like a shockwave
wave.transform = CGAffineTransformScale(waveTransform, 4, 4);
center.transform = CGAffineTransformScale(centerTransform, 5.75, 5.75);
// Fade the wave out to nothing
wave.alpha = 0;
} completion:^(BOOL finished) {
// Remove the shockwave
[wave removeFromSuperview];
[center removeFromSuperview];
}];
}
This works quite well...
...With only one shockwave. However, when they intersect, one center overlaps the other due to the most recent shockwave being sent to the back.
I would prefer intersecting shockwaves to be more like this:
I'm not sure how to create this type of effect, however, so any help is much appreciated!
Use [UIColor clearColor] to make the center of your circle transparent (so you can see interface elements residing beneath it).
center.backgroundColor = [UIColor clearColor];
It's a quick fix! You already did most of it. Just change this line:
center.backgroundColor = self.view.backgroundColor;
to
center.backgroundColor = [UIColor clearColor];

Changing the position of UIView

I need to set the position of UIView. The code below shows how I do it. But it does not work. How do I do this?
- (void)viewDidLoad
{
[super viewDidLoad];
CGRect frame = myview.frame;
frame.origin.x = myview.frame.origin.x;
frame.origin.y = 0;
myview.frame = frame;
NSLog(#"%d", frame.origin.y );
}
UIView's have a center property..if you want to change the position then just use that... rather to resize whole view
myview.center = CGPointMake(50, 250);
Hope it helps you.
Make sure that your OUTLET is connected to your view in the nib file.
Try to do this in viewDidAppear method,it works for me.
Move view/ change the position of view with animation
if you want to change the position of View as you want then just use following lines of code :
.h file :
- (void)moveView:(UIView *)view withDuration:(NSTimeInterval)duration
andCurve:(int)curve inDirection_X:(CGFloat)x inDirection_Y:(CGFloat)y;
.m file :
- (void)moveView:(UIView *)view withDuration:(NSTimeInterval)duration
andCurve:(int)curve inDirection_X:(CGFloat)x inDirection_Y:(CGFloat)y
{
// Setup the animation
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:duration];
[UIView setAnimationCurve:curve];
[UIView setAnimationBeginsFromCurrentState:YES];
// The transform matrix
CGAffineTransform transform = CGAffineTransformMakeTranslation(x, y);
view.transform = transform;
// Commit the changes
[UIView commitAnimations];
}
Note : To call above method anywhere just do like it ,
As per your requirement i.e. how to move view/ change the position of view with animation
[self moveView:mFrontSideView withDuration:2.0 andCurve:0 inDirection_X: 0.0 inDirection_Y: mBackSideView.center.y + 100.0];

UIButton rotation animation not rotating back with CGAffineTransformMakeRotation

I have a button (openMenu) that I am animating down (works fine) and rotate (works the first time) with a "drawer". The first time it rotates it works.. but when I try to rotate again it wigs out and hides the image and shows the button title? Any ideas of why? I need it to just rotate back another 45 degrees. Don't know why it would do this.
Also - see GIF image below so you see what is happening.
- (void)viewDidLoad
{
[super viewDidLoad];
draw1 = 0;
scrollView.frame = CGRectMake(0, -200, 768, 200);
[scrollView setContentSize:CGSizeMake(768, 200)];
openMenu.frame = CGRectMake(680, 100, 55, 55);
}
- (IBAction)openMenu:(id)sender {
if (draw1 == 0) {
draw1 = 1;
CGRect optionsDrawer = scrollView.frame;
CGRect optionsButton = openMenu.frame;
optionsDrawer.origin.y += 200;
optionsButton.origin.y += 200;
[UIView animateWithDuration:0.5
animations:^{
scrollView.frame = optionsDrawer;
openMenu.frame = optionsButton;
openMenu.transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(45));
}];
} else {
draw1 = 0;
CGRect optionsDrawer = scrollView.frame;
CGRect optionsButton = openMenu.frame;
optionsDrawer.origin.y -= 200;
optionsButton.origin.y -= 200;
[UIView animateWithDuration:0.5
animations:^{
scrollView.frame = optionsDrawer;
openMenu.frame = optionsButton;
openMenu.transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(45));
}];
}
}
Do like this, i am using layers to animate, it is easy, once u rotate, dont need to rotate again, just brings back to original state. I did like this it works for me, just try this.
since i am using layers add "QuartzCore" library and import this
#import<QuartzCore/QuartzCore.h> //include this
if (draw1 == 0)
{
....//your code
[UIView animateWithDuration:0.1 animations:^{
detailButton.layer.transform = CATransform3DMakeRotation((180) * 45, 0, 0, 1);
}];
}
else
{
....//your code
[UIView animateWithDuration:0.1 animations:^{
detailButton.transform = CGAffineTransformIdentity; //brings back to original position by animating
}];
}
hope this helps u :)
If you want to rotate the button back - you need to provide negative number as the value for CGAffineTransformMakeRotation().
Here is the snippet from Apple Docs:
CGAffineTransformMakeRotation()
Returns an affine transformation matrix constructed from a rotation
value you provide.
CGAffineTransform CGAffineTransformMakeRotation ( CGFloat angle );
The angle, in radians, by which this matrix rotates
the coordinate system axes. In iOS, a positive value specifies
counterclockwise rotation and a negative value specifies clockwise
rotation. In OS X, a positive value specifies clockwise rotation and a
negative value specifies counterclockwise rotation.
Hope this helps!

iOS/Objective-C: transitionWithView custom animation block resizes view immediately, not over duration

The following code is a method I created inside a UIViewController to popup/down a "reader" overlay on top of the controller's own view. The intention is for the reader to begin as transparent, size zero, at a specific point. "Popup" is then animated as increasing in opacity and size, and shifts towards an application frame central position. "Popdown" is subsequently animated as the reverse, shrinking back whilst moving toward a specified location, fading out.
The popup code works exactly as desired. However, the popdown version (i.e. code executed if isPopup == NO) immediately changes the bounds rather than doing so gradually. Thus the popdown animation shows from the beginning a 1 pixel square view moving towards its destination and fading out.
-(void)popupReader:(BOOL)isPopup from:(CGPoint)loc {
CGFloat newAlpha = 0.0f;
CGPoint newCenter = CGPointZero;
CGRect newBounds = CGRectZero;
CGRect appFrame = [UIScreen mainScreen].applicationFrame;
CGSize readerSize = [self viewSize];
if (isPopup) {
newAlpha = 1.0f;
newCenter = CGPointMake(appFrame.origin.x+appFrame.size.width/2,
appFrame.origin.y+appFrame.size.height/2);
newBounds = CGRectMake(0,0,readerSize.width,readerSize.height);
[self.view setAlpha:0.0f];
[self.view setCenter:loc];
[self.view setBounds:CGRectMake(0, 0, 0, 0)];
} else {
newCenter = loc;
newBounds = CGRectMake(0,0,1,1);
}
const CGFloat animDur = 0.3f;
[UIView transitionWithView:self.view
duration:animDur
options:UIViewAnimationOptionTransitionNone|UIViewAnimationOptionCurveEaseOut
animations:^{
self.view.alpha = newAlpha;
self.view.center = newCenter;
self.view.bounds = newBounds;
}
completion:nil];
}
I've already tried animating just the frame, rather than bounds and center, but the result was identical.
Does anyone know why this is happening, and how I can overcome this problem?
Many thanks for your time.
from the docs:
UIViewAnimationOptionTransitionNone -
An option for specifying that no transition should occur.
try one of:
UIViewAnimationOptionTransitionFlipFromLeft
UIViewAnimationOptionTransitionFlipFromRight
UIViewAnimationOptionTransitionCurlUp
UIViewAnimationOptionTransitionCurlDown
Edit:
Or if you're just looking to animate those values, try
[UIView animateWithDuration:(NSTimeInterval)duration
animations:(void (^)(void))animations
completion:(void (^)(BOOL finished))completion];