I have a subclass of UITableViewCell with button inside of it. The button have clear backgroundColor with some border. I want to do a fill in animation starting from the center of the button. My problem is that animation completes immediately. Here's my code, I've tried doing this in 2 different ways.
- (void)goingButtonAnimation {
UIView *goingButtonBackgroundView = [[UIView alloc] initWithFrame:CGRectMake(self.goingButton.center.x, self.goingButton.center.y, 0., 0.)];
goingButtonBackgroundView.layer.cornerRadius = 2.;
goingButtonBackgroundView.backgroundColor = [UIColor blackColor];
[self insertSubview:goingButtonBackgroundView belowSubview:self.goingButton];
[UIView animateWithDuration:2. animations:^{
goingButtonBackgroundView.frame = self.goingButton.frame;
}];
}
I've also tried this:
goingButtonBackgroundView.transform = CGAffineTransformMakeScale(0.1, 0.1);
[UIView animateWithDuration:2. animations:^{
goingButtonBackgroundView.transform = CGAffineTransformMakeScale(1.0, 1.0);
goingButtonBackgroundView.center = self.goingButton.center;
}];
But the animation completes immediately in each case. goingButtonAnimation method is called after tapping on self.goingButton
My problem was that after calling goingButtonAnimation I called [self.tableView reloadData]
Related
After I had set an image to an UIButton called bigIcon, I put it inside animateWithDuration with the change of its frame, then I ran the code, the button size changed instantly (has no animation), but it move from origin to destination slowly (has animation), how can I solve this problem? I found out that if I did set an image to the button this problem will disappear.
here is the code:
- (void)bigImage:(MCGodCell *)godCell withImage:(UIImage *)image {
self.bigIcon = [UIButton new];
self.bigIcon.adjustsImageWhenHighlighted = NO;
[self.bigIcon setBackgroundImage:image forState:UIControlStateNormal];
CGFloat iconX = self.tableView.frame.size.width / 2.0;
CGFloat iconY = self.tableView.frame.size.height / 2.0;
self.bigIcon.frame = CGRectMake(iconX, iconY, 1, 1);
[self.tableView addSubview:self.bigIcon];
CGFloat iconW = self.tableView.frame.size.width;
CGFloat iconH = iconW;
iconY = (self.view.frame.size.height - iconH) / 2.0;
[UIView animateWithDuration:0.3 animations:^{
self.bigIcon.frame = CGRectMake(0, iconY, iconW, iconH);
}];
}
You're not seeing the frame change because you're trying to animate it immediately after adding it to the view hierarchy.
UIKit needs to add the button as a subview, and then run the animation on the next UI update pass.
Wrap your animation block inside a dispatch_async block like this:
dispatch_async(dispatch_get_main_queue(), ^{
[UIView animateWithDuration:0.3 animations:^{
self.bigIcon.frame = CGRectMake(0, iconY, iconW, iconH);
}];
});
I have created custom buttons and worked with custom UIViews in the past. However I am not sure how to go about with this.
I am trying to create something similar to the twitter heart animation.
What I am unable to get is those tiny colored circles around the heart as shown in this gif:
https://dribbble.com/shots/2416983-Twitter-Heart-Animation
Any ideas?
Also is it possible for me to simply have a gif and add the gif as a custom view in a UIButton and play the gif when button is pressed?
Here's a concept:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
UIView *bubble = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 16.0, 16.0)];
bubble.layer.cornerRadius = 8.0;
bubble.center = self.view.center;
bubble.backgroundColor = [UIColor greenColor];
[self.view addSubview:bubble];
UIView *heart = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 100.0, 100.0)];
heart.layer.cornerRadius = 50.0;
heart.center = self.view.center;
heart.backgroundColor = [UIColor blueColor];
[self.view addSubview:heart];
[UIView animateKeyframesWithDuration:2.0
delay:0.0
options:UIViewKeyframeAnimationOptionRepeat
animations:^{
// Heart expands
[UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.10 animations:^{
heart.transform = CGAffineTransformMakeScale(1.3, 1.3);
}];
// Heart contracts.
[UIView addKeyframeWithRelativeStartTime:0.15 relativeDuration:0.25 animations:^{
heart.transform = CGAffineTransformMakeScale(1.0, 1.0);
}];
// Bubble travels.
[UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.4 animations:^{
CGPoint destination = self.view.center;
destination.x += 100;
destination.y -= 100;
bubble.center = destination;
}];
// Bubble shrinks.
[UIView addKeyframeWithRelativeStartTime:0.6 relativeDuration:0.2 animations:^{
bubble.transform = CGAffineTransformMakeScale(0.3, 0.3);
}];
// Bubble fades.
[UIView addKeyframeWithRelativeStartTime:0.8 relativeDuration:0.2 animations:^{
bubble.alpha = 0.0;
}];
} completion:nil];
}
To get the full effect, you will need to add any a few more key frames so the bubble curves around before the fade. Given that you have a couple of bubbles, it might be a good idea to create a key frame generator.
Alternatively, you can use SKEmitterNode and add real particles to your button.
Late Answer but useful to other developers.
Here is the Link for exact same animation: https://github.com/xhamr/fave-button
Same Animation in Objective-C also: https://github.com/tljackyi/fave-button
Much like other apps, my app has a "welcome" page controller with a quick overview of the features. During this overview, I draw a UITabBar and have a circle show where the relevant feature is seen below:
I draw the circle using the following code that is executed every time a page is drawn:
double circleSize = 75;
[circleView removeFromSuperview];
circleView = [[UIView alloc] initWithFrame:CGRectMake(circleX,
circleY,
circleSize,
circleSize)];
circleView.layer.cornerRadius = (circleSize / 2);
circleView.layer.borderColor = [UIColor VancityTransitBlue].CGColor;
circleView.layer.borderWidth = 2;
I wish to have this circle appear to "breath" (grow slowly then shrink back to its original size). I use the exact code from my answer to this question:
[UIView animateWithDuration:1
delay:0
options:UIViewKeyframeAnimationOptionAutoreverse | UIViewKeyframeAnimationOptionRepeat
animations:^{
circleView.transform = CGAffineTransformMakeScale(1.5, 1.5);
}
completion:nil];
This circle is shared across three pages of the page controller and draws just fine. The animation works just fine on the first page, periodically works on the second page, and never works on the third page.
How can I have the animation play on every page for every circle view?
Here is a solution that works across all tabs. The animation can be moved around while in progress. You may want to use a better mechanism to manage the animation so that it can be cancelled efficiently. The code below is implemented in the Tab Controller. Ensure -showOverTabBarItem: and -hideCircleView are executed on main thread. It has been built, linked, ran and tested.
Show
-(void)showOverTabBarItem:(CGFloat)x {
[self hideCircleView];
self.circleView.frame =({
CGRect frame = self.circleView.frame;
frame.origin.x = x;
frame;
});
[self.view addSubview:self.circleView];
[UIView animateWithDuration:1
delay:0
options:UIViewKeyframeAnimationOptionAutoreverse | UIViewKeyframeAnimationOptionRepeat
animations:^{
self.circleView.transform = CGAffineTransformMakeScale(1.5, 1.5);
}
completion:nil];
}
Hide
-(void)hideCircleView
{
[self.circleView removeFromSuperview];
}
Initialize
Such as in viewDidLoad.
double circleSize = 75;
CGFloat circleY = self.view.bounds.size.height-(circleSize/2);
self.circleView = [[UIView alloc] initWithFrame:CGRectMake(0,
circleY,
circleSize,
circleSize)];
self.circleView.layer.cornerRadius = (circleSize / 2);
self.circleView.layer.borderColor = [UIColor blueColor].CGColor;
self.circleView.layer.borderWidth = 2;
Invoke
Pass the horizontal position to your animation: [self showOverTabBarItem: self.view.bounds.size.width/2];
Keep the view around
This is a critical step: when your -removeFromSuperView, you want to make sure that the object does not get recycled.
#interface TabController ()
#property (nonatomic, retain) UIView * circleView;
#end
Why have you alloc the circle every time a page drawn?
You can remove these lines (just need these for the first init):
if (circleView == nil) {
circleView = [[UIView alloc] initWithFrame:CGRectMake(circleX,
circleY,
circleSize,
circleSize)];
circleView.layer.cornerRadius = (circleSize / 2);
circleView.layer.borderColor = [UIColor VancityTransitBlue].CGColor;
circleView.layer.borderWidth = 2;
}
For add to another page: remove from current page
[circleView removeFromSuperview];
[circleView.layer removeAllAnimations];
and then add it to another page:
[self.view addSubView:circleView];
[UIView animateWithDuration:1
delay:0
options:UIViewKeyframeAnimationOptionAutoreverse | UIViewKeyframeAnimationOptionRepeat
animations:^{
circleView.transform = CGAffineTransformMakeScale(1.5, 1.5);
}
completion:nil];
I'm trying to fade a label's background color by using animateWithDuration, but my code isn't working out. Here's what I've got:
.h (in #interface...)
IBOutlet UILabel *labelColor;
.m (in viewDidLoad method)
[labelColor setBackgroundColor:[UIColor colorWithRed:55/255.0 green:191/255.0 blue:122/255.0 alpha:0.3]];
if (labelColor.alpha >= 0.3) {
[UIView animateWithDuration:1 animations:^{
labelColor.alpha = 0.3;
labelColor.alpha = 1.0;
}];
} else if (labelColor.alpha == 1.0) {
labelColor.alpha = 0.3;
}
The color shows up at 0.3 alpha, but doesn't fade from 0.3 to 1.0. I'm trying to make it so the label's color fades from 0.3 to 1.0 in a continuous loop, resetting the alpha to 0.3 as the it hits 1.0.
Any help on how to achieve this is appreciated.
There are a few problems with your current code:
(1) Your else statement will never be called since if labelColor.alpha == 1.0 it will also be >= .3
(2) Having both labelColor.alpha = 0.3; and labelColor.alpha = 1.0; within your animation block means that only the second line (i.e. labelColor.alpha = 1.0;) will dictate the animation
(3) You haven't set up a loop as you'd like
(4) You haven't animated the fade out
If I'm in fact understanding what it is you're trying to accomplish, you could continuously fade the entire UILabel in and out like so:
- (void)performLabelFade {
// If the label is faded out, fade it in
if (labelColor.alpha == .3) {
[UIView animateWithDuration:1 animations:^{
labelColor.alpha = 1.0;
} completion:^(BOOL finished) {
// Repeat the current method (i.e. like a loop)
[self performLabelFade];
}
}
// Else if the label is faded in, fade it out
else if (labelColor.alpha == 1.0) {
[UIView animateWithDuration:1 animations:^{
labelColor.alpha = 0.3;
} completion:^(BOOL finished) {
// Repeat the current method (i.e. like a loop)
[self performLabelFade];
}
}
}
You should set your initial conditions outside of the animation block.
labelColor.alpha = 0.3;
[UIView animateWithDuration:1 animations:^{
labelColor.alpha = 1.0;
}];
Side note: This will fade the alpha value of the entire UILabel, not just the background colour. If you want the text to stick around while your background fades, you should be using something more along these lines:
labelColor.backgroundColor = [UIColor colorWithRed:55/255.0 green:191/255.0 blue:122/255.0 alpha:0.3];
[UIView animateWithDuration:1 animations:^{
labelColor.backgroundColor = [UIColor colorWithRed:55/255.0 green:191/255.0 blue:122/255.0 alpha:1.0];
}];
My main UIViewController has a sub UIView named viewContainer. It has a couple of UIImageViews, UIButtons and UIViews added to it. In my viewDidLoad method I've applied the following to viewContainer:
self.viewContainer.layer.shadowColor = [UIColor blackColor].CGColor;
self.viewContainer.layer.shadowOffset = CGSizeMake(0, 0);
self.viewContainer.layer.shadowOpacity = 1.0;
self.viewContainer.layer.shadowRadius = 10.0;
self.viewContainer.layer.shadowPath = [UIBezierPath bezierPathWithRect:self.viewContainer.layer.bounds].CGPath;
self.viewContainer.backgroundColor = [UIColor blackColor];
self.viewContainer.opaque = YES;
When a user presses a button inside the viewContainer, I perform the following translation:
[UIView animateWithDuration:0.3
animations:^{
[self.viewContainer setCenter: CGPointApplyAffineTransform(self.viewContainer.center, CGAffineTransformConcat(self.viewContainer.transform, CGAffineTransformMakeTranslation(60, 0)))];
}
completion:nil];
My problem is that at the end of the animation, the edge of the view flickers for a fraction of a second (a white vertical line). I've tried setting the frame instead of a transform but still the same result. I'm attempting to do a sort of slide to reveal options thing, which works but flickers on completion.
Any ideas?