最近在折腾iPhone 端的界面。屏幕适配是一个痛点,我是xib党,一般设计给的稿子都是iPhone6的设计稿。所以适配 iPhonese iPhone6s是个麻烦的事情,要不就是拖出很多个 IBOutlet 在界面加载出来的时候一个个设置值。
比如:
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *beginButtonBottomConstraint;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *selectCalssfyButtonBottomConstraint;
@property (weak, nonatomic) IBOutlet UIButton *beginButton;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *textFieldTopConstraint;
在页面加载出来的时候:
///调整布局
_textFieldTopConstraint.constant = 149 * kViewWidthRate;
_beginButtonBottomConstraint.constant = 40 * kViewWidthRate;
_selectCalssfyButtonBottomConstraint.constant = 149 * kViewWidthRate;
这里 kViewWidthRate 是 屏幕相对iPhone6 的比例。太麻烦了,想想,如果一个个界面有很多约束,累死人不偿命的!
本文给出一个优雅的方案
#import <UIKit/UIKit.h>
IB_DESIGNABLE
@interface PBTLayoutConstraint : NSLayoutConstraint
@property (nonatomic, assign) IBInspectable BOOL widthAdaptive;
@property (nonatomic, assign) IBInspectable BOOL heightAdaptive;
@end
实现文件
#import "PBTLayoutConstraint.h"
//获取屏幕宽度
#define SCREEN_WIDTH MIN([UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)
//获取屏幕高度
#define SCREEN_HEIGHT MAX([UIScreen mainScreen].bounds.size.height, [UIScreen mainScreen].bounds.size.width)
#define k1px (1 / [UIScreen mainScreen].scale)
//判断当前设备是不是iphone5
#define IPHONE6_WIDTH 375
#define IPHONE6_HEIGHT 667
#define kViewWidthRate SCREEN_WIDTH/IPHONE6_WIDTH
#define kViewHEIGHTRate SCREEN_HEIGHT/IPHONE6_HEIGHT
@implementation PBTLayoutConstraint
- (void)setWidthAdaptive:(BOOL)widthAdaptive {
_widthAdaptive = widthAdaptive;
if(widthAdaptive) {
CGFloat _cons = self.constant;
_cons = _cons * kViewWidthRate;
self.constant = _cons;
}
}
- (void)setHeightAdaptive:(BOOL)heightAdaptive {
_heightAdaptive = heightAdaptive;
if(heightAdaptive){
CGFloat _cons = self.constant;
_cons = _cons * kViewHEIGHTRate;
self.constant = _cons;
}
}
@end
此处widthAdaptive 和 heightAdaptive 的意思是,根据本机型屏幕的 宽或者高相对于iPhone6的屏幕宽高比例设置 constant 的值。使用 IBInspectable 直接可以在 xib上操作
使用如下:
在界面上,根据需求,设置 widthAdaptive 或者 heightAdaptive 为 on 或者 off 即可!!
当然 xib中,约束的class要设置成 PBTLayoutConstraint
方案二
直接使用分类,好处是不用再xib处,修改class为PBTLayoutConstraint
干净的终极方案
代码如下:
IB_DESIGNABLE
@interface NSLayoutConstraint(AllSize)
@property (nonatomic, assign) IBInspectable BOOL adaptive;
@end
实现文件如下:
#import "PBTLayoutConstraint.h"
#import <objc/runtime.h>
NS_INLINE CGFloat _sizeRate(){
static CGFloat _rate = 0.0;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_rate = [UIScreen mainScreen].bounds.size.width / 375.0;
});
return _rate;
}
@implementation NSLayoutConstraint(AllSize)
- (void)setAdaptive:(BOOL)widthAdaptive {
if (widthAdaptive) {
CGFloat _cons = self.constant;
_cons = _cons * _sizeRate();
self.constant = _cons;
}
objc_setAssociatedObject(self, @selector(adaptive), @(widthAdaptive), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (BOOL)adaptive {
NSNumber *value = objc_getAssociatedObject(self, @selector(adaptive));
return [value boolValue];
}
@end
此时只要在xib中修改 adaptive 就可以了
因为其他屏幕相对iPhone6的宽高比例是固定的,所以值放出一个适配就好了。
各位看官,有其他适配方案的,欢迎交流