I am trying to fade out whole view but one specific subview, which would emphasize the subview with the more clearer look. Let's say if self.view has 5 textfields and 2 UIView as subviews and I want 1 UIView to be emphasized. Is there a way to fade out/in the whole self.view with 5 textfields and 1 UIView without touching the emphasized UIView?
I have already tried to use method
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion
such as:
[UIView animateWithDuration:0.75
animations:^{
self.view.alpha = 0.5f;
}
completion:^(BOOL finished){self.view.layer.shouldRasterize = NO;}];
But, it seemed like whole subviews are affected by the UIView animation above. Any advice or tip will be greatly appreciated.
If you lower the alpha of a UIView, all it's subview's alpha will be lowered. A solution to your problem would be to lower the alpha of each subview individually, except the one you want:
UIView emphasizedView = ...
[UIView animateWithDuration:0.75
animations:^{
for (UIView *view in self.view.subviews) {
if (view != emphasizedView) {
view.alpha = 0.5f;
} else {
view.alpha = 1;
}
}
}
completion:^(BOOL finished){self.view.layer.shouldRasterize = NO;}];
Related
I created uiview custom class and implemented in Main View Controller
-(KPHomeChartCategory *)chartCategory {
if (!_chartCategory) {
_chartCategory = [[KPHomeChartCategory alloc] init];
_chartCategory.delegate = self;
_chartCategory.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:_chartCategory];
[self.chartCategory.topAnchor constraintEqualToAnchor:self.topAnchor constant:-7.5].active = YES;
[self.chartCategory.rightAnchor constraintEqualToAnchor:self.rightAnchor].active = YES;
self.chartCategoryLeftAnchor = [self.chartCategory.leftAnchor constraintEqualToAnchor:self.rightAnchor];
self.chartCategoryLeftAnchor.active = YES;
[self.chartCategory.heightAnchor constraintEqualToConstant:100].active = YES;
}
return _chartCategory;
}
I animated uiview custom class (KPHomeChartCategory) constraints in this way
-(void)openPanelTagAnimation {
self.chartCategoryLeftAnchor.active = NO;
self.chartCategoryLeftAnchor = [self.chartCategory.leftAnchor constraintEqualToAnchor:self.rightAnchor constant:-self.frame.size.width +105];
self.chartCategoryLeftAnchor.active = YES;
[UIView animateWithDuration:.6 delay:0 usingSpringWithDamping:1 initialSpringVelocity:1 options:UIViewAnimationOptionCurveEaseOut animations:^{
self.customSwitch.alpha = 0;
[self layoutIfNeeded];
} completion:nil];
}
Now if you look at the video, you will notice that the first time I show customView, my collection view is shown from above but afterwards the animation seems to be perfectly straightforward ... can you make me understand why this thing?
Video Link
VIDEO ANIMATION
Why my animation first starts from top to bottom and only then is linear ? (the linear animation from right to left is the correct one and should be the first time the custom view is animated)
In the animation you posted the cells are animating because their initial size is CGSizeZero or some value close to that and then the collection view layout invalidates so their size is increased. You could avoid this by animating the transform property of your collection view. This will like solve the problem you mention here as well. For example in a simple demo, I can place a collection view by pinning top, left and right to its superview with a constant height. I set the cell sizes programmatically like:
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return CGSizeMake(collectionView.bounds.size.width / 3.0, collectionView.bounds.size.height);
}
Then I use a CGAffineTransform to move the collection view off screen. For example:
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
self.collectionView.transform = CGAffineTransformTranslate(CGAffineTransformIdentity, self.view.bounds.size.width, 0.0);
}
Finally, when I want to perform an animation, I set the transform back to its identity:
- (void)animate {
// Reversing and repeating for the sake of testing
[UIView animateWithDuration:0.5 delay:0.0 options:UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse animations:^{
self.collectionView.transform = CGAffineTransformIdentity;
} completion:nil];
}
Using this method ensures that cells are always the same size and thus won't animate when constraints change in an animation block.
When I change constraints in my demo project this is the animation, notice the cell sizes change on the initial animation.
The same animation when setting transform:
I am trying to get my CalendarFlyoutView to Fade in and expand from the top right corner in Xcode and Objective-C. This is the method existing in the implementation file:
- (void)presentInView:(UIView *)holderView completion:(void (^) (void))completion
{
// make this view stretch
CGRect upperRightR = CGRectMake (CGRectRight (holderView.bounds), 0, 1, 1);
[self setFrame:upperRightR];
self.clipsToBounds = YES;
self.alpha = 0.0;
[holderView addSubview:self];
[UIView animateWithDuration:kAnimation_ExpandCalendarDuration
animations:^{
[self setFrame:holderView.bounds];
self.alpha = 1.0;
}
completion:^(BOOL finished){
}];
}
How do you get this to fade in and expand from the top right corner? Any help would be greatly appreciated.
This seems correct, maybe check the auto-layout for the top right corner? This could cause the issue...
I want to create a bouncy animation like in the Skitch application - when i press a button, a subview (simple view with several buttons) will appear from the side and will bounce a bit until it stops.
I can't find any standard animation that does that, so how i can implement this animation?
You can try this :
// Hide your view by setting its position to outside of the bounds of the screen
// Whenever you want, call this :
[UIView animateWithDuration:0.5
delay:0
usingSpringWithDamping:0.5
initialSpringVelocity:0
options:UIViewAnimationOptionCurveLinear
animations:^{
// Set your final view position here
}
completion:^(BOOL finished) {
}];
This method is the same as the usual animateWithDuration: but it introduces a spring animation.
Use UIView method:
+ (void)animateWithDuration:(NSTimeInterval)duration
delay:(NSTimeInterval)delay
usingSpringWithDamping:(CGFloat)dampingRatio
initialSpringVelocity:(CGFloat)velocity
options:(UIViewAnimationOptions)options
animations:(void (^)(void))animations
completion:(void (^)(BOOL finished))completion
This will do what you want
Use the UIView method, If you want bouncing effect. Then you need to nested the animation process and give the frame as needed for that view. Here's the example:
CGRect frameOnStart = CGRectMake(200,200 ,60 ,60); //On start show small view
CGRect frameOnAnimate = CGRectMake(80,80 ,150 , 150); //while animate show large view
CGRect frameAfterAnimate = CGRectMake(100,100,120 ,120); //after animate large take it back to original frame. SO it loos like bouncing animation
// Whenever you want, call this :
[UIView animateWithDuration:0.5
delay:0
usingSpringWithDamping:0.5
initialSpringVelocity:0
options:UIViewAnimationOptionCurveLinear
animations:^{
// Set your on Animate position here
view.frame = frameOnAnimate;
}
completion:^(BOOL finished) {
[UIView animateWithDuration:0.5
delay:0
usingSpringWithDamping:0.5
initialSpringVelocity:0
options:UIViewAnimationOptionCurveLinear
animations:^{
// Set your final view position here
view.frame = frameAfterAnimate;
}
completion:^(BOOL finished) {
}]
}];
Thanks.
A custom view I created is being animated by its container - in my view I update portions of the subviews with other animations (for instance a UICOllectionView)
I see that this is throwing errors
*** Assertion failure in -[UICollectionView _endItemAnimations
Digging around I see that my view has animations attached to it:
<GeneratorView: 0x15b45950; frame = (0 0; 320 199); animations = { position=<CABasicAnimation: 0x145540a0>; }; layer = <CALayer: 0x15b49410>>
So now before performing animation operations I check:
NSArray *animationKeys = [self.layer animationKeys];
for (NSString *key in animationKeys) {
CAAnimation *animation = [self.layer animationForKey:key];
}
and I see that animation objects are returned:
at this point I would like to "wait" until all animations have completed before updating self.
I see that I can add myself as the CAAnimation delegate.
But this is a bit messy and hard to track.
Is there an easier way using a UIView method - much higher level?
You can use UIView method to do the animation in the container:
[UIView animateWithDuration: animations: completion:];
[UIView animateWithDuration: delay: options: animations: completion:];
You should add properties to your custom view:
#property BOOL isAnimating;
In the container run the animation block and change view isAnimating property.
This method accept block which will be fired when the animation complete.
Example:
[UIView animateWithDuration:1.0 animations:^{
//Your animation block
view1.isAnimating = YES;
view1.frame = CGRectMake(50.0f, 50.0f, 100.0f, 100.0f);
// etc.
}completion:^(BOOL finished){
view1.isAnimating = NO;
NSLog(#"Animation completed.");
}];
Now it your view you can see if the view is animating:
if (self.isAnimating)
NSLog(#"view is animating");
Ithink you can you that :
#interface UIView(UIViewAnimationWithBlocks)
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion NS_AVAILABLE_IOS(4_0);
Hope that will help
Using UIView's animateWithDuration:animations:completion:, I'm resizing a UIView and a subview of that UIView which is a subclass of UITableView.
The UIView resizes fine, but the UITableView doesn't. It does move around a little, but the frame does not update properly and reverts to its original state.
Edit: if I move the resizing to the completion block.... it works. What gives?
tweetTable.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[tweetTable endUpdates];
[UIView animateWithDuration:DURATION animations:^{
CGRect leftFrame = leftPane.frame;
leftFrame.size.width = self.view.frame.size.width - MARGIN;
leftPane.frame = leftFrame;
leftPaneButton.frame = leftFrame;
CGRect tweetFrame = tweetTable.frame;
tweetFrame.size.width = leftPane.frame.size.width;
NSLog(#"%f to %f", tweetTable.frame.size.width, leftPane.frame.size.width);
tweetTable.frame = tweetFrame;
tweetTable.backgroundColor = [UIColor redColor];
tweetTable.alpha = 0.5f;
sideInfo.center = CGPointMake(self.view.frame.size.width - MARGIN + (sideInfo.frame.size.width / 2), sideInfo.center.y);
rightPaneButton.center = sideInfo.center;
} completion:^(BOOL finished) {
leftExtended = TRUE;
[tweetTable beginUpdates];
}];
Check in your storyboard if the UIView has Autoresize Subviews checked. That means that it resizes all of its subviews when the view itself gets resized. That would explain why it works in the completion block.