How to make my ui to be adaptable in all iOS devices.While researching , I saw few code where they've defined the sizes of various devices and designed the ui based on the size values. A sample code of how it is defines is as follows,
#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)
Its tedious, if I have to detect size each time. In case of android, there exists fragments to make ui work with various screen size. Is there any alternative for fragments in iOS and How to make my ui to be adaptable in various devices?
Hello I have one solution for you what i am using in my project.
I am using one simple mathematical equation to do this.
CGRectMake(0, 0,[UIScreen mainScreen].bounds.size.width*100/320, [UIScreen mainScreen].bounds.size.height*100/568);
Here i have one view and according to 5s i want it's size with (100x100) so i give that condition that will take size according to screen size increase or decrease.
In 5s it will take 100x100
In 6 it will take (375*100/320) Width and (667*100/568) Height
May be this will help you.
Related
I made iOS application with swift 3 and Xcode 8.3.2 and it's works correctly(Fit to All of iPhone screen size) but in iPad has problem for fit.
I set iPhone mode in General/Target setting.
Already i did this process and there is no problem.
Please help me to fix it.And i don't wanna to set setting Universal.
See this:
you can set a different storyboard for iPad and iPhone from you info.plist or you can load your specific storyboard from your appdelegate. you can check this link out
well you can change the screen size or component constraint value by using this below code by using it in your class so, you can set your view for iphone and ipad.
struct Device {
// iDevice detection code
static let IS_IPAD = UIDevice.current.userInterfaceIdiom == .pad
static let IS_IPHONE = UIDevice.current.userInterfaceIdiom == .phone
static let IS_RETINA = UIScreen.main.scale >= 2.0
static let SCREEN_WIDTH = Int(UIScreen.main.bounds.size.width)
static let SCREEN_HEIGHT = Int(UIScreen.main.bounds.size.height)
static let SCREEN_MAX_LENGTH = Int( max(SCREEN_WIDTH, SCREEN_HEIGHT) )
static let SCREEN_MIN_LENGTH = Int( min(SCREEN_WIDTH, SCREEN_HEIGHT) )
static let IS_IPHONE_4_OR_LESS = IS_IPHONE && SCREEN_MAX_LENGTH < 568
static let IS_IPHONE_5 = IS_IPHONE && SCREEN_MAX_LENGTH == 568
static let IS_IPHONE_6 = IS_IPHONE && SCREEN_MAX_LENGTH == 667
static let IS_IPHONE_6P = IS_IPHONE && SCREEN_MAX_LENGTH == 736
static let IS_IPHONE_X = IS_IPHONE && SCREEN_MAX_LENGTH == 812
}
now you can set constrain like this:==
if(Device.IS_IPHONE_5 || Device.IS_IPHONE_4_OR_LESS){
//--- set your constrain for iphone 5 and 4
}else if(Device.IS_IPAD){
//--- set your constrain for ipad
}else{
//--- set default constrain
}
I am trying to detect on which iPhone my app is running.
I found this, here at stackoverflow:
#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)
But this doesn't work for me. When I have an iPhone6 in standardmode (not zoomed) it says it is an iPhone5.
I also tested
[UIScreen mainScreen].bounds.size.width
but this returns everytime 320.
In simulator it works perfect but on device it fails.
Can someone help me to find out which iPhone is used?
best regards
Instead of relying on screen size, why not use "[[UIDevice curentDevice] model]" instead?
Here's a tutorial that might help you out.
And if "[[UIDevice currentDevice] model]" isn't detailed enough for you, there's also "sysctlbyname("hw.machine", machineNameAsCString, &size, NULL, 0);", where the tutorial shows how to get a "nice string" (or nice version of the model name) out of it.
There's also Open Source available that you can drop in to determine the Device display name.
I have a project which is supported for iPhone 5 and 4.
I wrote everything in code,i.e. no xibs or storyboards.
For example, a custom cell, there is a imageView like:
self.thumbnailImageView = [[UIImageView alloc]initWithFrame:CGRectMake(10, 10, 300, 180)];
In order to support 6 and plus, I want to scale the frame to fit 6 and plus screen, so I did something like:
self.thumbnailImageView = [[UIImageView alloc]initWithFrame:CGRectMake(CAL(10), CAL(10), CAL(300), CAL(180))];
Where CAL is a Marco:
#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_5_OR_LESS (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)
#define CAL(x) (IS_IPHONE_5_OR_LESS? x : RECAL(x) )
#define RECAL(x) (IS_IPHONE_6?RECAL_6(x):RECAL_6P(x))
#define RECAL_6(x) (x*375.0/320)
#define RECAL_6P(x) (x*414.0/320)
It checks if the device is 5/less or 6/plus and adjust the value accordingly.
I am not sure if this solution is feasible. I tried in simulator and it seemed working fine. Ang suggestions?
I also tried autoresizingMask, but it seems this method needs to change quite a lot of things and it is more complex.
I am attempting to detect whether the current device is iPhone5, iPhone6 or iPhone 6 Plus.
In my app I am already using this macro to detect iPhone 5 which works perfectly.
#define IS_IPHONE_5 (fabs((double)[[UIScreen mainScreen]bounds].size.height - (double)568) < DBL_EPSILON)
Similarly, I use this macro to detect iPhone 6 and iPhone 6 Plus.
#define IS_IPHONE_6 (fabs((double)[[UIScreen mainScreen]bounds].size.height - (double)667) < DBL_EPSILON)
#define IS_IPHONE_6_PLUS (fabs((double)[[UIScreen mainScreen]bounds].size.height - (double)736) < DBL_EPSILON)
The IS_IPHONE_5 macro works as expected in any orientation.
My problem is that the IS_IPHONE_6 and IS_IPHONE_6_PLUS macros do not return true when the device is held in LANDSCAPE. However they do work as expect while the device is held in PORTRAIT. What gives?
Also if anyone has a better recommendation to detect iPhone5, 6 and 6 Plus please share.
This is tested and designed for any combination of iOS system versions and SDK versions
#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)
Note: If iPhone 6 is in zoomed mode the UI is a zoomed up version of iPhone 5. This is reflected in the macros.
Usage: http://pastie.org/9687735
Don't use the screen size for this, it's better to use the hardware model. We are getting more and more screen sizes every year, the less you hard-code screen dimensions in your code the better for your future self.
You need a helper function to get the machine name. I'm using dispatch_once to avoid querying the system multiple times for data that won't change.
NSString* machineName()
{
static NSString* name = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
struct utsname systemInfo;
uname(&systemInfo);
name = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
});
return name;
}
Then define a few macros as needed:
#define IS_IPHONE_6 [machineName() isEqualToString:#"iPhone7,2"]
#define IS_IPHONE_6_PLUS [machineName() isEqualToString:#"iPhone7,1"]
For some models is trickier:
#define IS_IPHONE_5s [machineName() hasPrefix:#"iPhone6,"]
Finally, use the macros in your code:
if (IS_IPHONE_6) {
// for the 6
}
Note: This answer your question (detect models with macros) but you're doing it wrong IMHO. You should use autolayout and size classes, unless you support really old iOS versions...
Take a look at this answer: iOS - How to get device make and model? it doesn't use macros but it does the job. I've seen some similar problems with macros to detect iPhone 6 and iPhone 6 plus. So it would be a better idea to try out the answer from #Ohhmee
EDIT: Of course there probably is a solution detecting it with macros. But I don't know that and I can't find a solution so i'm suggesting a different approach.
Your macros are ridiculous and seem to indicate a fear of floating-point arithmetic.
#define IS_IPHONE_5 ([UIScreen mainScreen].bounds.size.height == 568)
#define IS_IPHONE_6 ([UIScreen mainScreen].bounds.size.height == 667)
#define IS_IPHONE_6_PLUS ([UIScreen mainScreen].bounds.size.height == 736)
will work just as good (or just as bad). Most likely they will work just as bad.
If you are interested in features of the iPhone 6 or 6+, check for the features, not the screen size. It is quite likely that Apple will soon have a 4" phone with all the iPhone 6 features. Or a cheap 6c with a big screen but without iPhone 6 features.
For user interface and so on, just take the mainScreen bounds and lay out your views accordingly. At this point, hard coding for fixed sizes is absolutely ridiculous and will bite you. You should be able to run for example on a 12" iPad with a split screen without problems, and heavens knows what screen size that will be.
I have found many questions related to macros but nothing can help me so please help me
My question is define macros constant with respect to device type.
Please see below code
#define IPAD UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad
#define IS_IPHONE ( [ [ [ UIDevice currentDevice ] model ] isEqualToString: #"iPhone" ] )
#if defined(IPAD)
#define SCREENWIDTH 768
#define SCREENHEIGHT 1024
#define TWIDTH 69
#define THEIGHT 69
#define BX 42
#define BY 0
#elif defined(IS_IPHONE)
#define SCREENWIDTH 320
#define SCREENHEIGHT 480
#define TWIDTH 29
#define THEIGHT 29
#define BX 16
#define BY 34
#endif
this code run well on ipad but in iphone return all ipad values ?
Try this -
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define SCREENWIDTH ((IS_IPAD) ? 768 : 320)
#define SCREENHEIGHT ((IS_IPAD) ? 1024 : 480)
#define TWIDTH ((IS_IPAD) ? 69 : 29)
#define THEIGHT ((IS_IPAD) ? 69 : 29)
#define BX ((IS_IPAD) ? 42 : 16)
#define BY ((IS_IPAD) ? 0 : 34)
This may help
The problem in your code is that you are checking if the macro (IS_IPAD) is defined or not, so whatever the value of IS_IPAD it is always defined, thats why its not going in else part, so check the value of macro. Thanks
That's because IPAD and IS_IPHONE are designed to be used at runtime, not compile time, for example:
if (IPAD) {
[self doIpadSpecificThing];
} else {
[self doIPhoneSpecificThing];
}
They use #define to make them easier to call, but that define expands to:
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
[self doIpadSpecificThing];
} else {
[self doIPhoneSpecificThing];
}
They are designed to be used in a Universal app which work on both iPad and iPhone but do different things depending on which platform they are running.
Therefore you cannot define SCREENWIDTH etc at compile time using IPAD and IS_IPHONE and as far as I am aware there is no compile-time macros available to test for targeting iPad/iPhone (see TargetConditionals.h).
EDIT A comment on the accepted answer:
This answer looks pretty clever and seems to be a good way of saving some typing. However I would like anyone considering using that answer to consider what is happening.
Given:
#define UI_USER_INTERFACE_IDIOM() \
([[UIDevice currentDevice] respondsToSelector:#selector(userInterfaceIdiom)] ? \
[[UIDevice currentDevice] userInterfaceIdiom] : \
UIUserInterfaceIdiomPhone)
And:
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define SCREENWIDTH ((IS_IPAD) ? 768 : 320)
#define SCREENHEIGHT ((IS_IPAD) ? 1024 : 480)
Then a typical use of SCREENWIDTH and SCREENHEIGHT:
[self setWidth:SCREENWIDTH
height:SCREENHEIGHT];
Will expand to (something like):
[self setWidth:([[UIDevice currentDevice] respondsToSelector:#selector(userInterfaceIdiom)] ? \
[[UIDevice currentDevice] userInterfaceIdiom] : \
UIUserInterfaceIdiomPhone) == UIUserInterfaceIdiomPad ? 768 : 320
height:([[UIDevice currentDevice] respondsToSelector:#selector(userInterfaceIdiom)] ? \
[[UIDevice currentDevice] userInterfaceIdiom] : \
UIUserInterfaceIdiomPhone) == UIUserInterfaceIdiomPad ? 1024 : 480];
Now I see several duplicate method calls in that call, and that cannot be a good thing, can it?
EDIT 2 To provide something that actually answers the question, you can use the macros from the accepted answer but also reduce the number of calls to UI_USER_INTERFACE_IDIOM().
Therefore whenever platform-specific code needs to be used, call UI_USER_INTERFACE_IDIOM() once at the start:
BOOL isIpad = UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad;
and then define the macros from the accepted answer to use that BOOL variable:
#define SCREENWIDTH (isIpad ? 768 : 320)
#define SCREENHEIGHT (isIpad ? 1024 : 480)
#define TWIDTH (isIpad ? 69 : 29)
#define THEIGHT (isIpad ? 69 : 29)
#define BX (isIpad ? 42 : 16)
#define BY (isIpad ? 0 : 34)
and then the example call I give expands to the much more reasonable:
[self setWidth:(isIpad ? 768 : 320)
height:(isIpad ? 1024 : 480)];
and then there is only one call to [[UIDevice currentDevice] respondsToSelector:] per calling-method, instead of one per called-parameter.