How can I make a UILabel change positions randomly? - ios

What I mean by this is, if I have a UILabel that I created, how can I make it change periodically within the view of the screen to a random point? Would I use something like arc4random, or something like a random CGPointMake?
I would have it change every second or so using something like this
Text = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(RandomText) userInfo:nil repeats:YES] ;
but i'm just not sure how to get it to "spawn" in a random place, if possible, and then to remove the other one.
A simpler version would also be, If I just made say, 4 different UILabels, how could I make it appear randomly on one of the 4, and then remove after the time interval? I assume I could use something like
int randomNumber = rand() % 4;
and then put a switch in there, but i'm not sure if that would be the correct way to do it either.

Do you have a single label that you want to move to different points on the screen? Or are you adding multiple labels?
Are you using auto-layout or not? (If you're using auto-layout then you can't just move the label around - instead you need to modify it's position constraints. That gets a little more complicated.)
As to how to move it around, I would suggest using arc4random_uniform to calculate a new location for the label's center.
You could put code like the following into your timer method. In the code below, "view" is the view that contains your label.
The code below keeps the label fully visible on-screen by moving the center no closer to the edges of it's parent view than half the label's width&height.
CGFloat newX = arc4random_uniform(view.bounds.width - label.bounds.width) +
label.bounds.width/2;
CGFloat newY = arc4random_uniform(view.bounds.height - label.bounds.height) + label.bounds.height/2;
label.center = CGPointMake(newX, newY);
If you want the label to move to it's new location in an animation you could use the UIView method animateWithDuration:animations to change the center point in an animation block.
Again, if you're using AutoLayout, you'll need to attach center X and center Y constraints as outlets, and change their value settings to move the label.

Interesting. Maybe this helps. This is just a prototype; by no way a production code. Hope this helps. Consider label,screenHeight and screenWidth as instance level variables.
- (void)viewDidLoad
{
[super viewDidLoad];
label = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 20, 20)];
label.backgroundColor = [UIColor blackColor];
[self.view addSubview:label];
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0
target:self
selector:#selector(createRandomPoint:)
userInfo:nil
repeats:YES];
screenHeight = [UIScreen mainScreen].bounds.size.height;
screenWidth = [UIScreen mainScreen].bounds.size.width;
}
-(void) createRandomPoint:(id)sender {
int randX = arc4random() % screenWidth;
int randY = arc4random() % screenHeight;
label.center = CGPointMake(randX, randY);
}

Related

Animate UILabel value increment

I'm trying to increment a percentage view using the following code:
// Progress
[UIView animateWithDuration:5.0 animations:^{
for (float percent = 0.0; percent <= 0.86; percent+=0.01) {
NSLog(#"%f", percent);
self.circularProgress2.progress = percent;
}
}];
It doesn't animate, it goes straight to the final value. I know I can use NSTimer:
[NSTimer scheduledTimerWithTimeInterval:0.0001 target:self selector:#selector(onLableAnimateTick:) userInfo:nil repeats:YES];
And then change the value from inside the called method. But I have several bars on the same view, so I guess using the first option would be better for me.
If not possible, how would I duplicate the NSTimer behavior without having to create properties and methods for every progress bar?
All the code inside the animation-block will be executed which is your case is a for-loop. Consider the following case:
[UIView animateWithDuration:5.0 animations:^{
CGRect f = aView.frame;
f.origin.x = 20;
f.origin.x = 25;
f.origin.x = 40;
aView.frame = f;
}];
This will animate the view from it's current position to x = 40. Not animate to 20, then to 25, then to 40. The result of the block is that aViews frames origin.x should be 40, no matter what happened before that.
I'd say use a timer if you want to auto-increment the progress with a given interval. You can still animate the change of course (for example by overriding the setProgress-method on your Progress-view class and call an animation from there), but don't use an animation block to increment the model value (progress).

Make a UITableView scroll from top to bottom over a set period of time?

I'm trying to get my UITableView to slowly scroll downwards at a steady speed, which I can specify. I've used scrollToRowAtIndexPath, but whether or not I choose to animate it, it's an almost instant movement. I'm looking at something that moves much more slowly.
I did wonder whether I could do something with a UIView animation block, moving one indexPath.row at a time, but since my cells are different heights, this would cause uneven animation speed.
Any other ways I can do this?
I got it with this..
[NSTimer scheduledTimerWithTimeInterval: 0.025 target:self selector:#selector(scrollTableView) userInfo:nil repeats:YES];
And..
- (void) scrollTableView {
float w = 1;
CGPoint scrollPoint = self.tableView.contentOffset;
scrollPoint.y = scrollPoint.y + w;
if (scrollPoint.y >= self.tableView.contentSize.height - (self.tableView.frame.size.height - 100) || scrollPoint.x <= -self.tableView.frame.size.height + 924) {
w *= -1;
}
[self.tableView setContentOffset: scrollPoint animated: NO];
}
You can always decrement the contentOffset y axis over time.
Here you go buddy. Just change the animateWithDuration to higher seconds like 1 or 1.5 to see if it achieves the effect you want. Make sure you include QuartzCore library and #import <QuartzCore/QuartzCore.h> in your *.m file. This is as easy as it gets
-(IBAction)modeTableSlowly
{
[UIView animateWithDuration:0.5 delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
//here tblSimpleTable2 is tableView
[tblSimpleTable2 setFrame:CGRectMake(183, 56, 137, 368)];
} completion:nil];
}

iOS: Programatically align button x pixels from bottom of screen

I'm creating compatibility for iOS6 for an app made by someone else. I'm used to using making buttons/UI elements with autoresizing masks but I don't really know how they work when you're creating the button programatically.
For example:
- (UIButton*) createSampleButton {
UIButton* b = createSampleViewButton(CGRectMake(67, 270, 191, 45),
#"btn_shuffle",
#"btn_shuffle_active",
self,
#selector(sampleAction));
b.autoresizingMask = UIViewAutoresizingFlexibleTopMargin;
[self attachButton:b];
return b;
}
How can I change these buttons such that they'll be placed according to some scale/margin instead of arbitrarily choosing points until everything "looks right" ?
I was thinking of something like:
- (UIButton*) createSampleButton {
CGFloat height = self.bounds.size.height;
CGFloat bottomBound = 80;
UIButton* b = createSampleViewButton(CGRectMake(67, height-bottomBound, 191, 45),
#"btn_shuffle",
#"btn_shuffle_active",
self,
#selector(sampleAction));
[self attachButton:b];
return b;
}
This would guarantee me that the button is placed 80 points from the bottom of the screen every time right? Is there a more graceful or purposeful way of doing this?
The masks are the same as when created in IB or code. The thing you want to make sure to do in code though is make sure the frames are set properly proportioned once. In your case, yes you do want UIViewAutoResizingFlexibleTopMargin, and setting the correct y-value on the origin in terms of y = parentView.bounds.size.height - (x points as you described), is all you need to do.
EDIT:
According to your updated question, maybe this will help you. If the button has a constant size, set the frame to that size with CGPointZero as the origin when you create the button. If a UIView owns the button, then put this code in layoutSubviews. If a UIViewController owns the button, replace self.bounds with self.view.bounds and put this in view(Will/Did)LayoutSubviews (Assuming iOS5+).
// Aligning the button at it's current x value, current size, with its bottom border margin pizels from the bottom of the parent view.
CGFloat margin = 10;
CGRect buttonFrame = button.frame;
buttonFrame.origin.y = self.bounds.size.height - buttonFrame.size.height - margin;
button.frame = buttonFrame;
Also, define constant values at the top of the implementation file. Feel free to create convenience methods for readability (if you find this more readable and not doing too much on one line) such as
CGRect CGSetYInRect(CGFloat y, CGRect rect)
...
button.frame = CGSetYInRect(self.bounds.size.height - button.frame.size.height - margin, button.frame);
Use AutoResizing when appropriate to avoid explicit logic in layoutSubviews.
When you move to iOS 6 + only, use AutoLayout.

Generating an infinite number of objects in Xcode

I'm working on a game right now, in which every second, I want to create x number of new UIImage objects that begin at the top of the screen. After they have been instantiated, I want them automatically to fall down until they reach the bottom of the screen, at which point I no longer have any use for them.
Its almost like raindrops - X number of them are created every second, and they each fall down at different speeds.
I'm getting really confused as to how I would even just design my program to do this.
Any help would be greatly appreciated. Thanks.
Are they all copies of the same image, or at least copies of one among a limited set of images?
For such a game-like, graphics intensive app I would seriously consider using OpenGL ES, although the learning curve is steep for people familiar with UIKit only. Fortunately, there are third party, open-source libraries such as Cocos2d that make efficient 2d graphics almost as easy to code as UIKit.
Regarding your question in particular, I haven't watched the video mentioned by #ctrahey, but I can think of these patterns:
Have a (finite) 'pool' of reusable objects, which size is equal to the maximum amount of instances that might appear on screen at any given time. You definitely want to set this limit, since graphics performance is not infinite. Each time an object falls off-screen, 'reset' its state and reuse it (from the top, again). UITableView does something like this with table cells.
Create the instances on demand, and destroy them (release->dealloc) once they go off-screen.
You have to balance the runtime cost of creating/destroying instances vs. the cost/inconvenience of resetting objects.
Hope it helps
Step 1: Run a piece of code every second
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(dispatchSomeRaindrops) userInfo:nil repeats:YES];
Step 2: Create some particles, send them down the screen, and clean them up when they reach the bottom.
- (void)dispatchSomeRaindrops
{
for (int i = 0; i < 5; i++) {
UIImageView *view = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"safari.png"]];
CGFloat halfHeight = view.frame.size.height / 2;
CGFloat x = arc4random() % (int)self.view.frame.size.width;
view.center = CGPointMake(x, -halfHeight);
[self.view addSubview:view];
NSTimeInterval duration = 10 + arc4random() % 10;
[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
float endY = self.view.frame.size.height + halfHeight;
view.center = CGPointMake(x, endY);
} completion:^(BOOL finished) {
[view removeFromSuperview];
}];
}
}
Check out the Core Animation video from WWDC 2011, and near the end there is a bit on "Replicators", and it sounds like exactly what you are after.
FYI: found a terrific resource to handle this exact scenario. It does require you to use cocos2d, but it explains it in a very clear and understandable manner.
http://www.raywenderlich.com/352/how-to-make-a-simple-iphone-game-with-cocos2d-tutorial

iOS - how to add one UIButton with respect to another?

I am an iOS newbie, so please bear with me. I have a blank page with a button centered in it. I want to add another button to the view, just below the centered button. How would I do that? I have added the first button like this -
float x=60, y=200, dy=50;
CGRect frame = CGRectMake(x, y, 200, dy);
UIButton *inboxButton = [[[UIButton alloc] initWithFrame:frame]autorelease];
inboxButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
inboxButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
....
[theView addSubview:inboxButton];
Just calculate the second frame based on the first
CGRect secondFrame = CGRectMake(CGRectGetMinX(frame),
CGRectGetMaxY(frame) + 8.0, // some y padding
CGRectGetWidth(frame),
CGRectGetHeight(frame));
You are not saying if you need that second one centered by itself - I am assuming that you just want it below, left-aligned with the first one:
UIButton *outboxButton = [[[UIButton alloc] initWithFrame:CGRectMake(frame.x,
frame.y + dy + 10.0f,
frame.width,
frame.height)] autorelease];
[theView addSubview:outboxButton];
What I am doing here is simply reusing the horizontal coordinate from the first button. For the vertical coordinate, I am using the original coordinate and add the height and an offset (10.0f) to it. Both, the width and the height are taken from the first button, assuming that they should match in size.
As you will see, there is no way to have this calculation done implicitly, which I assume you actually wanted to find out - that is, by simply supplying some ordering arguments.

Resources