Rotating after an animation - objective-c

I have a UIViewController subclass that can display animations (mostly changing alphas on imageview subviews). If an animation is occurring when the device is rotated, I would like the rotation animation to occur after the current animation block completes. How can I make this happen?

When you call a method that animated an image, set some BOOLean value to NO and conditionally allow rotation in the -shouldAutorotateToInterfaceOrientation method. Something like this:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
if (!someBool)
return NO;
return YES;
}

Related

NSScrollView doesn't call drawRect for documentView

I have NSScrollView with drawable content.
It works fine with scrolling until I press Cmd+Tab or hide window in any other way.
When I open window with scrollView second time it doesn't redraw content on scrolling.
so drawRect function for documentView doesn't work anymore.
setting content view (I need to redraw it on scrolling because self.documentView is much wider than window's width)
[self.documentScroll setDocumentView:self.documentView];
in NSClipView
-(void) drawRect:(NSRect)dirtyRect {
[self setCopiesOnScroll: NO];
[super drawRect:dirtyRect];
NSArray* ar = self.subviews;
NSView* docView = ar.firstObject;
BOOL b = docView.needsDisplay;
}
docView.needsDisplay is always NO after window was hidden and shown second time. On application's launch it's always YES and drawRect method calls for documentView on every scrolling event

UIView animations - When does it animate certain properties like scale and position?

I'm currently working with a UITableViewController which contains some UITableViewCells subclasses.
When layoutSubviews is called on these UITableViewCells, I change some of the cells' subviews' scales and positions depending on the width and height of the contentView. (The UITableViewCells have some subviews, and I change their scales and positions)
A good example is toggling edit mode, since it shortens the contentView by a bit.
When I do this, the scales and positions of my UITableViewCell's subview do animate
func toggleEdit() {
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(0.35)
self.tableView.beginUpdates()
self.tableView.editing = !self.tableView.editing
self.tableView.endUpdates()
UIView.commitAnimations()
}
When I do this, ONLY the positions animate, the scales change immediately which looks really ugly:
func toggleEdit() {
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(0.35)
self.tableView.editing = !self.tableView.editing
UIView.commitAnimations()
}
I kind of found this out by accident, so I'm wondering now what kind of magic begin/end tableViewUpdate does, and how I can control myself in any scenario which properties should animate and which shouldn't.
The docs state
When you call endUpdates, UITableView animates the operations simultaneously
You could try changing things that you don't want animated in a performWithoutAnimation(_:) block
UIView.performWithoutAnimation {
// things you don't want to animate
}

How to not animate transformation?

How can I not animate transformation during moving some frame? I have some block with animation:
[UIView animateWithDuration:.2 animations:^{
self.center = [ViewController fitPointToNet:self.center];
[self.delegate repaint];
}];
And repaint call paintInView method. This method draw some figure (e.g. line) and rotate them. I want to animation look like line move to destination point - now it move and rotate.
- (void)paintInView:(UIView*)view
{
//some drawing code
line.transform = CGAffineTransformMakeRotation(M_PI);
//some drawing code
}
Anyone can help?
You're calling the repaint method from within the animation block - so any changes to animatable properties of any view will be animated.
You should call that method from the completion block of the animation instead - use the animateWithDuration:animations:completion method instead of the one you are using now.
This will perform the transform without animating, after the animation has completed.

Squashed and distorted view after device rotation

I've been reading through theses pages for a while now and have been having some trouble getting my CGRect to load properly. I learned it was because I'm forcing an orientation after viewDidLoad runs, and I'm trying to get the CGRect to draw again after. Basically, this is what I'm looking at:
-(void)viewDidLoad
{
//mybutton.frame = CGRectMake(...);
//...
}
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return UIInterfaceOrientationIsLandscape(interfaceOrientation);
}
When the view appears, the CGRect is very squashed and distorted, due to the rotation of the view.
You could extract the drawing code out from viewDidLoad and into its own function. Then you can call the function from within the shouldAutorotateToInterfaceOrientation and from the viewDidLoad.

Why aren't my views being positioned correctly on interfaceOrientation changes?

I have a UIViewController one UIWebView in it. I'd like the UIWebView to be positioned in the centre of the iPad screen in landscape and portrait modes. So, I've implemented it like this
// UIViewController
// InfoGraphicView is the UIWebView
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Overriden to allow any orientation.
return YES;
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration {
if (toInterfaceOrientation == UIInterfaceOrientationPortrait ||
toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) {
[self layoutPortrait];
} else {
[self layoutLandscape];
}
}
- (void)layoutLandscape {
NSLog(#"Layout Landscape");
infoGraphicView.frame = CGRectMake(100, 100, 936, 700);
}
- (void)layoutPortrait {
NSLog(#"Layout Portrait");
infoGraphicView.frame = CGRectMake(100, 100, 700, 936);
}
However, it's not behaving as I expected. In the above code, I would expectt he UIWebView to be 100px (or points or whatever the unit is) away from the top and the left. But it's not. In Portrait mode it appears flush with the top left of the screen, and in Landscape mode it seems to be partially offscreen in the top left.
If I set the frame as CGRectMake(-100, 100, 700, 936) then I get it positioned in the center of the screen as I'd like it to be, but I've no idea why.
As usual, there's most likely something simple I'm overlooking but I can't figure it out. Any help greatly appreciated as always.
The coordinates you set on infoGraphicView are relative to its superview, not to the screen generally. And views don't necessarily clip their subviews. Furthermore, the shape set automatically to self.view will depend on the scaling flags set in Interface Builder. However, I think that by default it is set to fill the whole screen.
That said, I think the mistake is in your use of willRotateToInterfaceOrientation:duration:. That is called before the rotation begins, so self.view has the old size (ie, it'll still be portrait sized if rotating from portrait to landscape and vice versa). Probably better to hook willAnimateRotationToInterfaceOrientation:duration: — then the correct size has been set and you'll be within the CoreAnimation block so your view will grow/shrink as part of the rotation animation.
It's also worth checking which resizing flags you have set on infoGraphicView. They'll take effect automatically, in addition to any changes you make. So you probably want to disable them all.
This probably is an issue with the view that the web view is in. The coordinate system used is that of the view’s superview. If that view isn’t being resized on rotation, then you’ll see unexpected layout like this. You can access the superview of a view through the superview property; one way to see its frame would be to use its description. Put this line in one of your layout methods:
NSLog(#"Superview: %#", [infoGraphicView superview]);
That should print out a description of the view.
Once you get that figured out, if you want the web view to have the same layout, you can use its autoresizingMask property. If you set it like this:
infoGraphicView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
Then the view will automatically change its width and height to keep the top, left, right, and bottom margins the same.