In my iphone application I have several images. lets say some small square images. what I want is I want that small objects appear from the top of the screen at rondom times and leaves the screen from the bottom. I mean, for example, object randomly appeared from the x:30 y:0 point (x value must be random) and leaves from the x:30 y:460 with an animation.
I am programming an 2d racing game and they are the cars. hope it is clear.
edit: well I tried to change the frame the numbers belong to something else. But I could not have the frame of the image and also I could not figure out how to generate position randomly more than one time. since I was planning to put it on the viewDidLoad.
[UIView beginAnimations:#"myAnimation" context:nil];
CGRect Frame = image.frame;
if(Frame.origin.y == 340){
Frame.origin.y = 260;
}else{
Frame.origin.y = 340;
}
image.frame = Frame;
[UIView commitAnimations];
Your example code doesn't show what you are asking for. It's also really hard to guess what you want.
Here's my literal interpretation of what you have asked for
for (int i = 0; i < 100; i++) {
CGRect startFrame = CGRectMake(arc4random_uniform(320), -50, 50, 50);
CGRect endFrame = CGRectMake(arc4random_uniform(320),
CGRectGetHeight(self.view.bounds) + 50,
50,
50);
UIView *animatedView = [[UIView alloc] initWithFrame:startFrame];
animatedView.backgroundColor = [UIColor redColor];
[self.view addSubview:animatedView];
[UIView animateWithDuration:2.f
delay:i * 0.5f
options:UIViewAnimationCurveLinear
animations:^{
animatedView.frame = endFrame;
} completion:^(BOOL finished) {
[animatedView removeFromSuperview];
}];
}
If you stick this in viewDidAppear: then you'll see 100 objects animate in the way you want. Obviously this is extremely inefficient and you may want to look at recycling the views etc but this shows how to animate views with UIView animation with some random points
Related
I want to animate a view inside ViewController, somewhat like the notification center as seen on the iPhone.
How does one extend the subview using the x,y and/or the height values to do this? Because I would like it to be compatible with both the 3.5 inch screens and the 4 inch screens, so it would be better not to use specific values.
I just tested this out in my own project and confirmed that it works on varying screen sizes.
UIView *slidingview = [[UIView alloc] initWithFrame:CGRectOffset(self.view.frame, 0, -self.view.frame.size.height)];
slidingview.backgroundColor = [UIColor whiteColor];
[self.view addSubview:slidingview];
[UIView animateWithDuration:1 animations:^{
slidingview.center = CGPointMake(self.view.frame.size.width/2, self.view.frame.size.height/2);
}];
To implement this, simply replace slidingview with the view you want to slide down. You would, however, have to declare your own view using the frame I provided.
How about something like this?
CGRect currentFrame = self.view.bounds;
UIView * slidingView = [UIView alloc] initWithFrame:(CGRect){currentFrame.origin, currentFrame.size.width, 0};
[self.view addSubview:slidingView];
[UIView animateWithDuration:0.5f animations:^{
slidingView.frame = currentFrame;
}];
You may need to use delay version of animateWithDuration... to make animation in effect.
I am working on a game project, and what i want to do is moving a group of labels in a window, from top of the screen to the bottom, let user read these labels, and fade away (like labels sliding from top to bottom without any trigger).
I thought that a timer variable in a loop would help me slide and change their position according to the timer value.
I made some research but if you share an article with me, i can know what i should look up for.
Thank you.
#Chuck is right. To elaborate:
-(void)doTheLabelThing {
// assume all the labels are in a container view that is 320 wide and 100 tall
self.labelContainer.frame = CGRectMake(0, -100, 320, 100);
[UIView animateWithDuration:0.5 animations:^{
// slide down
self.labelContainer.frame = CGRectMake(0, 360, 320, 100);
} completion:^(BOOL finished) {
// give user 3 seconds to read it
[UIView animateWithDuration:0.5 delay:3.0 options:0 animations:^{
// fade out
self.labelContainer.alpha = 0.0;
} completion:^(BOOL finished) {
// restore everything to original state
self.labelContainer.alpha = 1.0;
self.labelContainer.frame = CGRectMake(0, -100, 320, 100);
}];
}];
}
Don't use a loop or a timer; use Core Animation. Just do animateWithDuration:animations: or similar and set their position to the new place you want them to be.
I have several objects of a subclass of uiview, inside the main view of a viewcontroller that I animate infinitely by calling the following method in the class:
- (void)hover:(NSNumber *)upDown {
int sense = [upDown intValue];
[UIView animateWithDuration:0.8 delay:0.1 options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionAllowUserInteraction
animations:^{
CGRect frame = self.frame;
frame.origin.y += (sense==1?1:-1) * 5;
self.frame = frame;
}
completion:^(BOOL finished){
[self hover:[NSNumber numberWithInt:(sense==1?0:1)]];
}];
}
It works great except that in the device, when the home button is pressed, the app semi-freezes (the app eventually goes to background by pressing the home button repeatedly for quite a while) and any interaction with other buttons stops working. It works fine in any other case, i.e. as long as I don't press the home button I can navigate through controllers, press buttons, etc... and on the simulator.
Any ideas?
UPDATE: The culprit seems to be the shadow I'm applying to the views I'm animating
self.layer.shadowColor = [UIColor blackColor].CGColor;
self.layer.shadowOpacity = 1.0;
self.layer.shadowRadius = 5.0;
This seems to be causing some kind of overhead that only affects the app not being able to go into background state???
Anyone encountered this?
UPDATE: In the end I decided to get rid of that code and draw the shadow with Quartz in the drawRect: method. I suspect the problem might have to do with the snapshot that the iPhone takes before going into background mode and the shadow applied to the layer outside the bounds, but it's just a guess.
Basically the problem has to do with this way of obtaining a rounded shape and shadow:
[self.layer setCornerRadius:radius];
self.layer.shadowColor = [UIColor blackColor].CGColor;
self.layer.shadowOpacity = 0.2;
self.layer.shadowRadius = 5;
self.layer.shadowOffset = CGSizeMake(0, 10);
The shadow draws outside the frame of the view and the iPhone's process of going into background state doesn't seem to like that when animating.
As I mention in the update, I got rid of this and used Quartz to draw both shape an shadow inside the frame. There are many posts on how to do this but here it goes anyway:
-(void)drawRect:(CGRect)rect
{
const CGFloat *cComps = CGColorGetComponents([UIColor blackColor]).CGColor;
CGContextRef context = UIGraphicsGetCurrentContext();
CGFloat center = rect.size.width / 2.0;
CGFloat radius = center;
CGContextBeginPath(context);
CGContextSetShadowWithColor(context, CGSizeMake(0, 10), 4, [UIColor colorWithWhite:0 alpha:0.1].CGColor);
CGContextAddArc(context, center, center, radius, 0, 2*M_PI, 1);
CGContextSetRGBFillColor(context, cComps[0], cComps[1], cComps[2], 1.0);
CGContextFillPath(context);
}
NOTE: I set the height of the view to +15px to accommodate the shadow at the bottom.
Hope it helps somebody. It certainly drove me mad for a couple of days...
I recently ran into this problem and this post was incredibly helpful in identifying the culprit. Turns out though, that simply setting shouldRasterize on the shadowed layers is sufficient to prevent the freeze. (You should also set rasterizationScale to be the same as the device's main screen's scale.)
All of my shadowed layers were relatively static and weren't being constantly animated, so YMMV.
Your standard shadow adding code:
layer.shadowColor = [UIColor blackColor].CGColor;
layer.shadowOffset = CGSizeMake(0, 1);
layer.shadowOpacity = 0.5;
layer.shadowRadius = 1.0;
This is what you need to add:
layer.rasterizationScale = [[UIScreen mainScreen] scale];
layer.shouldRasterize = YES;
My first thought is that you should implement a BOOL in your .h file (let's call it stopGoing). Then do the following:
- (void)hover:(NSNumber *)upDown {
if(!stopGoing){
int sense = [upDown intValue];
[UIView animateWithDuration:0.8 delay:0.1 options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionAllowUserInteraction
animations:^{
CGRect frame = self.frame;
frame.origin.y += (sense==1?1:-1) * 5;
self.frame = frame;
}
completion:^(BOOL finished){
[self hover:[NSNumber numberWithInt:(sense==1?0:1)]];
}];
} else {
// do something else
}
}
Then, in your IBAction that you have linked to the button, just do this:
-(IBAction)myButton:(id)sender{
stopGoing = YES;
}
That should effectively stop the loop, without being too invasive.
I am trying to create an animation effect where an image who's alpha value is 0.5 (approximately) at start changes to 1 gradually, but not like the conventional effect. Here is what I am looking for.
original Image.
after some time
after some more time
and at the end
So basically if the alpha value of part of the image can be reduced than I can show the animation of filling up a glass or something close to it.
I don't know if this can be done at all or if it's possible with core graphics or core animation.
P.S. They are made in photoshop.
Does anyone have any thoughts about what should be done to achieve this kind of animation?
I'd suggest the following:
Create the UIImageView that shows the image in the view.
Create a new UIView with a background color and transparency:
UIView *transpView = [UIView new];
tranpsView.alpha = 0.4;
transpView.frame = self.view.frame;
[self.view addSubview:transpView];
Animate the transparent view to slide upwards:
[UIView animateWithDuration:1.0 animations:^{
transpView.frame = CGRectOffset(transpView.frame, 0, -tranpsView.frame.size.height);
}];
Don't forget to release the tranpsView after you are done. Possibly with the completed block.
To get the "glass filling up" type of animation, just change the frame of of the tranpsView accordingly. The tranpsView can be any UIView subclass (like a texture of liquid or something).
Hope that helps.!
You can add view above and change it's frame. The best way.
If you're using images, then sunclass UIView and implement
-(void) drawRect:(CGRect) rect {
//if you want to clip the image, the frame for the view must be smaller then rect
[image drawInRect: rect];
}
Here's yet another idea.
Set the background of your UIView *view to the image.png you want with alpha = 0.5. Let
w = view.bounds.size.width;
h = view.bounds.size.height;
Create another UIView *glassView also with alpha = 0.5, and add it as a subview:
[view addSubview:glassView];
glassView.frame = CGRectMake(0.0, h, w, 0.0);
Create a UIImageView *glassImageView and set its image to image.png as well, and add it as a subview of glassView:
[glassView addSubview:glassImageView];
glassImageView.frame = CGRectMake(0.0, -h, w, h);
Now set up the animation to increase the height and alpha of glassView while maintaining the size of imageGlassView, something like this:
[UIView beginAnimations:nil context:NULL]; {
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:1.0];
[UIView setAnimationDelegate:self];
glassView.alpha = 1.0;
glassView.frame = CGRectMake(0.0, 0.0, w, h);
glassImageView.frame = CGRectMake(0.0, 0.0, w, h);
} [UIView commitAnimations];
To be fair, I haven't tested this out, but something along these lines seems like it may work. Then again, maybe not. If you found a perfect solution, please post it back. I'd love to know how to do this!
See if this helps
http://www.iphonedevsdk.com/forum/iphone-sdk-development-advanced-discussion/32481-animating-uiimage-mask-fill.html
Well I know this question is quite old and I am the one who asked it, but today I was experimenting with something similar and found this simple solution to my own question which was asked 10 months ago.
I was working on a project which requires a image to look like its loading from completely white which is 0% progress to completely red image which is 100% progress.
I thought of adding 2 imageViews containing the images on top of each other and set the content mode of the top imageview containing image with red color to bottom so that when you reduce the size of imageview the image appears to be loading and it worked. With some animation blocks the image appears to be loading. Then I thought of this question that I had asked so long and then came up with the solution to my own problem.
So the solution to this question will be that if you add 2 imageViews on top of each other and then reduce the alpha value one that is behind and reduce the height to zero and then gradually increase the height and change the y coordinate of the image view that has alpha value 1 then It will appear to be loading as asked in this question.
I have used these two functions to get the illusion of loading image.
- (void)startAnimation
{
CGRect rect = loadedImageView.frame;
rect.origin.y = unloadedImageView.frame.origin.y;
rect.size.height = unloadedImageView.frame.size.height;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:2.0f];
[UIView setAnimationDidStopSelector:#selector(stopAnimation)];
loadedImageView.frame = rect;
[UIView commitAnimations];
}
- (void)stopAnimation
{
CGRect rect = loadedImageView.frame;
rect.origin.y = unloadedImageView.frame.size.height + unloadedImageView.frame.origin.y;
rect.size.height = 0;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:2.0f];
[UIView setAnimationDidStopSelector:#selector(startAnimation)];
loadedImageView.frame = rect;
[UIView commitAnimations];
}
I want to add some text which is a long text lets say a story and I want it to be presented in a moving up fashion. That is it will be displayed in a box and the text will be moved line by line to show the whole story. So one line gets out of the box from top and other comes from the bottom. Like a HTML marquee behavior.
You should look into whether or not UIScrollView's contentOffset property is animatable using UIView animation blocks.
If it's not, then you could try using an NSTimer and in its function, either set the contentOffset or call [scrollView scrollRectToVisible:desiredContentFrame animated:YES]; where desiredContentFrame.origin.y is just a little bit lower than what you previously had it at (depending on the scroll speed you want). Then play around with the firing frequency of your timer and the desiredContentFrame.origin.y's delta to see what looks best and has the best performance.
Here's a quick hack showing both ways:
- (void)startAnimTimer
{
currentRect = CGRectMake(0, 0, 1, 1);
[NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:#selector(doScroll) userInfo:nil repeats:YES];
}
- (void)startAnimUIView
{
[UIView beginAnimations:#"scrollUIViewAnim" context:nil];
[UIView setAnimationDuration:20.0];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
CGPoint newContentOffset = CGPointMake(0, scrollView.contentSize.height);
scrollView.contentOffset = newContentOffset;
[UIView commitAnimations];
}
- (void)loadView {
[super loadView];
self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(5, 5, 200, 200)];
scrollView.contentSize = CGSizeMake(200, 1000);
scrollView.backgroundColor = [UIColor magentaColor];
CGFloat y = 10;
CGFloat yDelta = 21;
for(int i = 0; i < 47; i++)
{
// Add some UILabels to the scrollview just so we can see it animating
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, y, 180, 20)];
label.text = [NSString stringWithFormat:#"Cheezburger %d", i];
[scrollView addSubview:label];
[label release];
y += yDelta;
}
[self.view addSubview:scrollView];
// Comment out one of these
//[self startAnimTimer];
[self startAnimUIView];
}
- (void)doScroll
{
CGFloat scrollDelta = 1.0f;
CGRect newRect = CGRectMake(0, currentRect.origin.y + scrollDelta, currentRect.size.width, currentRect.size.height);
// Scroll the scrollview to the next position
[scrollView scrollRectToVisible:newRect animated:YES];
currentRect = newRect;
}
This method may help (or not):
- (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated
If not, just make a big UILabel and animate its frame using a CABasicAnimation.
I think you want to look at the Scroll View (UIScrollView) in the iPhone SDK.
http://developer.apple.com/IPhone/library/documentation/UIKit/Reference/UIScrollView_Class/Reference/UIScrollView.html
Depending on your implementation, you may not be able to use it "out of the box" but it should provide the functionality you seem to be describing. I'm not sure it will do the auto-scroll thing but that should be pretty easy to implement... maybe.... But, I'm still confident it could be done.