I have 4 different buttons for every corner of the screen. Just need to show their coordinates for every device changes in a text field or a label.
“x0” - button x coordinate on the screen
“y0” - button y coordinate on the screen
i should show like x = "x0" ; y = "y0"
There is an easy built-in way to log frames. Use NSStringFromCGRect(frame); to show the coordinates of the button.
Although you can directly print a CGRect using NSStringFromCGRect, here is a sample of what you are looking for. I'm just putting button1's coordinates in text field.
UIButton *button1, *button2, *button3, *button4;
CGFloat button1X = button1.frame.origin.x;
CGFloat button1Y = button1.frame.origin.y;
CGFloat button2X = button2.frame.origin.x;
CGFloat button2Y = button2.frame.origin.y;
CGFloat button3X = button3.frame.origin.x;
CGFloat button3Y = button3.frame.origin.y;
CGFloat button4X = button4.frame.origin.x;
CGFloat button4Y = button4.frame.origin.y;
NSString *button1Coords = [NSString stringWithFormat:#"x = \"%f\" x = \"%f\"", button1X, button1Y];
self.textField.text = button1Coords;
Related
This is the code I'm using to center my button to the bottom of the screen:
CGFloat centro = self.view.center.x;
CGFloat bottom = CGRectGetMaxY(self.view.frame);
_sendButton.center = CGPointMake(centro, bottom);
However, the actual center of the button is set to be at the bottom of the screen, which covers half the button. How can I set it so that the very lowest point on the button is set to:
CGPointMake(centro,bottom)
instead?
You need to subtract half the height of the button:
CGFloat centro = self.view.center.x;
CGFloat bottom = CGRectGetMaxY(self.view.frame) - _sendButton.frame.size.height / 2.0;
_sendButton.center = CGPointMake(centro, bottom);
I have 2 UIImageView. Both UIImageView has the same size proportion. The first UIImageView's size is always smaller or equal to the second UIImageView's size.
On the first UIImageView I have a UIView. This UIView the user can place it anywhere on the first UIImageView.
I want to find the x,y of the second UIView that will be on the second UIImageView with same proportion as the first UIView.
Please look at this image to be clear. Please note that Rectangle 1 is first UIImageView and Rectangle 2 is second UIImageView.
What I've tried:
CGFloat xMultiplier = imageView2.frame.size.width / imageView1.frame.size.width;
CGFloat yMultiplier = imageView2.frame.size.height / imageView1.frame.size.height
CGFloat view2x = view1.frame.origin.x * xMultiplier;
CGFloat view2y = view1.frame.origin.y * yMultiplier;
My application is an application that users can choose stickers (UIView) and place it anywhere on their photo. The stickerView on the second image is not in the same place as stickerView in the second image
The resulting x,y for my code is close to where it should be but its not exactly where it should be.
What am I missing?
Thanks!
First you should get the factor ( which you are already doing correctly ) , but then you have to calculate it proportionally to Point1 ( to some point in View1 ) , for example
CGFloat yFactor = view1.frame.size.height / view2.frame.size.height;
CGFloat xFactor = view1.frame.size.width / view2.frame.size.width;
CGPoint pointInView2 = CGPointMake(pointInView1.x / xFactor,pointInView1.y / yFactor);
pointInView1 is the origin of Sticker in View1
if sticker2 is subview of view2 , then origin will be pointInView2
if sticker2 is not subview of view2 , and they have the same superview , the origin will
CGPointMake(pointInView2.x + view2.frame.size.width,pointInView2.y + view2.frame.size.height);
if there is any other hierarchy , you can use UIVIews method convertPoint ...
[view2 convertPoint:pointInView2 toView:sticker2.superView]
assuming that the rectangle 2 is merely a rescaled version of rectangle 1. the position of view 2 is :
xpos_view2 = xpos_view1/xwidth_Rect1 * xwidth_Rect2
ypos_view2 = ypos_view1/ywidth_Rect1 * ywidth_Rect2
View2.position = CGPoint(x:xpos_view2, y:ypos_view2)
Calculate Ratio from smallest iPhone device
func ratioW(_ ofSize : CGFloat) -> CGFloat {
let bounds = UIScreen.main.bounds
let windowWidth = bounds.size.width
let temp = 320/ofSize
return windowWidth / temp
}
func ratioH(_ ofSize : CGFloat) -> CGFloat {
let bounds = UIScreen.main.bounds
let windowHeight = bounds.size.height
let temp = 480/ofSize
return windowHeight / temp
}
I'm working in Spritekit and I'm pretty new to it. I'm creating a game with levels and for each level I'm trying to position the sprites in my game to be proportionate to the screen size. I'm calling their positions from plist files. Since I am positioning each sprite according to the screen's dimensions and size, I would have to position it something like this
Sprite.position = CGPointMake(self.scene.size.width /2, self.scene.size.height /2);
My question is, how would I be able to convert this position from my plist? I tried using
Sprite.position = CGPointFromString(level[#"Sprite"]);
and typing
CGPointMake(self.scene.size.width /2, self.scene.size.height /2);
in my plist file, but it's not working.
This is how you access data from a plist:
NSString* path = [[ NSBundle mainBundle] bundlePath];
NSString* finalPath = [ path stringByAppendingPathComponent:#"MyGameData.plist"];
NSDictionary *plistData = [NSDictionary dictionaryWithContentsOfFile:finalPath];
The simplest way would probably be to store the x and y positions in 2 separate strings. Something like PlayerPositionX and PlayerPositionY
Then you convert the string to a float like this:
float myFloat = [myString floatValue];
You can also convert a single string into a CGPoint like this:
CGPoint myPoint = CGPointFromString([NSString stringWithFormat:#"{%#}",textField.text]);
The string has to be in the format {x,y}
(Credit to jrturton for his answer here).
You could solve the problem of positioning your sprites proportionate to the screen size in the following way:
First you create your plist like this:
Sprite = {
x = 20;
y = 20;
}
Then you can obviously get the values with:
NSDictionary *spriteInfo = plist[#"Sprite"];
NSNumber *xPosition = spriteInfo[#"x"];
NSNumber *yPosition = spriteInfo[#"y"];
Now you can interpret these values in two ways:
They represent the position your sprite should be on a default screen (ex: 320x568) and you get the actual position with:
actionPosition = xPosition * screenSize / defaultScreenSize;
//ex: 40 = 20 * 640 / 320, if the current device has a width of 640.
Or the represent % values, aka the sprite should be at 20% of the screen, thus you'd get the actual position with:
actionPosition = screenSize * xPosition / 100;
//ex: 128 = 20 * 640 / 100, if the current device has a width of 640.
I'm making a game that doesn't use Autolayout, and have used constraints to scale everything and it worked perfectly. However I cant seem to figure this out, I'm using arc4random to randomly position X and Y coordinates of a UIButton on the 4.7 inch screen. When I try running it on the smaller screen it plots the UIButton off the screen at times. How can I scale arc4random up and down depending on screen size.
-(void)position{
Randompositionx = arc4random() %270;
Randompositionx = Randompositionx + 51;
Randompositiony = arc4random() %411;
Randompositiony = Randompositiony +163;
UIButton.center = CGPointMake(Randompositionx, Randompositiony);
}
You should be using arc4random_uniform rather than arc4random and the modulo operator. It gives numbers without "modulo bias".
You need to adapt the upper value of your random number based on screen size. T_77's answer was a step in the right direction, but still not right.
The code below assumes the button you want to move is called myButton.
It uses margin values of 20 all around. Change the values as desired.
EDIT: I updated it to use the height and width of the button in the position calculation. With the updated code the button should never be closer to any edge than the margin value, even if the button size changes. No magic numbers, either. It should adapt to the size of it's superview.
-(void)position
{
CGRect frame = myButton.superview.bounds;
CGFloat leftMargin = 20; //use whatever values you want for magins
CGFloat rightMargin = 20;
CGFloat topMargin = 20;
CGFloat bottomMargin = 20;
CGFloat randomX, randomY;
CGFloat xMax = frame.size.width-leftMargin-rightMargin-
button.bounds.size.width/2;
randomX = arc4random_uniform(xMax) + leftMargin;
CGFloat yMax = frame.size.height-topMargin-bottomMargin-
button.bounds.size.height/2;
randomY = arc4random_uniform(yMax) + topMargin;
myButton.center = CGPointMake(randomX, randomY);
}
Also note that if you're using auto layout you shouldn't move the button's position directly, and instead should have position constraints and modify their constants, then call layoutIfNeeded. Otherwise the first thing that causes your layout to change will cause your button to revert to it's previous position.
Try this
-(void)position{
CGRect frame = [self.view frame];
Randompositionx = arc4random() %270;
Randompositionx = Randompositionx + CGRectGetMinX(frame);
Randompositiony = arc4random() %411;
Randompositiony = Randompositiony +CGRectGetMinY(frame);
UIButton.center = CGPointMake(Randompositionx, Randompositiony);
}
Now you can position your UIButton within your view.
I've successfully implemented the custom map annotation callout code from the asynchrony blog post .
(When user taps a map pin, I show a customized image instead of the standard callout view).
The only remaining problem is that the callout occupies the entire width of the view, and the app would look much better if the width corresponded to the image I'm using.
I have subclassed MKAnnotationView, and when I set it's contentWidth to the width of the image, the triangle does not always point back to the pin, or the image is not even inside it's wrapper view.
Any help or suggestions would be great.
Thanks.
I ran into a similar problem when implementing the CalloutMapAnnotationView for the iPad. Basically I didn't want the iPad version to take the full width of the mapView.
In the prepareFrameSize method set your width:
- (void)prepareFrameSize {
// ...
// changing frame x/y origins here does nothing
frame.size = CGSizeMake(320.0f, height);
self.frame = frame;
}
Next you'll have to calculate the xOffset based off the parentAnnotationView:
- (void)prepareOffset {
// Base x calculations from center of parent view
CGPoint parentOrigin = [self.mapView convertPoint:self.parentAnnotationView.center
fromView:self.parentAnnotationView.superview];
CGFloat xOffset = 0;
CGFloat mapWidth = self.mapView.bounds.size.width;
CGFloat halfWidth = mapWidth / 2;
CGFloat x = parentOrigin.x + (320.0f / 2);
if( parentOrigin.x < halfWidth && x < 0 ) // left half of map
xOffset = -x;
else if( parentOrigin.x > halfWidth && x > mapWidth ) // right half of map
xOffset = -( x - mapWidth);
// yOffset calculation ...
}
Now in drawRect:(CGRect)rect before the callout bubble is drawn:
- (void)drawRect:(CGRect)rect {
// ...
// Calculate the carat lcation in the frame
if( self.centerOffset.x == 0.0f )
parentX = 320.0f / 2;
else if( self.centerOffset.x < 0.0f )
parentX = (320.0f / 2) + -self.centerOffset.x;
//...
}
Hope this helps put you on the right track.