Currently I am working on an iPhone application. I find some difficulties in fixing the UI layouts.
Is there a tool thats measures the pixels given in my application? Something like a ruler in Microsoft Word or Photoshop around my application which allows me to find the measurements in my app.
Thanks
If I understand correctly, you'r looking for a way to better understand the current (and desired) positions of the UI elements in InterfaceBuilder (whether you're working with xib files or storyboards).
If that's the case, there are two things you need to know:
If you select any object on the screen and press the ALT key then drag the mouse cursor (without pressing the mouse button), you'll see the distance between that element and any other element that you're interested in (the one your cursor is currently pointing to). This makes the positioning of elements on the screen very straight forward and is relatively similar to the rulers you described.
In addition to the previous tool, you have the Size Inspector tab on the top right corner of InterfaceBuilder, in which you can see the sizes and positions (in points, not pixels) of the current element you're editing. The display of this tab changes whether you're using auto-layout or autoresizing masks.
I hope this helps. Good luck!
Screen height and width macros:
#define SCREEN_WIDTH ((([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortrait) || ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortraitUpsideDown)) ? [[UIScreen mainScreen] bounds].size.width : [[UIScreen mainScreen] bounds].size.height)
#define SCREEN_HEIGHT ((([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortrait) || ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortraitUpsideDown)) ? [[UIScreen mainScreen] bounds].size.height : [[UIScreen mainScreen] bounds].size.width)
these macros give SCREEN_HEIGHT and SCREEN_WIDTH whenever you use them for the current Iphone or Ipad device
If you want the scale then you can check the scale like so:
[UIScreen mainScreen].scale;
Point coordinates multiplied by screen scale = Pixel size, so for an Iphone 6+ this is how this would work:
SCREEN_WIDTH * 3 = Pixel width
SCREEN_HEIGHT * 3 = Pixel height
Related
I know this question seems to be a old-school one, but I can't find a nice answer to it, there is the thing:
The logical screen resolutions for iPhone5, iPhone6 and iPhone6+:
iPhone5 320 x 568
iPhone6 375 x 667
iPhone6+ 414 x 736
Assume that I have a square UI element at the center of the screen, and there is three ways to constrain its width(&height) over different devices:
width is constant
width/screen.width is constant
screen.width - width is constant
these three different ways of constraining result in three different appearances:
Picture 1: 3 different appearances
I think the 2nd way of constraining (i.e. middle column in the Picture 1) is most natural from designer's point of view but it's least natural from programmer's point of view. I need to check device type and calculate dimensions and use different images for different devices(autolayout can't help in this circumstance)
1st way seems very natural to implement, but it sucks in practice, especially when dealing with text font sizes.
3rd one also need to judge which image to use programmatically, because three UI elements in three different devices do not match the simple #x2 #x3 scale factors.
Is there any work around to easily implement 2nd way of constraining?
You can just give Horizontally in Container and Vertically in Container constraints to view which is in centre if ViewController and if needed then give Height and Width of View itself.
If you are using storyboard you can easily calculate the 2nd way you want. You can give proportional width with the superview.
As you can see in the image
you can give multiplier to your views.
Or you can create a width constraint in your code such as:
#IBOutlet weak var widthConstraint: NSLayoutConstraint!
and you can update your constraint in your code.
Use Macro's
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_RETINA ([[UIScreen mainScreen] scale] >= 2.0)
#define SCREEN_WIDTH ([[UIScreen mainScreen] bounds].size.width)
#define SCREEN_HEIGHT ([[UIScreen mainScreen] bounds].size.height)
#define SCREEN_MAX_LENGTH (MAX(SCREEN_WIDTH, SCREEN_HEIGHT))
#define SCREEN_MIN_LENGTH (MIN(SCREEN_WIDTH, SCREEN_HEIGHT))
#define IS_IPHONE_4_OR_LESS (IS_IPHONE && SCREEN_MAX_LENGTH < 568.0)
#define IS_IPHONE_5 (IS_IPHONE && SCREEN_MAX_LENGTH == 568.0)
#define IS_IPHONE_6 (IS_IPHONE && SCREEN_MAX_LENGTH == 667.0)
#define IS_IPHONE_6P (IS_IPHONE && SCREEN_MAX_LENGTH == 736.0)
if(IS_PHONE_5){//TODO}
if(IS_PHONE_6){//TODO}
I try to make my Views completely dynamic so the Views can fit any Screen Dimensions. At the Moment i get the screen Width and Height for calculation like this:
CGFloat getDisplayHeight() {
CGSize result = [[UIScreen mainScreen] bounds].size;
return result.height;
}
CGFloat getDisplayWidth() {
CGSize result = [[UIScreen mainScreen] bounds].size;
return result.width;
}
The Problem is that the "Resizable Iphone" Emulator always give me a Width of 768 and a Height of 1024 (Like the iPad). It doesn´t matter when i change the Width and Height Values on the Bottom of the Emulator...is there any new Function i can use for better testing?
EDIT:
I´m still not sure how to handle this exactly...At the Moment i calculate the Size of my Subviews in "viewDidLayoutSubviews" because this is the only Method which shows the correct Width and Heigth of the "resizable Iphone Simulator", the Problem is that when i calculate all my Stuff inside this method it gets called every time when i scroll or touch the UI, so it could be the case that it gets called hundreds of times...and when i try to calculate my Views in "ViewDidAppear" its too late and evrything look reallys weird after the recalculation....
I am trying to build an augmented reality app using the CoreMotion framework. I have tried to go off of Apple's pARk sample code project, but it only works in portrait mode. I need it to work in landscape. When switched to landscape mode the subviews in the overlay view move in the opposite directions and at the wrong rate (they either move too fast or too slow across screen)
I have read other postings that provide two solutions:
Create a reference attitude and apply the inverse of that attitude to the current attitude, as suggested in the CoreMotion Tea Pot Example.
Rotate the quaternion representation of the attitude 90 degrees
I do not think that the first will work because my augmented reality app requires that it be referenced to true north.
I also do not understand the math required to do the second.
Any suggestions on how to accomplish this complex problem I welcome.
How far are you now in your augmented reality app? I think beginning by taking a look at PARk from Apple is harsh. You need to have some advanced mathematical understanding. But if you do, why not!
you can take a look at this repository, this an augmented reality project working on Portrait and Landscape mode. Here is how the rotation is handled:
- (void)deviceOrientationDidChange:(NSNotification *)notification {
prevHeading = HEADING_NOT_SET;
[self currentDeviceOrientation];
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
// Later we may handle the Orientation of Faceup to show a Map. For now let's ignore it.
if (orientation != UIDeviceOrientationUnknown && orientation != UIDeviceOrientationFaceUp && orientation != UIDeviceOrientationFaceDown) {
CGAffineTransform transform = CGAffineTransformMakeRotation(degreesToRadian(0));
CGRect bounds = [[UIScreen mainScreen] bounds];
switch (orientation) {
case UIDeviceOrientationLandscapeLeft:
transform = CGAffineTransformMakeRotation(degreesToRadian(90));
bounds.size.width = [[UIScreen mainScreen] bounds].size.height;
bounds.size.height = [[UIScreen mainScreen] bounds].size.width;
break;
case UIDeviceOrientationLandscapeRight:
transform = CGAffineTransformMakeRotation(degreesToRadian(-90));
bounds.size.width = [[UIScreen mainScreen] bounds].size.height;
bounds.size.height = [[UIScreen mainScreen] bounds].size.width;
break;
case UIDeviceOrientationPortraitUpsideDown:
transform = CGAffineTransformMakeRotation(degreesToRadian(180));
break;
default:
break;
}
[displayView setTransform:CGAffineTransformIdentity];
[displayView setTransform: transform];
[displayView setBounds:bounds];
degreeRange = [self displayView].bounds.size.width / ADJUST_BY;
}
}
You have to rotate all your annotations and then your overlay view after the device rotation!
If you're really stuck, and are willing to use another toolkit, try iPhone-AR-Toolkit. It works in both portrait and landscape.
My app is only allowable in the landscape orientations, and it launches in landscape. Thus, the top left corner when the iPad is landscape is (0,0), so everything works fine.
However, when I pick up "touchesBegan"...it isn't working properly. Only when I tap on like the right two-thirds of the iPad does it pick up the touches. I know it has something to do with the orientation, because the app is literally just blank screen with a single UIView and nothing else. It is quite simple. There are no other possible problems that would cause this.
To be sepecific, if I print out the x location in the touchesBegan function, and if the iPad is held with the home button on the left, the width is 1024. And 1024-768 is 256. This is exactly the x position where it begins to sense my touches. Anything to the left of x=256 does not sense the touches.
How do I fix this?
Check Struts and Springs and make sure that whatever should pick up the touches is covering the whole area and locked to the 4 sides.
To do it programmatically,
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
CGRect appFrame = [[UIScreen mainScreen] applicationFrame];
[self.view setFrame:CGRectMake(0.0f, 0.0f, appFrame.size.width, appFrame.size.height)];
return YES;
// if you want to support only LANDSCAPE mode, use the line below
/*
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft | UIInterfaceOrientationLandscapeRight);
*/
}
This sets the view to occupy the full screen.
The answer is that, when defining the UIWindow, it needs to be defined as
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
and not strict coordinates.
I am making an iPad app that starts out in the portrait orientation but can rotate over to the landscape orientation. In -(void) loadView, I call the function drawView. In drawView, I have this line of code:
CGRect r = [[UIScreen mainScreen] bounds];
The only problem is that it doesn't update itself when I rotate to landscape mode, so it still thinks that the screen is in the vertical orientation and if I want a text view to extend all the across the entire screen, it cuts it off at the 768th pixel, instead of the 1024th pixel. In -(BOOL)shouldAutorotate... I have case UIInterfaceOrientationLandscapeRight: and case UIInterfaceOrientationLandscapeLeft:, and I would have to ideally place CGRect r = [[UIScreen mainScreen] bounds]; under each case, but I don't think that will work. Any suggestions? Thanks for your help!
Edit: I've even tried calling a function with
CGRect r = [[UIScreen mainScreen] bounds];
in it, but it still won't work. I place an NSLog after it and I received a response, so the app is definitely working properly and not crashing, but I am still unable to figure this out. Any ideas? Thanks for your help!
I think your problem could be solved by using the autoresizingMask of UIView;
Does your app happen to rely on plists for configuration? I've seen some apps where you can get landscape but only after you set an orientation key to false.