Extending a view to the left side, animated - objective-c

I have a view that I want to extend on the left side using an animation. All borders but the left one should remain the same, so the x position and the width of the view are changing.
I use this code:
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:5.0];
self.frame = CGRectMake(self.frame.origin.x-100,
self.frame.origin.y,
self.frame.size.width+100,
self.frame.size.height);
[UIView commitAnimations];
If I run this code, the width of the view is set to the new value immediately and then the view is moved to the new x point, but why? How can I change this behaviour?
Thanks for your ideas!

Your code runs fine for me. How are you running it? Calling -setFrame is the right choice for what you're doing. Here is what my custom view looks like:
#import "TestView.h"
#implementation TestView
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
// Initialization code
}
return self;
}
- (void)dealloc {
[super dealloc];
}
- (void)go;
{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:5.0];
self.frame = CGRectMake(self.frame.origin.x-100,
self.frame.origin.y,
self.frame.size.width+100,
self.frame.size.height);
[UIView commitAnimations];
}
#end
I create an outlet from my view controller of type TestView and connect it and set its type in IB. Then I create a button whose handler calls [customView go]; Seems to work fine.

Okay, I made it woring now. The problem was that my view was a UIButton and I set the title and background with the setBackground:forState: and setTitle:forState:.
It seems that the background of the view is not animatable. I use the work around that I add my own background with a UIImageView.
Thanks for your replies!

Related

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

Fading UIView allows subviews to be seen

I have a UIScrollView which contains various subviews (UIImageViews, UILabels and standard UIViews). Some of the UIImageViews are partially covered by other UIViews.
However, when I fade out the UIScrollView, the partially covered parts of the UIImageViews are being exposed for the brief moment of the animation.
I want to be able to fade the scrollview and all it's contents at the same time in the same animation - i.e. not revealing any of the partially covered images.
If it's not possible, I can always add a UIView on top of all the other controls and fade it from alpha 0 upto 1 to hide everything, but I'm sure there's a way to perform a complete fade on a view and all it's subviews.
I tried this:
[UIView beginAnimations:nil context:NULL];
[scrollViewResults setAlpha:0.0f];
[UIView commitAnimations];
And I've tried this:
- (IBAction)questionGroupChanged:(UIButton*)sender {
[UIView beginAnimations:nil context:NULL];
[self fadeViewHierarchy:scrollViewResults toAlpha:0.0f];
[UIView commitAnimations];
}
- (void)fadeViewHierarchy:(UIView*)parentView toAlpha:(float)alpha {
[parentView setAlpha:alpha];
for (UIView *subView in parentView.subviews) {
[self fadeViewHierarchy:subView toAlpha:alpha];
}
}
But I've still not cracked it. Any ideas?
This happens because of the way the compositor works. You need to enable rasterization on the view's layer when fading it in/out:
view.layer.shouldRasterize = YES;
You should probably only enable this for the duration of the animation because it will take up some extra memory and graphics processing time.
Mike's answer is the correct one and he deserves all credit for this. Just to illustrate, it might look like:
- (void)fadeView:(UIView*)view toAlpha:(CGFloat)alpha
{
view.layer.shouldRasterize = YES;
[UIView animateWithDuration:0.75
animations:^{
view.alpha = alpha;
}
completion:^(BOOL finished){
view.layer.shouldRasterize = NO;
}];
}
Thus, using your scrollViewResults, it would be invoked as:
[self fadeView:scrollViewResults toAlpha:0.0f];
Did you try with UIView class methods +animateWithDuration:* (available on iOS 4 and +)
Like :
- (void)fadeAllViews
{
[UIView animateWithDuration:2
animations:^{
for (UIView *view in allViewsToFade)
view.alpha = 0.0;
}
completion:^(BOOL finished){}
];
}

Remove from superview AND enable user interaction

I'm doing some custom animations to change views in a single method. I already removed "fromView" from superView using [UIView setAnimationDidStopSelector:#selector(removeFromSuperview)], but I also want to enable user interaction after the end of the animation.
Here's my code:
-(void) switchFrom:(UIViewController*) fromViewController To:(UIViewController*) toViewController usingAnimation:(int) animation{
UIView *fromView = fromViewController.view;
UIView *toView = toViewController.view;
/*************** SET ALL DEFAULT TRANSITION SETTINGS ***************/
// Get the current view frame, width and height
CGRect pageFrame = fromView.frame;
CGFloat pageWidth = pageFrame.size.width;
// Create the animation
[UIView beginAnimations:nil context:nil];
// Create the delegate, so the "fromView" is removed after the transition
[UIView setAnimationDelegate: fromView];
[UIView setAnimationDidStopSelector:#selector(removeFromSuperview)];
// Set the transition duration
[UIView setAnimationDuration: 0.4];
/*************** IT DOESN'T WORK AT ALL ***************/
[toView setUserInteractionEnabled:NO];
[UIView setAnimationDelegate: toView];
[UIView setAnimationDidStopSelector:#selector(setUserInteractionEnabled:)];
[toView setUserInteractionEnabled:YES];
// Add the "toView" as subview of "fromView" superview
[fromView.superview addSubview:toView];
switch (animation) {
case AnimationPushFromRigh:{
// Position the "toView" to the right corner of the page
toView.frame = CGRectOffset(pageFrame, pageWidth,0);
// Animate the "fromView" to the left corner of the page
fromView.frame = CGRectOffset(pageFrame, -pageWidth,0);
// Animate the "toView" to the center of the page
toView.frame = pageFrame;
// Animate the "fromView" alpha
fromView.alpha = 0;
// Set and animate the "toView" alpha
toView.alpha = 0;
toView.alpha = 1;
// Commit the animation
[UIView commitAnimations];
}
.
.
.
Any idea how can I call this two methods in setAnimationDidStopSelector and actually make them work together?
EDIT 1
Tried #safecase code like this, replacing this commented block:
/*************** IT DOESN'T WORK AT ALL ***************
[toView setUserInteractionEnabled:NO];
[UIView setAnimationDelegate: toView];
[UIView setAnimationDidStopSelector:#selector(setUserInteractionEnabled:)];
[toView setUserInteractionEnabled:YES];
*************** IT DOESN'T WORK AT ALL ***************/
// Remove the interaction
[toView setUserInteractionEnabled:NO];
[fromView setUserInteractionEnabled:NO];
// Create the animation
[UIView animateWithDuration:0.4 animations:^{
[fromView performSelector:#selector(removeFromSuperview)];
}
completion:^(BOOL finished){
[UIView animateWithDuration:0.4
animations:^{
C6Log(#"finished");
[toView performSelector: #selector(setUserInteractionEnabled:)];
}];
}];
The "toView" is removed instead of the "fromView" is removed :(
The buttons continue to be interactive during the animation
Do you know beginIgnoringInteractionEvents and endIgnoringInteractionEvents?
Normally, if you don't want any userInteraction during an animation, you would use those.
Anyway you still need correct callbacks to trigger them.
You need to define your own method, e.g. remove: and pass that as the selector. In the method, just use the passed UIView to remove it.
-(void)remove:(id)sender {
UIView *v = (UIView*)sender;
[v removeFromSuperview];
}
You can use this:
[UIView animateWithDuration:0.4
animations:^{ [self performSelector:#selector(removeFromSuperview)]; // other code here}
completion:^(BOOL finished){ [UIView animateWithDuration:0.4
animations:^{ [self performSelector:#selector(setUserInteractionEnabled:)]; //other code here}]; }];
Hope helpful.
I think u can use to enable user interaction
self.view.userInteractionEnabled=NO;
I ended up creating a Category extension to UIView… and it finally works!
UIView+Animated.h code
#import <UIKit/UIKit.h>
#interface UIView (Animated)
- (void) finishedAnimation;
#end
UIView+Animated.m code
#import "UIView+Animated.h"
#implementation UIView (Animated)
- (void) finishedAnimation{
C6Log(#"FinishedAnimation!");
[self removeFromSuperview];
[[UIApplication sharedApplication] endIgnoringInteractionEvents];
}
#end
Then, I #imported this extension in my coordinating controller:
C6CoordinatingController.h partial code
#import "UIView+Animated.h"
And called the selector in setAnimationDidStopSelector:
C6CoordinatingController.m partial code
// Create the delegate, so the "fromView" is removed after the transition
[UIView setAnimationDelegate: fromView];
// Ignore interaction events during the animation
[[UIApplication sharedApplication] beginIgnoringInteractionEvents];
// Set the transition duration
[UIView setAnimationDuration: 0.4];
// Call UIView+Animated "finishedAnimation" method when animation stops
[UIView setAnimationDidStopSelector:#selector(finishedAnimation)];
So, I ended up using #jaydee3 and #Mundi concepts and it works like a charm!
Thank you guys!

How to stop an UIView animation

I have several UIImageViews within a UIScrollView that I want to wiggle when the user long-presses one of them. So similar to the behavior you get when you long-press an icon in your iPad/iPhone menu.
So I have the following:
- (void)startWiggling {
for (UIImageView *touchView in [scrollView subviews]) {
[UIView beginAnimations:#"wiggle" context:nil];
[UIView setAnimationDuration:0.1];
[UIView setAnimationRepeatAutoreverses:YES];
[UIView setAnimationRepeatCount:FLT_MAX];
//wiggle 1 degree both sides
touchView.transform = CGAffineTransformMakeRotation();
touchView.transform = CGAffineTransformMakeRotation(-0.0174532925);
[UIView commitAnimations];
}
}
- (void)stopWiggling {
NSLog(#"Stop wiggling");
}
This works fine. The issue is... How can I make it stop wiggling after the user has pressed a button? I have a button and connected it etc and it's reaching the stopWiggling method, so that's fine. But so...
How do I remove the UIView animation from these UIImageViews?
Can I bind this action to the user pressing the home button on their device?
#import <QuartzCore/QuartzCore.h>
then
[myView.layer removeAllAnimations];
or
[self.view.layer removeAllAnimations];

getting a view controller to disappear

I'm trying out a multiple view application, but I can't seem to get the first view controller to go away when I bring in the new view controller. I'm laying the second (coming) view controller at index 0, and it's just placing it in the background. I thought the [going.view removeFromSuperview] would remove the original viewcontroller, but that's not what is happening...
UIViewController *coming = nil;
UIViewController *going = nil;
UIViewAnimationTransition transition;
if (answer == YES)
{
coming = boyController;
going = getInfoController;
transition = UIViewAnimationTransitionFlipFromLeft;
}
else
{
coming = girlController;
going = getInfoController;
transition = UIViewAnimationTransitionFlipFromLeft;
}
NSLog(child);
[UIView setAnimationTransition:transition forView: self.view cache:YES];
[coming viewWillAppear:YES];
[going viewWillDisappear:YES];
[going.view removeFromSuperview];
[self.view insertSubview:coming.view atIndex:0];
[going viewDidDisappear:YES];
[coming viewDidAppear:YES];
[UIView commitAnimations];
First a little refactoring:
coming = (answer ? boyController : girlController);
You can delete going and transition, as they're only used once. Then, to actually do the animation, you need to put everything in the context of an animation block.
[UIView beginAnimations:#"flipAnimation" context:NULL];
[UIView setAnimationTransition:transition forView:self.view cache:YES];
[getInfoController.view removeFromSuperview];
[self.view addSubview:coming.view];
[UIView commitAnimations];
viewWillAppear: and viewWillDisappear: are delegate methods. These will be called automatically on those views' delegates, if any. They shouldn't ever be called manually.