Moving an Image with a button - objective-c

I've got a button. After you click it, it disappears. I want to make it move a UIImageView continuously down a page with one click.
I've tried a for loop statement but the Image just drops down 200 y coordinates. This is the statement:
for (int i = 1; i <= 200; i++)
{
CGRect oldFrame = _rocketship.frame;
CGRect newFrame = CGRectMake(oldFrame.origin.x, oldFrame.origin.y + 1, oldFrame.size.width, oldFrame.size.height);
_rocketship.frame = newFrame;
}
[self.rocketship startAnimating];
I would think that the Image would continuously go down the page, hence the for statement, but it doesn't. Is there any other way to do this?
(PS: The while loop statement does the same thing)

In IOS the screen is updated when the main thread is available and not currently running anything.
What you are doing is not going to work ever. All you are doing is setting the views position to off the screen because the for loop will finish before the vote is updated.
What you need to do is use core animation.
There is a class method on UIView that starts with "aninateWithDuration". There are several different methods.
These are the methods that you need to use in order to animate anything in IOS.
I can't answer with code at the moment as I'm on a mobile but check the docs for UIView. It will have documentation for these animation methods.
The method is...
[UIView animateWithDuration:1.0
animations:^{
// set the end position here
}];
Also I have a feeling that you will probably have auto layout on. If so let me know because there are different ways of animating if that is the case.

Try something like this instead:
[UIView animateWithDuration:1.0 animations:^{
CGRect oldFrame = _rocketship.frame;
CGRect newFrame = CGRectMake(oldFrame.origin.x, oldFrame.origin.y + 200, oldFrame.size.width, oldFrame.size.height);
_rocketship.frame = newFrame;
}];

Josue Espinosa is almost correct
[UIView animationWithDuration:1.0{
CGRect oldFrame = _rocketship.frame;
CGRect newFrame = CGRectMake(oldFrame.origin.x, oldFrame.origin.y + 1, oldFrame.size.width, oldFrame.size.height);
_rocketship.frame = newFrame;
but you probably want to move the image more then 1 pixel. the way this work is that this will animate the movement to the new location from point A to point B taking the time duration. in the code above it will take 1 second to move the button from point A to point B so say you want to move the button down 200 pixel the coude should be:
[UIView animationWithDuration:1.0
animations:^{
CGRect oldFrame = _rocketship.frame;
CGRect newFrame = CGRectMake(oldFrame.origin.x, oldFrame.origin.y + 200, oldFrame.size.width, oldFrame.size.height);
_rocketship.frame = newFrame;
}];
this will basically animate any visual change you set as being the end result. from state A to state B.

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

Hide and show scrollview with animation

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

ios simple bar graph with animation

I need to show 2 bar graphs in my app, I dont want to use core-plot as is overkill to show just 2 bars with variant height, [UIimageView with box.png]
i have done some tests just using UIView animations, wich seem to be enough to make the bar grow or shrink, [the problem is that the height is dependant on the starting point, so my bar doesnt have a point 0 for Y, wich changes with the height for the bar]
so how could i set a point 0 for my Y axis?, so I just have to think of heigh, and not the starting point as well?
or shall i go with some bar generator framework that is not so over kill as core-plot,,
what is the simplest, lightest weight?
power-plot
ecgraph, Other?
PS. the other point is that i need to have a custom background for the chart, and custom bars thats why im using box.png for the bars]
the code...
viewDidLoad { ***
CGRect chartbackGroundImageRect = CGRectMake(150, 20, 632, 653);
UIImageView *chartbackGroundImage = [[UIImageView alloc] initWithFrame:chartbackGroundImageRect];
[chartbackGroundImage setImage:[UIImage imageNamed:#"chartArtBgnd.png"]];
chartbackGroundImage.opaque = YES; // explicitly opaque for performance
[self.view addSubview:chartbackGroundImage];
[chartbackGroundImage release];
CGRect leftBarImageRect = CGRectMake(550, 550, 81, 40);
leftBarImage = [[UIImageView alloc] initWithFrame:leftBarImageRect];
[leftBarImage setImage:[UIImage imageNamed:#"leftBar.png"]];
leftBarImage.opaque = YES; // explicitly opaque for performance
[self.view addSubview:leftBarImage];
[leftBarImage release];
***}
testBarAnimation {***
// Setup the animation
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.2]; //animation for arrow
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
[UIView setAnimationBeginsFromCurrentState:YES];
CGRect newFrame = CGRectMake(550, 300, 81, 290);
leftBarImage.frame = newFrame;
[UIView commitAnimations];
***}
thanks a lot!
Define a utility function:
CGRect modifyRectByHeight(CGRect originalRect, CGFloat newHeight)
{
CGRect result = originalRect;
result.origin.y += height;
result.size.height += height;
return result;
}
Then use as follows:
leftBarImage.frame = modifyRectByHeight( leftBarImage.frame, 150);
I dont know, it's applicable to your project. But I used different approach, as iOS doesn't have good libraries for Chart.
I used UIWebview with HTML5 /CSS based free chart engines available on Web. For me its working fine, Bit slow than native charts would be but enough for my project

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