I'm trying to customise the design for XS Max. Previously I just identified the device by checking the main.bound.screen.height, which, for XS Max, according to this site: https://www.paintcodeapp.com/news/ultimate-guide-to-iphone-resolutions, should return 896.0, right?
The Xcode 10.0 XS Max simulator returns 812.0 as screen height (the same goes for XR, which should have the same screen points), though. Any idea how to fix this?
enum IPhone: String {
case SE, normal, plus, X, XSMax
init?(height: CGFloat) {
switch height {
case 568: self = .SE
case 667: self = .normal
case 736: self = .plus
case 812: self = .X
case 896: self = .XSMax
default:
return nil
}
}
}
struct Design {
static var iPhone = IPhone(height: UIScreen.main.bounds.height)!
}
In the viewDidLoad() of the view controller:
print("screen height: \(UIScreen.main.bounds.height), iPhone: \(Design.iPhone.rawValue)")
Ok, after some searching I've found the answer to my question here: UIScreen MainScreen Bounds returning wrong size
Turns out, Xcode will guess the size of the screen by going through the launch images you've provided. Can you believe that? So if you didn't provide an image in the proper size for the new XS Max it will fall back to the biggest launch image it finds. That's why in a new project without launch images it worked fine.
I've provided launch images for XS Max and XR and now the screen sizes are correct.
Related
UIScreen.main.bounds.width and UIScreen.main.bounds.height are both wrong. It's returning 414x736 but it should be about 360x640.
Device: iPhone 8 Plus.
iPhone [Any] Plus native rendering resolutions are downsampled by ÷1.15 because screens didn't have enough pixels to show #3x until iPhone X arrived.
Screen resolution is 360x640 physical points but screen rendering is 414x736 software points. That only happens on Plus models.
414 ÷ 1.15 = 360
736 ÷ 1.15 = 640
Check out this: https://www.paintcodeapp.com/news/iphone-6-screens-demystified
It depends on when you call the function.
You have to call this after View Appear fully.
override func viewDidLoad() { // Or viewDidAppear()
{
let frame = self.view.bounds; // or UIScreen.main.bounds also works
}
You will get different value if you call the function on viewWillAppear.
I read the native height of the phone to size my display output, and determine top and bottom keep out areas. This is a tab based app. My display is purely programmatic, it is graphically layed out based on screen dimension only. On the iPhone 12 mini, the display is smaller than it should be. The other iPhone 12 types display correctly.
While testing my new app on various iPhone types in the xcode simulator, they
looked correct. But when I put the app on my iPhone 12 mini, the display was smaller than it should be. I learned the simulator returns the value 2436 for native height, but the phone returns the value 2340.
This code examines the display and tells me how much to reserve on the top and bottom of the screen by type of phone:
nativeHeight=UIScreen.main.nativeBounds.height
if nativeHeight==1136 || nativeHeight==1334 // SE,6S,7,8
{reserveTopPixels=40; reserveBottomPixels=98}
else if nativeHeight==1792 // 11, XR
{reserveTopPixels=88; reserveBottomPixels=198}
else if nativeHeight==2208 // 6s+ 7+ 8+
{reserveTopPixels=54; reserveBottomPixels=146}
else if nativeHeight==2436 || nativeHeight==2688 // X, XS, 11Pro, 11, Xr
{reserveTopPixels=132; reserveBottomPixels=260}
else if nativeHeight==2340 //iPhone 12 mini "downsampled screen"
{reserveTopPixels=132; reserveBottomPixels=260; nativeHeight = 2436}
else if nativeHeight==2532 // 12, 12 pro
{reserveTopPixels=132; reserveBottomPixels=260}
else if nativeHeight==2778 // 12 pro max
{reserveTopPixels=132; reserveBottomPixels=260}
else {reserveTopPixels=40; reserveBottomPixels=98}
My correction is to change the value received from the phone, 2340, to a larger value, 2436.
The app displays correctly now on both the simulator and the phone. My question is, is this a reasonable solution, or should I try something else.
nativeBounds: CGRect. : provides the bounding rectangle of the physical screen, measured in pixels. And the physical screen for iPhone 12 mini is 1080×2340 pixels
The iPhone 12 mini has a physical screen resolution of 1080 x 2340 pixels (476 ppi). This is lower than the native resolution reported by the operating system (using nativeBounds on UIScreen). I assume this is to maintain compatibility with the resolutions of the 5.8" models (iPhone X/XS/11 Pro).
Reference :
https://hacknicity.medium.com/how-ios-apps-adapt-to-the-various-iphone-12-screen-sizes-e45c021e1b8b
https://useyourloaf.com/blog/iphone-12-screen-sizes/
It depends on where you are using this nativeHeight to layout.
As you indicated you have problem just for on the iPhone 12 mini simulator. Then Why do you need all checking logic ? Just be sure you working on simulator and catch the iPhone 12 mini and make your adjustment. I think that extension would make sense.
static var isSimulator: Bool {
return TARGET_OS_SIMULATOR != 0
}
extension UIDevice {
var modelIdentifier = ""
modelIdentifier = ProcessInfo.processInfo.environment["SIMULATOR_MODEL_IDENTIFIER"] ?? ""
let nativeHeight = UIScreen.main.nativeBounds.height
if nativeHeight==2340 // your specific case
{
reserveTopPixels=132; reserveBottomPixels=260; nativeHeight = 2436
}
}
Edit
Then If you want certain code to be run only in the iOS simulator either device, you should use this:
func adjust() {
#if targetEnvironment(simulator)
// we're on the simulator
}
#else
// we're on a device
}
#endif
}
I have tried creating a game in unity and build it on ios on any apple devices there were no problem except on iphone x. Screenshot is below.enter image description here. It was covered by the iphone x notch and then when when the character is on the left or the right side it was cut it half.Is there any other solution or a plugin we can use to solve the issue ?. Is there a unity settins or xcode settings to that ? .Thank You
About the iPhone X notch, you can use this:
Screen.safeArea
It is a convenient way to determine the screen actual "Safe Area". Read more about it in this thread.
About the character cutting in half, this is probably something you need to take care of manually based on your game logic. By getting the Screen.width - you should be able to either adjust the Camera (zoom out) or limit the character movement in a way that it will not get past the screen edge.
For the iPhone X and other notched phones you can use the generic Screen.safeArea provided by Unity 2017.2.1+. Attach the script below to a full screen UI panel (Anchor 0,0 to 1,1; Pivot 0.5,0.5) and it will shape itself to the screen safe.
Also recommended to have your Canvas set to "Scale With Screen Size" and "Match (Width-Height)" = 0.5.
public class SafeArea : MonoBehaviour
{
RectTransform Panel;
Rect LastSafeArea = new Rect (0, 0, 0, 0);
void Awake ()
{
Panel = GetComponent<RectTransform> ();
Refresh ();
}
void Update ()
{
Refresh ();
}
void Refresh ()
{
Rect safeArea = GetSafeArea ();
if (safeArea != LastSafeArea)
ApplySafeArea (safeArea);
}
Rect GetSafeArea ()
{
return Screen.safeArea;
}
void ApplySafeArea (Rect r)
{
LastSafeArea = r;
Vector2 anchorMin = r.position;
Vector2 anchorMax = r.position + r.size;
anchorMin.x /= Screen.width;
anchorMin.y /= Screen.height;
anchorMax.x /= Screen.width;
anchorMax.y /= Screen.height;
Panel.anchorMin = anchorMin;
Panel.anchorMax = anchorMax;
}
}
For a more in depth breakdown, I've written a detailed article with screenshots here: https://connect.unity.com/p/updating-your-gui-for-the-iphone-x-and-other-notched-devices. Hope it helps!
Sorry for the late answer but I have adjusted the camera's viewport rectangle for iOS devices and it works correctly. Check if it works for your camera as well.
I have tried safeArea and other script based solutions which do not seem to work.
#if UNITY_IPHONE
mainCamera.rect = new Rect(0.06f, 0.06f, 0.88f, 1);
#endif
I've tried
self.frame.size
self.view!.frame.size
UIScreen.mainScreen().bounds.size
None of them work.
How do I get the correct screen size for the device?
You can use following swift code to get the screen size.
let displaySize: CGRect = UIScreen.mainScreen().bounds
let displayWidth = displaySize.width
let displayHeight = displaySize.height
You can use:
let deviceWidth = UIScreen.mainScreen().bounds.width
let deviceHeight = UIScreen.mainScreen().bounds.height
And if you need to get the ratio so you can detect what device they are using, you can use the following for portrait mode or switch it for landscape mode.
let maxAspectRatio: CGFloat = deviceHeight / deviceWidth
You can then check what ratio the device is to determine certain things.
if maxAspectRatio == (4 / 3) {
//The ratio of an iphone 4S is 4:3
print("The user is using an iPhone 4S or iPod 4th Generation.")
} else if maxAspectRatio >= 1.7 && maxAspectRatio <= 1.8 {
//The ratio of these devices is 16:9
print("The user is using an iPhone 5, 5S, 5C, 6, 6S, 6 Plus, 6S Plus, or iPod 5th Generation.)
} else {
print("The user is using an iPad, iPad Mini, iPad Air, iPad Retina, or iPad Pro.")
}
If you want to get the correct view that the player can see, as in the bounding frame of the device's size, you can use the following guide.
I've created an app with the latest version of AIR (16.0.0.272) and I'm trying to scale the content to fit any resolution of the iPhone from 4 to 6+
In desktop debugging I see all perfectly scaled changing the stage dimension to test my solution. Trying on my iPhone 5 I can't see the scaled content.
If I comment the resize function everything is ok (I see all the content, not scaled obviously).
That's my solution
private function resize(e:Event=null):void{
w=stageW();
h=stageH();
var initW:Number=640;
var initH:Number=960;
//bg.img.width=w;
trace(w+"/"+h);
main.y=62;
//main.x=w*.5-320;
bg.width=w;
bg.height=h;
menu.bg.width=w;
menu.bg.height=h;
var divisor:Number = 640/w;
main.width = Math.floor(main.width / divisor);
main.height = Math.floor(main.height / divisor);
}
I have tried to temporize the resize call to test it on the iPhone but again after 2000ms I can't see anything.
After this I've tried with a listener addEventListener(Event.ADDED_TO_STAGE, init); calling the resize above at the end of my operations of building UI and so on.
Can't figure why resizing a movieclip that contains my app content make it disappear from iPhone and not from the desktop.
Hope in a solution
Thanks in advance
Capabilities.screenResolutionX and Capabilities.screenResolutionY are what you should use for screen width and height on apps.
Note: the X and Y don't change with rotation - they'll stay the same when screen rotates, so your code to get screen dimensions will look like this:
if (bStagePortrait) {
iScreenWidth = Capabilities.screenResolutionX;
iScreenHeight = Capabilities.screenResolutionY;
} else {
iScreenWidth = Capabilities.screenResolutionY;
iScreenHeight = Capabilities.screenResolutionX;
}
Also use this code to prevent app from resizing or moving:
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
For a variety of reasons, your resize function could be getting called more than once.
main.width = Math.floor(main.width / divisor);
main.height = Math.floor(main.height / divisor);
will continuously make the main clip smaller. It may be better to use a constant or number for size calculation. I usually do something with scaling, though.
main.scaleX = main.scaleY = percentStageScaled;