I want to add a photo captured from my app and display on the iPad for 2 seconds. I have a self timing photo app that counts down from 4 to 1 then takes the photo. I have it set to display a PNG image when it reaches zero. But I want to display the photo that was taken immediately after the PNG image. I am stumped.
This is part of the code that saves the image.
- (void)captureEnded:(CameraView *)camView {
NSLog(#"%f, %f", [camView capturedImage].size.width, [camView capturedImage].size.height);
UIImage *img = [camView capturedImage];
This is part of the code that displays the countdown. When the timer reaches zero "smile3" displays on screen for .2 seconds. I want the UI Image above to display following that smile3 for 2 seconds. Any thoughts?
if (mTimer-counter+1 == 0) {
[[AppDelegate sharedAppDelegate] playShutterSound];
lblRemainPhoto.hidden = YES;
[btnTimeCounter setBackgroundImage:[UIImage imageNamed:#"smile3"] forState:UIControlStateNormal];
[NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:#selector(anim1) userInfo:nil repeats:NO];
}
Related
I'm developing an app for Apple Watch using WatchKit and I need to implement a circular progress while recording audio, similar to Apple demos.
I don't know if WatchKit includes something to do it by default so I have created my own images (13 for 12 seconds [209 KB in total]) that I change with a timer.
This is my source code:
Button action to start/stop recording
- (IBAction)recordAction {
NSLogPageSize();
NSLog(#"Recording...");
if (!isRecording) {
NSLog(#"Start!");
isRecording = YES;
_timerStop = [NSTimer scheduledTimerWithTimeInterval:12.0
target:self
selector:#selector(timerDone)
userInfo:nil
repeats:NO];
_timerProgress = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(progressChange)
userInfo:nil
repeats:YES];
} else {
NSLog(#"Stop :(");
[self timerDone];
}
}
Action when timer is finished or if tap again on the button
-(void) timerDone{
NSLog(#"timerDone");
[_timerProgress invalidate];
_timerProgress = nil;
[recordButtonBackground setBackgroundImageNamed:[NSString stringWithFormat:#"ic_playing_elipse_12_%d", 12]];
counter = 0;
isRecording = NO;
}
Method to change progress
- (void)progressChange
{
counter++;
NSLog(#"%d", counter);
NSString *image = [NSString stringWithFormat:#"ic_playing_elipse_12_%d", counter];
[recordButtonBackground setBackgroundImageNamed:image];
NSLog(image);
}
This is a gif showing the bug. It starts to show but change the image randomly until it gets a pair of seconds. (Note: I have already checked that the first images have the right progress)
Update (other solution): using startAnimating
There is a new way to show a circle progress using startAnimatingWithImagesInRange:duration:repeatCount
You need to specify the images range and the duration for your animation. See an example below:
[self.myElement startAnimatingWithImagesInRange:NSMakeRange(0, 360) duration:myDuration repeatCount:1];
I believe this is a side-effect of the way WatchKit interprets image names.
Image names ending in numbers are used to represent frames in an animated image, so "ic_playing_elipse_12_10" is being interpreted as the first frame of the image named "ic_playing_eclipse_12_1" and your 10th image gets displayed when you want it to display your first one.
You should be able to just change your image names so the number isn't the last part of the image name and it will fix it.
I know that this question is answered but I would like to explain better the solution of startAnimating.
[myElement startAnimatingWithImagesInRange:NSMakeRange(imageIdBegin, imageIdEnd) duration:duration repeatCount:repetitions];
In order to use this, you need a suite of images named like you want but with sequential ids. For example: progress_0.png, progress_1.png, progress_2.png, .., progress_n.png
You can decide the begin index and the end index using that values in NSMakeRange(imageIdBegin, imageIdEnd) just indicating the number id (not the full image name)
Of course, you will need to indicate the duration of the animation in seconds, WatchKit will interpolate for you to animate your images between init index and end index.
And finally, you can indicate if you want to repeat this animation (for example for a loading action) or not. If you don't want to repeat, you have to indicate 1.
I hope this can help more people to perform circle progress or another animations inside their AppleWatch applications :)
I'm making a game that involves falling images. I have 6 images and I want each one to fall randomly (ex. The $1 bill will be falling and then a $5 bill (or whatever randomly generated image) falling either beside it or right behind it (The iOS game Sky Burger by: NimbleBit LLC or Crazy Goats by: Barry Calvagna are a couple of examples)). Can anybody help me? This is all the code I have so far
-(void)moneyDrop {
money.animationImages = [NSArray arrayWithObjects:
[UIImage imageNamed:#"$1 (bill).png"],
[UIImage imageNamed:#"$5 (bill).png"],
[UIImage imageNamed:#"$20 (bill).png"],
[UIImage imageNamed:#"$50 (bill).png"],
[UIImage imageNamed:#"$100 (bill).png"],nil]; }
I have not necessarily worked with falling image, unless you count a Flappy Bird remake or a Ball Pong game, so please excuse the lack of code. If my question doesn't make any since, I will re-word it.
First off, it sounds to me like you want multiple UIImageViews each with a different image, not a single UIImageView with an array of animationImages.
For making things move, you can use NSTimer.
- (void)start {
mainTimer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:#selector(mainTimerLoop) userInfo:nil repeats:YES];
}
- (void)mainTimerLoop {
NSLog(#"Loop");
//In here, you can assign random images to and adjust the centers of money image views.
}
You could make a function like this to return an image.
- (UIImage *)moneyImageForRandomInt:(int)random {
if (random == 0) return [UIImage imageNamed:#"$1 (bill).png"];
if (random == 1) return [UIImage imageNamed:#"$5 (bill).png"];
if (random == 2) return [UIImage imageNamed:#"$20 (bill).png"];
if (random == 3) return [UIImage imageNamed:#"$50 (bill).png"];
return [UIImage imageNamed:#"$100 (bill).png"];
}
And use a function like this to assign a random image to a UIImageView.
- (void)assignRandomImageToMoneyImageView:(UIImageView *)moneyImageView {
moneyImageView.image = [self moneyImageForRandomInt:arc4random() % 5];
}
This is how I would go about it, anyway.
I have an iOS App that loads a set of images and a duration into an array then I have a timer that displays the images like so:
- (void)fireTimer:(NSTimer *)theTimer
{
self.image = [frames objectAtIndex:currentFrame];
NSTimeInterval time = [[durations objectAtIndex:currentFrame] floatValue];
self.timer = [NSTimer scheduledTimerWithTimeInterval:time target:self selector:#selector(fireTimer:) userInfo:nil repeats:NO];
currentFrame++;
if (currentFrame >= [frames count])
{
currentFrame = 0;
[timer invalidate];
}
}
To start the animation I call fireTimer and cycle through the images then when all the images are processed I call [timer invalidate] to stop the animation. I cannot use startAnimation because I need different durations for each image.
Right know I am NOT doing this on a background thread so the animation is choppy because other processing is happening whilst the image animates.
What is the best way to animate this in the background? Can I simply put this call to fireTimer in a block?
I know this may not be the best way to animate an image on iOS, but I do not want to do a lot of refactoring on the code right now.
Thanks for any suggestions or examples for a better solution!!!
I would suggest you use UIImageView to animate your images : it is made to do this task. If, like you say, some images needs to remains longer then others, then you can just display them many times. Let's say that image2 needs to be displayed twice longer than image1 and image3, just initialize the array animationImages on your UIImageView like : #[image1, image2, image2, image3].
Instead of using a timer, you could use performSelector: withObject: afterDelay:
-(void)loopBackground:(int)index
{
if(index < [self.durations count]{
self.image = [self.frames objectAtIndex:index];
[self performSelector:#selector(loopBackground:) withObject:index++ afterDelay:[[self.durations objectAtIndex:index] floatValue]];
}
}
i have multiple images in array and a scrollView all the images should scroll automatically and when i clicked the image it should navigate to other view and display its details. after completing images scrolling from 0 to end of the array it should Again load 1st image i.e 0. in Animating i have lot of problem please help me....
iam using this code
[NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:#selector(onTimer) userInfo:nil repeats:YES];
- (void) onTimer {
// Updates the variable h, adding 100 (put your own value here!)
h += 100;
//This makes the scrollView scroll to the desired position
yourScrollView.contentOffset = CGPointMake(0, h);
}
try iCarousel library for scrolling the images, use autoscrolling example for the reference, set wrap property to yes if you want to repeat the content in the loop. add image array to carousel and implement carousel datasource and delegate methods to scroll the images. you can change different types like linear, rotary or overflow etc.
you can create image outlet after that
NSMutableArray *imgArray = [[NSMutableArray alloc]init];
for (int i =0; i<imgUrlArray.count; i++) {
NSString *imgStr = [serviceImgArray objectAtIndex:i];
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:imgStr]];
[imgArray addObject:[UIImage imageWithData:imageData]];
}
yourimageView.animationImages = imgArray;
yourimageView.animationDuration = 10;
[yourimageView startAnimating];
that's it.
I'm trying to make a photo slider similar to iOS's photos app. I've seen PhotoScroller, and I'm using initWithContentsOfFile.
CATiledLayer seems like a good idea, except I have no way of pre-generating tiles. The tiles also take up a lot of space. Images are part of a document bundle synced up with iCloud. Photos are typically JPEG. From hours of reading it seems like generating the tiles on the fly is slower than just loading the whole image.
It seems like a majority of the time is spent in decompressing the image anyway. And moving it to a background queue and displaying a smaller image should work well. So that's what I'm trying to do. And it works to a point, but if I slide without waiting for the image to load there's still somewhat of a stutter, which sometimes causes the scroll view to hang momentarily (when paging).
This is the function that sets the image:
- (void)setImage:(UIImage *)image placeholder:(UIImage *)placeholder
{
_image = image;
self.zoomScale = 1.0;
imageView.image = nil;
imageSize = image.size;
imageView.frame = CGRectMake(0, 0, image.size.width, image.size.height);
MachTimer *timer = [MachTimer new];
[timer start];
imageView.image = placeholder;
NSLog(#"placeholder: %f", [timer elapsedSeconds]);
//imageView.layer.contents = (id)placeholder.CGImage;
self.contentSize = image.size;
[self setMaxMinZoomScalesForCurrentBounds];
self.zoomScale = self.minimumZoomScale;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
MachTimer *timer = [MachTimer new];
[timer start];
UIGraphicsBeginImageContext(CGSizeMake(1, 1));
[image drawAtPoint:CGPointZero];
UIGraphicsEndImageContext();
NSLog(#"decode: %f", [timer elapsedSeconds]);
dispatch_sync(dispatch_get_main_queue(), ^{
if(_image == image) {
MachTimer *timer = [MachTimer new];
[timer start];
imageView.image = image;
NSLog(#"display: %f", [timer elapsedSeconds]);
//imageView.layer.contents = (id)image.CGImage;
}
});
});
}
My "placeholder" times are about 0.00005 - 0.00006 seconds (decompress and display), and they're 480px tall. My "decode" times (for full image) are about 0.8 to 1.2 seconds. "display" is about 0.0001 seconds (which is about 0.1 milliseconds).
So with those times the UI should be smooth as butter, but it isn't.
I've even tried to go as far as setting contents of a regular UIView to the CGImage. I've tried iOS 6.0's drawsAsynchronously, and that seems to make it a little worse.
What am I doing wrong?
EDIT:
I've pushed my sample project to GitHub:
https://github.com/lukescott/PhotoScroller
I would create a background thread for hard work (photo load or decode) and when its done then delegate UI work (draw or whatever) to main thread using one of tools (queues, msgs, etc).