I have a relatively simple question but I can't seem to find the answer anywhere. When I use:
UIScreen.main.bounds.height
Does this give me the height from the bottom edge of the screen all the way to the top or only till the safe area? For eg. is the height only until the notch for the iPhone X or does it go all that way up past the notch.
is the height only until the notch for the iPhone X or does it go all that way up past the notch
You can easily check this yourself. Set a breakpoint somewhere in any iOS project, and see what rectangles are returned by bounds or nativeBounds for the main screen when the app runs on the device you're interested in, e.g. iPhone X:
(lldb) po [[UIScreen mainScreen] bounds]
(origin = (x = 0, y = 0), size = (width = 375, height = 812))
(lldb) po [[UIScreen mainScreen] nativeBounds]
(origin = (x = 0, y = 0), size = (width = 1125, height = 2436))
You can check that against the dimensions reported for the screen in Apple's documentation:
I'd assume from that that the rectangle returned by bounds for the main screen represents the entire screen, not just the safe area. But if you're still not convinced, you could write a few lines of code that draws a rectangle with those dimensions, and you'll see that the notch and corners occlude parts of the rectangle:
Related
I am working on an ObjectiveC app in which I need to set the width and height of a uiview in pixels and than scale that uiview equal to the devices width. The width and height values in pixels are fixed ( let say 900 px x 500 px).
Currently I am doing this,
UIScreen* mainScreen = [UIScreen mainScreen];
CGRect frame = CGRectMake(0, 0, 900.0, 500.0);
[view setFrame:frame];
CGFloat valScale = mainScreen.bounds.size.width/900.0;
[view setContentScaleFactor:valScale];
But this is not giving me the desired values.
What should I do?
(P.S) Does view.frame.size.width return the width in pixels or points?
Hi for scaling a view you can use the transform property. Say you wish to scale your UIView by a factor of 2 then you can use.
self.view.transform = CGAffineTransformScale(CGAffineTransformIdentity, 2, 2);
CGRect width and height returns points not pixels. One point has two pixels for 2x devices like iPhone 6,7 and three pixels for 3x devices like iPhone 6 Plus,7 Plus.
For more detail you can refer this Apple's documentation link.
Considering that iPhone X Notch has smooth curves (no rectangle around notch), How to find if a pixel (x,y) on captured screenshot is part of draw buffer covered by the notch (vs actual display buffer) on iPhone X?
I am trying to log start X and end Y (pixel) position for actual pixels drawn for each of the horizontal scan lines when iPhone X is in landscape mode.
Is there a way to use inbuilt api to get this information? [[UIScreen mainScreen] nativeBounds] won't suffice in this case.
Hardcoding values or proving an image mask to detect it is possible. I am wondering if there is a more robust way to find width in pixel for scan line A/B/C in attached pic.
// For a given scan-line for a given Y = any-value between 0 & window.screen.height (Landscape orientation)
+ (CGPoint)printScanlineForY:(NSUInteger )y {
// what goes here?
...
// Case 1: expected for non-notch scan-line, return CGPointMake(0, screen-width)
// Case 2: expected for notch affected scan-line, return (non-0, screen-width)
// non-0 as determined by notch draw curve.
}
// Returning nativeBounds CGRect would return larger bounding box for entire screen.
// Output on iPhone X simulator: Native Screen Bounds: {{0, 0}, {1125, 2436}}
+ (CGRect)printScreenBounds {
CGRect bounds = [[UIScreen mainScreen] nativeBounds];
NSLog(#"Native Screen Bounds: %#", NSStringFromCGRect(bounds));
return bounds;
}
Related question with helpful details: Detect if the device is iPhone X
You can reference the documentation here which has some nice images
https://developer.apple.com/ios/human-interface-guidelines/overview/iphone-x/
If you align your views to layout margins the system should take care of putting your views in visible areas.
If you want to figure out exactly where the notch is you can empirically calculate it by creating a view taking the full screen bounds, and doing a hit hit test for each coordinate , checking if it is "touchable". Collect the coordinates to some sort of array and then use them for future reference.
For instance something like:
#implementation FindNotch
- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event; // recursively calls -pointInside:withEvent:. point is in the receiver's coordinate system
{
UIView *hitView = [super hitTest...];
if (view == null) { ... } // the notch isn't "touchable"
}
#end
FindNotch *notch = [FindNotch alloc] initWithFrame:[UIScreen mainScreen].bound];
static UIWindow *window; window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds;]
window.windowLevel = UIWindowLevelStatusBar + 1; // make sure the view is above anything else in the notch area. Might require some tweaking
Notice that it isn't tested and you may need to raise the window level above the status bar or else it may be "underneath" and not respond to touches
I am facing one strange problem, using the below code I am making the UIScrollView to full screen.
CGRect screenBound = [[UIScreen mainScreen] bounds];
CGSize screenSize = screenBound.size;
CGFloat screenWidth = screenSize.width;
CGFloat screenHeight = screenSize.height;
CGRect scrollFrame = CGRectMake(0, 0, screenWidth, screenHeight);
self.imageHostScrollView.frame = scrollFrame;
NSLog(#"Scroll Height: %f, Width: %f",screenHeight,screenWidth);
The problem I am facing when the iPad is in the Portrait mode, the height will be big and width will be small, instead I am getting height smaller and width bigger (same happens in Landscape mode also).
Portrait mode the value I am getting is
Scroll Height: 768.000000, Width: 1024.000000
In Landscape mode the value I am getting is
Scroll Height: 1024.000000, Width 768.000000
Can anyone help me
The problem is that the way you're setting the self.imageHostScrollView.frame is silly. You are effectively hard-coding assumptions about the screen into the frame of a view — two things that are completely unrelated to one another.
Instead, use auto layout to pin the edges of the scroll view to the edges of the window. That way, whatever the window may do from now on — making no assumptions about what that may be — the scroll view will continue to fill it exactly.
I've tried
self.lblTimer = [[UILabel alloc] initWithFrame:CGRectMake(x,y,width,height)];
..but since the label i'm looking to position is at the bottom of the screen it goes out of view when i switch devices. I'm trying to make the label 10 pixels in from the left and 10 pixels up from the bottom. It should look consistent regardless if it's viewed on iPhone 4, 5, 6 or 6 plus.
So, your question is about X and Y, right?
The points in iOS start at the top left corner of the screen, so the top left corner of the screen is (0,0).
If you move up/down along the left edge, the X coordinate will continue to be 0. So if you want 10 points to the right of the left edge, X will be 10.
The bottom of the screen can be calculated this way:
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenWidth = screenRect.size.width;
CGFloat screenHeight = screenRect.size.height;
In here, the variable screenHeight will be the bottom line of the screen. So if you want 10 points above the line, you'll need to get (screenHeight - 10).
However, as mentioned by Lyndsey Scott in the comments below, this places the top left corner of your label in the top screenHeight - 10, which could (very likely with a value of 10) place your label out of sight.
To solve this, you also subtract the height of the label so the label is in sight, in the correct spot.
So your final answer is:
CGRectMake(10,(screenHeight - height - 10),width,height);
How to get the screen width and height only in landscape orientation , i have two ipad 4 tablets and on one of them it takes me the landscape width & height , and on the other one it takes me the portrait one even if it's orientation is on lanscape
at the moment i am using this but its not working well
CGFloat width = self.view.bounds.size.width;
CGFloat height = self.view.bounds.size.height;
Use [UIScreen mainScreen].bounds you'll have the same.
Discussion
This rectangle is specified in the current coordinate
space, which takes into account any interface rotations in effect for
the device. Therefore, the value of this property may change when the
device rotates between portrait and landscape orientations.
Use [UIScreen mainScreen].nativeBounds in iOS8 only to get the portrait-locked bounds.
Discussion This rectangle is based on the device in a
portrait-up orientation. This value does not change as the device
rotates.
Swift 3
let pixelWidth = UIScreen.main.nativeBounds.width
let pixelHeight = UIScreen.main.nativeBounds.height
let pointWidth = pixelWidth / UIScreen.main.nativeScale
let pointHeight = pixelHeight / UIScreen.main.nativeScale
print ("Pixels: \(pixelWidth) x \(pixelHeight)")
print ("Points: \(pointWidth) x \(pointHeight)")
On a 6s Plus will print...
Pixels: 1080.0 x 1920.0
Points: 414.0 x 736.0