I am new to IOS development. I am using custom GridView to load the content in my project, and it is working fine for Simulator when the content reloads. But in iPad the content gets shuffles when reloads.
- (void)reloadData {
if (_gridViewDelegate && self.superview != nil) {
CGFloat maxX = 0.f;
CGFloat maxY = 0.f;
_scrollView.pagingEnabled = YES;
self.gridRects = [self.gridViewDelegate rectsForCellsInGridView:self];
[self.gridCells.allValues makeObjectsPerformSelector:#selector(removeFromSuperview)];
[self.reuseableCells addObjectsFromArray:self.gridCells.allValues];
[self.gridCells removeAllObjects];
for (NSValue *rectValue in self.gridRects) {
CGRect rect = [rectValue CGRectValue];
maxX = MAX(maxX, rect.origin.x + rect.size.width);
maxY = MAX(maxY, rect.origin.y + rect.size.height);
}
CGFloat pageWidth = self.scrollView.frame.size.width;
self.maximumContentWidth=maxX;
maxX = MAX(MIN(maxX, self.maximumContentWidth), self.contentSize.width);
maxY = MAX(MIN(maxX, self.maximumContentHeight), self.contentSize.height);
maxX=pageCount*pageWidth;
self.scrollView.contentSize = CGSizeMake(maxX, maxY);
[self loadCellsInRect:self.visibleRect];
[self updateStickyViewsPosition];
[pageNumberLable removeFromSuperview];
currentPage = floor((self.scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
if(pageWidth == 1024)
{
pageNumberLable=[[UILabel alloc]initWithFrame:CGRectMake(self.scrollView.contentOffset.x+990, 690, 20, 20)];
pageNumberLable.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
}
else
{
pageNumberLable=[[UILabel alloc]initWithFrame:CGRectMake(self.scrollView.contentOffset.x+740, 943, 20, 20)];
pageNumberLable.backgroundColor=[UIColor redColor];
pageNumberLable.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
}
pageNumberLable.text=[NSString stringWithFormat:#"%d",currentPage+1];
pageNumberLable.textColor=[UIColor blackColor];
pageNumberLable.font = [UIFont boldSystemFontOfSize:16];
pageNumberLable.backgroundColor=[UIColor clearColor];
[self.scrollView addSubview:pageNumberLable];
pageIndex = [NSUserDefaults standardUserDefaults];
[pageIndex setInteger:currentPage+1 forKey:#"integerKey"];
}
}
-(void)reloadGrid
{
if(rotate == newIntValue)
{
[spinningLibrary stopAnimating];
[update removeFromSuperview];
settingLabel.hidden=YES;
spinningLibrary.hidden=YES;
}
if(rotate<newIntValue)
{
rotate++;
[self.gridView scrollRectToVisible:CGRectMake(768*rotate, 0, self.gridView.frame.size.width, self.gridView.frame.size.height) animated:YES];
[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(reloadGrid123) userInfo:nil repeats:NO];
}
[NSThread sleepForTimeInterval:0.2];
self.gridView.scrollView.hidden=NO;
[settingsPopoverController dismissPopoverAnimated:YES];
}
You're comparing iPad's RAM and your machine's RAM.It's not fair though.
[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(reloadGrid123) userInfo:nil repeats:NO];
Try to adjust the interval(> 0.1) by setting, scheduledTimerWithTimeInterval.
And it's a bad way of blocking the main thread.
Use below blocks approach to "do something after sometime".
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Do something taking a long time in background.
[NSThread sleepForTimeInterval:0.2];
// Background thread has finished it's work.
// Call another block on main thread to do UI stuff like updating etc..
dispatch_async(dispatch_get_main_queue(), ^{
// Here you are in the main thread again
// You can do whatever you want
});
});
Related
I've made a program that generates an image at a random x-coordinate at the top of the screen. The image then falls down to the bottom. However, I want to keep generating new images (of the same image) every few seconds so that it's as though these duplicates of the same image are continually "raining" from the top.
How can I make all of this code repeat every 0.5 seconds?
#implementation ViewController {
UIImageView *_myImage;
}
- (void)viewDidLoad
{
srand(time(NULL));e
int random_x_coordinate = rand() % 286;
CGRect myImageRect = CGRectMake(random_x_coordinate, 0.0f, 40.0f, 40.0f);
UIImageView *myImage = [[UIImageView alloc] initWithFrame:myImageRect];
[myImage setImage:[UIImage imageNamed:#"flake.png"]];
myImage.opaque = YES;
[self.view addSubview:myImage];
_myImage = myImage;
//FALLING BIRDS TIMER
moveObjectTimer = [NSTimer scheduledTimerWithTimeInterval:0.001 target:self selector:#selector(moveObject) userInfo:nil repeats:YES];
}
//FALLING BIRDS MOVER
-(void) moveObject { // + means down and the number next to it is how many pixels y moves down per each tick of the TIMER above
_myImage.center = CGPointMake(_myImage.center.x, _myImage.center.y +1);
}
Just put animation cycle inside the method you call on timer, something like
- (void)viewDidLoad
{
[super viewDidLoad];
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.5
target:self
selector:#selector(animate)
userInfo:nil repeats:YES];
[timer fire];
}
- (void)animate
{
CGFloat hue = ( arc4random() % 256 / 256.0 ); // 0.0 to 1.0
CGFloat saturation = ( arc4random() % 128 / 256.0 ) + 0.5; // 0.5 to 1.0, away from white
CGFloat brightness = ( arc4random() % 128 / 256.0 ) + 0.5; // 0.5 to 1.0, away from black
UIColor *color = [UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:1];
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
view.backgroundColor = color;
[self.view addSubview:view];
[UIView animateWithDuration:1.0 animations:^{
view.frame = CGRectMake(0, 200, 50, 50);
}];
}
Will give you squares dropping down from top, continuously. Just remember to clean up unused views regularly to avoid memory issues.
How can I implement marquee effect animation in UIImage.
I have a image of cloud (320*480). I need to animation it continuously left from right without any lagging and disappearing. Below is a sample of html.
http://www.quackit.com/html/codes/html_marquee_code.cfm
2nd from top(Continuous scrolling text:).
Please help
UIImage *clouds = [UIImage imageNamed:#"Clouds"];
UIImageView *cloudView = [[UIImageView alloc] initWithImage:clouds];
CGRect origin = CGRectMake(320, 0, clouds.size.width, clouds.size.height);
CGRect destination = CGRectMake(0, 0, clouds.size.width, clouds.size.height);
cloudView.frame = origin;
[self.view addSubview:cloudView];
[UIView animateWithDuration:5 delay:0 options:UIViewAnimationOptionRepeat | UIViewAnimationOptionCurveLinear animations:^{
cloudView.frame = destination;
} completion:nil];
Do this:
-(void)marqueeEffect
{
imgView.frame = CGRectMake(self.view.frame.origin.y,50,320,480); //right frame
//increase time duration as per requirement
[UIView animateWithDuration:3.0
delay: 0.0
options: UIViewAnimationCurveEaseOut
animations:^{
imgView.frame = CGRectMake(-imgview.frame.size.width,50,320,480); //left frame
}
completion:^(BOOL finished){
[self performSelector:#selector(marqueeEffect)];
}];
}
TRY THIS EXAMPLE , ITS FOR UILABEL:
int x;
#synthesize label;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
label=[[UILabel alloc]initWithFrame:CGRectMake(300, 400, 150, 30)];
label.text=#"WWW.SONGS.PK";
label.backgroundColor=[UIColor clearColor];
x=300;
[NSTimer scheduledTimerWithTimeInterval:.01 target:self selector:#selector(clickme) userInfo:nil repeats:YES];
}
-(void)clickme
{
x--;
label.frame=CGRectMake(x, 400, 150, 30);
if( x==-150)
{
x=300;
}
[self.view addSubview:label];
}
I am having an array of UIViews and I want to arrange them in a main view in a grid form, and I also wanted it to animate ( ie the grids should appear one by one slowly). Tried animating with in a for loop but didnt work but came up with a work around to achieve something closer to what I want, but just wanted to know if there is a better way to do this. I know there is some property with CAAnimationGroup (begintime) but sure how to connect it to addtosubview. Here is my code, let me know if there is a better way to do it.
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
CGFloat x = 0;
CGFloat delay = .3;
for(int i=0;i<30;i++)
{
UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(x, 0, 50, 50)];
myView.backgroundColor = [UIColor greenColor];
myView.alpha = 0.0;
x = x + 50+ 2;
[UIView animateWithDuration:0.25 delay:delay options:UIViewAnimationOptionCurveEaseInOut animations:^{
[self.view addSubview:myView];
myView.transform = CGAffineTransformMakeScale(0.5, 0.5);
// myView.transform = CGAffineTransformMakeRotation(90);
} completion:^(BOOL finished) {
[UIView animateWithDuration:.5 animations:^{
myView.transform = CGAffineTransformMakeScale(1.0, 1.0);
myView.alpha = 1.0;
}];
}];
delay = delay + .3;
}
// Do any additional setup after loading the view, typically from a nib.
}
-anoop
Hi,I have also used animation within for loop but it didn't work
properly then I call a method that animate the view , multiple times
and it worked properly.I think this is better way to simply apply
animation. by calling a method.I m putting some code here may it will
help u.
- (void)viewDidLoad
{
radius=82.097;
rotationMultiplier=1;
toAngle = fromAngle = 0;
toStart = NO;
center=CGPointMake(161, 233);
NSString *path = [[NSBundle mainBundle] pathForResource:#"click" ofType:#"mp3"];
self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:nil];
[self.player prepareToPlay];
SingleTouchGesture *wheelRecogniser=[[SingleTouchGesture alloc] initWithTarget:self action:#selector(rotateWheel:)];
[self.view addGestureRecognizer:wheelRecogniser];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
-(void) rotate:(int) time
{
CABasicAnimation *topAnimation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
topAnimation.duration=time;
topAnimation.fromValue= [NSNumber numberWithFloat:fromAngle];
topAnimation.toValue=[NSNumber numberWithFloat:toAngle];
topAnimation.delegate = self;
topAnimation.fillMode = kCAFillModeForwards;
topAnimation.removedOnCompletion = NO;
[wheelImage.layer addAnimation:topAnimation forKey:#"transform"];
fromAngle = toAngle;
}
-(void) rotateWheel:(SingleTouchGesture*) recogniser
{
toAngle += recogniser.rotation;
if (toStart)
{
if (recogniser.state == UIGestureRecognizerStateEnded)
{
NSLog(#"Speed === %f",recogniser.speed);
rotationMultiplier=[self getMultiplier:recogniser.speed];
NSLog(#"Rotation Multiplier..%f",rotationMultiplier);
toStart = NO;
NSLog(#"State Ended");
self.player.currentTime=0;
[self.player play];
if (recogniser.rotation>=0)
{
toAngle =fromAngle+(rotationMultiplier*3.14);
}
else
{
toAngle =fromAngle-(rotationMultiplier*3.14);
}
}
[self rotate:1];
}
else
{
if (recogniser.state==UIGestureRecognizerStateChanged) {
NSLog(#"continue...");
CGPoint pt=[recogniser locationInView:self.view];
float dis=[recogniser distanceBetweenPoints:center with:pt];
if (dis<radius)
{
if (recogniser.rotation>=0)
{
NSLog(#"Rotation value: +ve: %f",recogniser.rotation);
toStart = YES;
toAngle =fromAngle+(rotationMultiplier*3.14);
recogniser.rotation = 0;
}
else
{
NSLog(#"Rotation value: -ve: %f",recogniser.rotation);
toStart = YES;
toAngle=fromAngle-(rotationMultiplier*3.14);
recogniser.rotation = 0;
}
}
}
}
}
Here rotate method is calling multiple times.
I have some 10 images, I wanted to show 10 images continuously in two way, one by moving the image with user interaction and other way by automatically moving the images in a time interval with out any user interaction. Following code allow me to move images when user touch and moves the image.... but how can i move the images automatically?
{
scrollView.delegate = self;
[self.scrollView setBackgroundColor:[UIColor blackColor]];
[scrollView setCanCancelContentTouches:NO];
scrollView.indicatorStyle = UIScrollViewIndicatorStyleWhite;
scrollView.clipsToBounds = YES;
scrollView.scrollEnabled = YES;
scrollView.pagingEnabled = YES;
NSUInteger nimages = 0;
CGFloat cx = 0;
for (; ; nimages++) {
NSString *imageName = [NSString stringWithFormat:#"pimac%d.gif", (nimages + 1)];
UIImage *image = [UIImage imageNamed:imageName];
if (image == nil) {
break;
}
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
CGRect rect = imageView.frame;
rect.size.height = image.size.height;
rect.size.width = image.size.width;
rect.origin.x = ((scrollView.frame.size.width - image.size.width) / 2) + cx;
rect.origin.y = ((scrollView.frame.size.height - image.size.height) / 2);
imageView.frame = rect;
[scrollView addSubview:imageView];
[imageView release];
cx += scrollView.frame.size.width;
}
self.pageControl.numberOfPages = nimages;
[scrollView setContentSize:CGSizeMake(cx, [scrollView bounds].size.height)];
}
You can use NSTimmer and invoke your image move function there.
self.timer = [NSTimer scheduledTimerWithTimeInterval:5
target:self
selector:#selector(imageMove)
userInfo:nil
repeats:YES];
const CGFloat kScrollObjWidth = 320.0;
const NSUInteger kNumImages = 3;
-(void)viewdidLoad
{
// additional further step
[NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:#selector(onTimer) userInfo:nil repeats:YES];
curXLoc=0;
}
- (void) onTimer {
curXLoc += kScrollObjWidth;
//This makes the scrollView scroll to the desired position
if(curXLoc<(kNumImages * kScrollObjWidth))
ScrollView.contentOffset = CGPointMake(curXLoc,0 );
else
{
curXLoc =0;
ScrollView.contentOffset = CGPointMake(curXLoc,0 );
}
}
I have 5 pictures inside an infinite scrollView.
So in order to make that scrollView infinite/circular I positioned my images like this:
5 1 2 3 4 5 1
meaning: last picture first picture second picture.....last picture first picture
And in order for it to become infinite I have the following code:
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
if(self.scrollView.contentOffset.x == 0){
[self.scrollView scrollRectToVisible:CGRectMake(self.view.frame.size.width*pathImages.count, 0, self.view.frame.size.width, self.view.frame.size.height) animated:NO];
}
else if (self.scrollView.contentOffset.x == self.view.frame.size.width*(pathImages.count+1)) {
[self.scrollView scrollRectToVisible:CGRectMake(self.view.frame.size.width,0 ,self.view.frame.size.width, self.view.frame.size.height) animated:NO];
}
}
which means that when I'm at the last picture the contentOffset of the scrollView is set to go to the first picture-in this way I get an infinite scrollView.
What I wanted next was for my scrollView to slide automatically-for this I set a timer which calls one method-onTimer:
- (void) onTimer{
NSLog(#"flip pages");
if(h < pathImages.count*self.view.frame.size.width)
{
h+= self.view.frame.size.width;
}
else
{
h=self.view.frame.size.width;
}
if(self.scrollView.contentOffset.x == 0){
[self.scrollView scrollRectToVisible:CGRectMake(self.view.frame.size.width*pathImages.count, 0, self.view.frame.size.width, self.view.frame.size.height) animated:NO];
}
if (self.scrollView.contentOffset.x == self.view.frame.size.width*pathImages.count)
{
[self.scrollView scrollRectToVisible:CGRectMake(self.view.frame.size.width,0 ,self.view.frame.size.width, self.view.frame.size.height) animated:NO];
}
else
[UIView animateWithDuration:1
delay:0
options:UIViewAnimationOptionCurveEaseInOut
animations:^{ self.scrollView.contentOffset = CGPointMake(h, 0); }
completion:NULL];
}
This magic line:
[UIView animateWithDuration:1
delay:0
options:UIViewAnimationOptionCurveEaseInOut
animations:^{ self.scrollView.contentOffset = CGPointMake(h, 0); }
completion:NULL];
does the scoll automatically with animation.
Everything is great except this:
after I view the last picture I should set the offset of scroll view in order to get back to the first picture with animation.
Well if I do that:
if (self.scrollView.contentOffset.x == self.view.frame.size.width*pathImages.count)
{
[UIView animateWithDuration:1
delay:0
options:UIViewAnimationOptionCurveEaseInOut
animations:^{ [self.scrollView scrollRectToVisible:CGRectMake(self.view.frame.size.width,0 ,self.view.frame.size.width, self.view.frame.size.height) animated:NO]; }
completion:NULL];
}
after the last picture is viewed in order to get to the first picture...it loops through all the other pictures.
What I want is this:after I view the last picture to get me back to the first picture which should be loaded on screen using animation, but without viewing all the other pictures between them.Thanks
If I see this correctly, the problem is, that you again use the animation to scroll the view back to zero position. I believe you need to modify the last bit of code you posted to something like this:
if (self.scrollView.contentOffset.x == self.view.frame.size.width*pathImages.count)
{
[self.scrollView scrollRectToVisible:CGRectMake(self.view.frame.size.width,0 ,self.view.frame.size.width, self.view.frame.size.height) animated:NO];//no animation on returning
[self onTimer];//even if this code is already inside method "onTimer"
}
Rather then what you are doing try using a scrollview that displays only 3 to 5 images at the time (if they are fullscreen). If you will have many images in your application, it will crash because of high memory consumption. Try playing with this test example that does nearly what you want:
HEADER:
#import <Foundation/Foundation.h>
#interface IScrollView : UIScrollView <UIScrollViewDelegate> {
NSMutableArray *imagePaths;
UIImageView *imageViews[3];
NSInteger currentImage;
NSTimer *animationTimer;//weak link
}
#end
SOURCE:
#import "IScrollView.h"
#implementation IScrollView
- (UIImage *)imageFromResourcesWithName:(NSString *)name {
UIImage *ret = [[UIImage alloc] initWithContentsOfFile:[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:name]];
return [ret autorelease];
}
- (id)initWithFrame:(CGRect)frame {
if((self = [super initWithFrame:frame])) {
imagePaths = [[NSMutableArray alloc] init];
[imagePaths addObject:#"imag1.png"];
[imagePaths addObject:#"imag2.png"];
[imagePaths addObject:#"imag3.png"];
[imagePaths addObject:#"imag4.png"];
[imagePaths addObject:#"imag5.png"];
imageViews[0] = [[UIImageView alloc] initWithFrame:CGRectMake(320.0f*0, .0f, 320.0f, 480.0f)];
imageViews[1] = [[UIImageView alloc] initWithFrame:CGRectMake(320.0f*1, .0f, 320.0f, 480.0f)];
imageViews[2] = [[UIImageView alloc] initWithFrame:CGRectMake(320.0f*2, .0f, 320.0f, 480.0f)];
[self addSubview:imageViews[0]];
[self addSubview:imageViews[1]];
[self addSubview:imageViews[2]];
imageViews[0].image = [self imageFromResourcesWithName:[imagePaths objectAtIndex:0]];
imageViews[1].image = [self imageFromResourcesWithName:[imagePaths objectAtIndex:1]];
imageViews[2].image = [self imageFromResourcesWithName:[imagePaths objectAtIndex:2]];
currentImage = 1;
self.contentOffset = CGPointMake(320.0f*currentImage, .0f);
self.contentSize = CGSizeMake(3.0f*320.0f, 480.0f);
self.delegate = self;
animationTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/60.0 target:self selector:#selector(scrollFragment) userInfo:nil repeats:YES];
}
return self;
}
- (void)repositionIfNeeded {
CGFloat offsetX = self.contentOffset.x;
NSInteger iCount = [imagePaths count];
if(offsetX > 320.0f*1.75f) {
self.contentOffset = CGPointMake(offsetX-320.0f, .0f);
imageViews[0].image = imageViews[1].image;
imageViews[1].image = imageViews[2].image;
NSInteger imageToLoad = currentImage+2;
if(imageToLoad>iCount-1)
imageToLoad -= iCount;
imageViews[2].image = [self imageFromResourcesWithName:[imagePaths objectAtIndex:imageToLoad]];
currentImage++;
if(currentImage>iCount-1)
currentImage -= iCount;
}
else if(offsetX < 320.0f*.25f) {
self.contentOffset = CGPointMake(offsetX+320.0f, .0f);
imageViews[2].image = imageViews[1].image;
imageViews[1].image = imageViews[0].image;
NSInteger imageToLoad = currentImage-2;
if(imageToLoad<0)
imageToLoad += iCount;
imageViews[0].image = [self imageFromResourcesWithName:[imagePaths objectAtIndex:imageToLoad]];
currentImage--;
if(currentImage<0)
currentImage += iCount;
}
}
- (void)scrollFragment {
self.contentOffset = CGPointMake(self.contentOffset.x+1.0, .0f);
[self repositionIfNeeded];
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
[self repositionIfNeeded];
}
- (void)dealloc {
[imageViews[0] release];
[imageViews[1] release];
[imageViews[2] release];
[imagePaths release];
}
#end