I know there is most probably something seriously wrong here because I only started on iOS yesterday but I can't seem to get this to update the screen properly, the count works fine and it's incrementing and checking the conditions correctly just that the screen doesn't get displayed, can anybody point me in the right direction please?
#implementation draw2D
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
// Initialization code
[self myTimer];
}
return self;
}
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// Drawing code
[self updateBackground];
}
NSTimer *timer = nil;
int count = 0;
- (void)myTimer
{
timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:#selector(updateBackground) userInfo:nil repeats:NO];
if (count < 1) {
count++;
} else {
count = 0;
}
}
- (void)updateBackground:
{
if(count == 1)
{
UIImage *myImage = [UIImage imageNamed:#"bg.png"];
CGRect imageRect = CGRectMake(0, 0, 320, 480);
[myImage drawInRect:imageRect];
[myImage release];
// count++;
}
else
if (count == 0)
{
UIImage *myImage = [UIImage imageNamed:#"SCENE_002.png"];
CGRect imageRect = CGRectMake(0, 0, 320, 480);
[myImage drawInRect:imageRect];
[myImage release];
// count = 0;
}
[self myTimer];
}
#end
EDIT: It displays the first image, but never swaps to the second.
On second look, you have two things methods calling updateBackground, one is drawRect, which can be called any time you're updating the display, and on the timer fire. In the myTimer method, you're changing the count value, with the expectation the screen will refresh 0.5 seconds later.
I'm suspicious that the reason one image is never displayed is that it may be being drawn, but the call to drawInRect might fire drawRect, which could then blit the other image on top of the recently drawn image.
So, basically I'd remove the call to updateBackground from drawRect:
** ORIGINAL ANSWER:
[UIView drawRect] is only called when necessary. After the initial call, UIKit just caches the result internally and continues to redraw the cached copy to the display.
What you need to do is send a signal to the view that it needs to be refresh. You can do that by adding the line:
[self setNeedsDisplay];
In your updateBackground selector.
Also, why are you re-creating the timer after each time it fires, instead of changing the repeats parameter to YES?
Related
I want make something like animation.
I have four UIImageView (names: IW1, IW2, IW3, IW4)
I want change image in IW1 on image1 and next on image2, after that change image in IW2 on image1 and next on image2, after that change image in IW3 on image1 and next image2, after that change image in IW4 on image1 and next on image2.
Unfortunately when I tried to do this, the only thing I could do is change the images in all UIImageViews at the same time, but I want to do it sequentially.
Someone will help?
I would do it this way
Header interface
int j;
int i;
UIImageView *imgV1;
UIImageView *imgV2;
UIImageView *imgV3;
UIImageView *imgV4;
UIImage *img1;
UIImage *img2;
NSArray *views;
NSArray *imgs;
Implementation
- (void)viewDidLoad{
i=0;
j=0;
views = [[NSArray alloc] initWithObjects:imgV1, imgV2, imgV3, imgV4, nil];
imgs = [[NSArray alloc] initWithObjects:img1, img2, nil];
[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:#selector(changeImage) userInfo:nil repeats:YES];
}
-(void)changeImage{
UIImageView *imageView = [views objectAtIndex:j];
UIImage *image = [imgs objectAtIndex:i];
imageView.image = image;
i++;
if(i==2){
i=0;
j++;
if(j==4)
j=0;
}
}
Hope this helps (I didnt try it)
- (void)runSwitchImages
{
[UIView animateWithDuration:2 delay:2 options:UIViewAnimationCurveEaseInOut animations:^{
//Animate Image Change Here
} completion:^(BOOL finished) {
//When The Image is done animating it will go here
}];
}
You can use something like this to do the changes in series. You can create another one these functions for each images and have them call in series. Or Change the function to be recursive .
If you want it to continue to change us a NSTimer to call the function.
call this somewhere
[self performSelector:#selector(changeImage:) withObject:yourImageView afterDelay:1]
which will call this after a 1 second delay
-(void)changeImage:(UIImageView *)yourImageView
{
yourImageView.image = yourImage;
}
I want to smothly animate an image in an UIImageView to turn into the next one within one second like UIModalTransitionStyleCrossDissolve does.
Currently, I've got an UIImageView * called "imageView" and a function which is called "imageForState" which returns me a UIImage * for the correct image.
So what I want to do is to animate the image A smoothly into image B if there is one.
Currently, my function is like that:
- (UIImage *) imageForState{
NSLog(#"state: %d", [save state]);
switch ([save state]) {
case 0:
case 1:
return [UIImage imageNamed:#"Sakuya_Debug.PNG"];
case 2:
return [UIImage imageNamed:#"Sakuya_2_Debug.PNG"];
default:
return NULL;
//Never called
}
}
-(void) tap{
[imageView setAnimationImages:[NSArray arrayWithObjects:[imageView image], [self imageForState], nil]];
imageView.animationDuration = 2.0;
[imageView startAnimating];
save.state++;
}
My problem is, that 1.) the animation goes on forever (when I set imageView.animationRepeatCount to 1, I end up at the first image again) and b.) the animation is not smooth; just like I would have used "setImage";
What am I doing wrong?
I suggest doing it with two imageViews and an animation block. In the following example I assume two square images with a siza of 100px. If you add the two imageViews as subviews make sure that imageB is added after imageA so it covers it.
Init the imageViews:
UIImageView *imageA = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Sakuya_Debug.PNG"]];
UIImageView *imageB = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Sakuya_2_Debug.PNG"]];
// hide the second image
imageB.alpha = 0.0;
// put the image with the same size at same position
imageA.frame = CGRectMake(0.0, 0.0, 100.0, 100.0);
imageB.frame = imageA.frame;
Blend method:
- (void)crossDissolveImageAtoB
{
[UIView animateWithDuration:1.0
animations:^{
imageB.alpha = 1.0;
}
completion:^(BOOL finished){
// do something after the animation finished,
// maybe releasing imageA if it's not used anymore...
}];
}
In my application after the view load, an image should appear from left to right.
I am writing this code in in viewdidload or viewwillappear:
UIImage *image = [UIImage imageNamed:#"PG05(REV).jpg"];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
for (int i=-1024; i<=0; i++) {
NSLog(#"i: %d",i);
sleep(5);
imageView.frame = CGRectMake(i,0, 1024, 768);
NSLog(#"done");
[self.view addSubview:imageView];
}
[imageView release];
But problem is that, before loading view it executes the above code than loads the view, so that it seems that view loaded and a static image is there.
But my requirement is that first view load completely then image should display from left to right.
Please help me out.
First of all, you should not call the -(void)addSubview: inside your for loop. You just need to call it once.
Secondly, if you want to animate your imageView from left to right, UIView class provides great functionalities for this using blocks.
Your code should look like this :
UIImage *image = [UIImage imageNamed:#"PG05(REV).jpg"];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
imageView.frame = CGRectMake(-1024, 0, 1024, 768);
[self.view addSubview:imageView];
[imageView release]; //Your imageView is now retained by self.view
//Animation
[UIView animateWithDuration:2.0
animations:^(void) {
imageView.frame = CGRectMake(0, 0, 1024, 768);
}];
The animateWithDuration: method will handle the animation timer for you, just set the duration argument according to your needs.
You can use a function and call it using timer method.
timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:#selector(moveImage) userInfo:nil repeats:NO];
-(void)moveImage
{
//Your condition
}
This is a job for UIView animations.
Put your imageView down at -1024 left, then go:
[imageView animateWithDuration:5 animations:^{
[imageView.frame = CGRectMake(0,0, 1024, 768)];
}];
Ta-da! A five second animation of your image sliding to the right.
Check out the animation methods of UIView (of which UIImageView is a subclass):
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIView_Class/UIView/UIView.html
Is it possible to have a UIIView with a textured background image and an opacity gradient? i.e., the bg image should fade in from left to right against the background container view.
thanks
Save your background image with an alpha channel (i.e. PNG) and do the fade in whatever graphics app you use.
Then, put it as the first child of your UIView as a UIImageView
- (void)viewDidLoad {
[super viewDidLoad];
image1=[[UIImageView alloc]initWithImage:[UIImage imageNamed:#"Default.png"]];
image1.frame=CGRectMake(0, 0, 320, 460);
image2=[[UIImageView alloc]initWithImage:[UIImage imageNamed:#"directoryPage.png"]];
image2.frame=CGRectMake(0, 0, 320, 480);
[self.navigationController setNavigationBarHidden:YES];
}
- (void)fade
{
image2.alpha = 0;
[self.view addSubview:image2];
// The upper layer will transition from alpha 1 to 0s
[self.view addSubview:image1];
BSheepAppDelegate *appD=(BSheepAppDelegate *)[[UIApplication sharedApplication]delegate];
if(appD.flag==0){
timer = [NSTimer scheduledTimerWithTimeInterval:.01 target:self selector:#selector(fadeTimerEvent) userInfo:nil repeats:YES];
appD.flag=1;
}
else if (appD.flag==1) {
[self.view addSubview:image2];
image2.alpha=1;
}
}
// Rate of transition for alpha values
#define FADE_IN_RATE 1.0/100.0
#define FADE_OUT_RATE 2.0/200.0
- (void)fadeTimerEvent
{
if (image2.alpha >= 1)
{
// At this point, image2 is now visible
[timer invalidate];
timer = nil;
}
else
{
// Fade lower layer in (increase alpha)
image2.alpha += FADE_IN_RATE;
// Fade upper layer out (decrease alpha)
image1.alpha -= FADE_OUT_RATE;
}
}
use this code to set
1.My mainView is a UIScrollView. I have to load 9 images as tiles onto it.
2.I am calling the function as a different thread to get the 9images and to load it into the interface(mainthread). By doing so, the interface remains responsive.
3.But the problem even when the images are being loaded they doesnt get displayed in the UIScrollView until the whole thread is completed. But if I am doing some action on the interface, I am able to see each of them being loaded and displayed.
Means I have to update the interface(mainthread) from the background thread after each image is being loaded into it.
How can i do it? I have given the code which I use to load the images to the UIScrollView which i call using a different thread.
- (void)setUpDisplay:(NSArray *)array
{
NSAutoreleasePool *pool=[[NSAutoreleasePool alloc] init];
myScrollView.userInteractionEnabled = YES;
myScrollView.multipleTouchEnabled = YES;
int x=0,y=0;
CGRect frame;
for (i = 0; i < 3; i++)
{
if(j == 3)
{
x=x+256;
y = y-768;
}
for (j = 0; j < 3; j++) {
imageView = [[UIImageView alloc] initWithImage:[self getCachedImage:[NSString stringWithFormat:#"url to fetch images"]]];
frame = [imageView frame];
frame.origin.x = x;
frame.origin.y = y;
[imageView setFrame:frame];
imageView.userInteractionEnabled = YES;
imageView.multipleTouchEnabled = YES;
[myScrollView addSubview:imageView];
y = y+256;
[imageView release];
imageView=nil;
}
}
[pool release];
}
This method of NSObject is often helpful:
[someObject performSelectorOnMainThread:#selector(updateUI:) withObject:anotherObject waitUntilDone:YES /* or NO */];
You may want to try calling [myScrollView setNeedsDisplay] on the main thread after each image load is finished.