IOS 适配方案

在公司项目中,我用到了xib设置约束,Masonry,比例适配,三种适配方案的结合来达到项目中的页面适配,字体适配等。当然项目中对iPhone X的适配,我也有封装一个分类。

  • 我相信xib设置约束和Masonry,我就不用详细介绍了,我主要介绍一下比例适配和iPhone X的适配。

一、比例适配

  • 比例适配的原理在于:iphone 机型中除了iPhone X,其他机型都是宽高比都是基本相同,那么既然宽高比相同,我们就可以认为,当我们UI设计师给的图是任意一款苹果机的屏幕尺寸,咱们都能根据比例去适配其他手机屏幕。
第一步:创建一个.h头文件
20180716095949.png
第二步:在该文件里写下如下代码:
#ifndef Adaption_h
#define Adaption_h

#import 

#pragma 屏幕尺寸

#define kwidth [UIScreen mainScreen].bounds.size.width
#define kheight [UIScreen mainScreen].bounds.size.height

#pragma UI设计图尺寸

#define kBaseWidth 750
#define kBaseHeight 1334
//宏定义内联函数
#define Inline static inline
#pragma mark --设置比例
//实际屏幕宽度和设计图宽度的比例
Inline CGFloat AAdaptionWidth() {
    return kwidth/kBaseWidth;
}

//传入设计图尺寸标注,转化为实际屏幕尺寸标注
Inline CGFloat AAdaption(CGFloat x) {
    return x * AAdaptionWidth();
}
//传入设计图size,转化为实际屏幕的CGsize返回
Inline CGSize AAdaptionSize(CGFloat width, CGFloat height) {
    CGFloat newWidth = width * AAdaptionWidth();
    CGFloat newHeight = height * AAdaptionWidth();
    return CGSizeMake(newWidth, newHeight);
}
//传入设计图Point,转化成CGpoint返回
Inline CGPoint AAadaptionPoint(CGFloat x, CGFloat y) {
    CGFloat newX = x * AAdaptionWidth();
    CGFloat newY = y * AAdaptionWidth();
    return  CGPointMake(newX, newY);
}
//传入设计图Rect,返回已适配真实屏幕的CGrect
Inline CGRect AAdaptionRect(CGFloat x, CGFloat y, CGFloat width, CGFloat height){
    CGFloat newX = x*AAdaptionWidth();
    CGFloat newY = y*AAdaptionWidth();
    CGFloat newW = width*AAdaptionWidth();
    CGFloat newH = height*AAdaptionWidth();
    return CGRectMake(newX, newY, newW, newH);
}

Inline CGRect AAdaptionRectFromFrame(CGRect frame){
    CGFloat newX = frame.origin.x*AAdaptionWidth();
    CGFloat newY = frame.origin.y*AAdaptionWidth();
    CGFloat newW = frame.size.width*AAdaptionWidth();
    CGFloat newH = frame.size.height*AAdaptionWidth();
    return CGRectMake(newX, newY, newW, newH);
}



//字体适配:传出设计图字体大小
Inline UIFont * AAFont(CGFloat font){
    return [UIFont systemFontOfSize:font*AAdaptionWidth()];
}
//加粗字体适配
Inline UIFont * BoldFont(CGFloat font){
    return [UIFont boldSystemFontOfSize:font*AAdaptionWidth()];
}

#endif /* Adaption_h */
第三步:在项目中使用
  • 导入头文件
    #import "Adaption.h"

  • 代码调用与普通初始化类似

    UIView *redView = [[UIView alloc]initWithFrame:AAdaptionRect(100, 100, 100, 100)];
    redView.backgroundColor = [UIColor redColor];
    [self.view addSubview:redView];
    

你现在可以试一下各个屏幕上显示的效果,肯定是能适配的,除了iPhone X

  • 这个适配文件有一个缺点,只适配竖屏,横屏事得重新设置设计图设计图尺寸,或者用masonry适配。

iPhone X的适配:

  • 首先在配置文件里定义几个宏
//宏定义常用的导航栏,tabbar,状态栏高度
#define TabBarH ((kheight == 812) ? 83 : 49)
#define NavH ((kheight == 812) ? 88 : 64)//这个包含状态栏在内
#define StuBarH ((kheight == 812) ? 44 : 20)
  • 然后给UIViewController创建一个分类
  • UIViewController+ContentView.h内容
#import 
@interface UIViewController (ContentView)
@property (nonatomic, strong) UIView *contentView;
@end
  • UIViewController+ContentView.m内容

#import "UIViewController+ContentView.h"

#import 

static const void *ContentView = &ContentView;

@implementation UIViewController (ContentView)
//用runtime重写setter,getter方法,来给分类添加属性
- (void)setContentView:(UIView *)contentView {
    /*
     OBJC_ASSOCIATION_ASSIGN;            //assign策略
     OBJC_ASSOCIATION_COPY_NONATOMIC;    //copy策略
     OBJC_ASSOCIATION_RETAIN_NONATOMIC;  // retain策略
     
     OBJC_ASSOCIATION_RETAIN;
     OBJC_ASSOCIATION_COPY;
     */
    /*
     * id object 给哪个对象的属性赋值
     const void *key 属性对应的key
     id value  设置属性值为value
     objc_AssociationPolicy policy  使用的策略,是一个枚举值,和copy,retain,assign是一样的,手机开发一般都选择NONATOMIC
     objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);
     */
    objc_setAssociatedObject(self, ContentView, contentView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

/**
 contentView用来作为根视图代替self.view
 注意:本项目是用的系统的导航栏,假如用的自定义的导航栏,
 请在宏定义里改掉相应的导航栏高度和tabbar高度。
 有一个缺点:当你由于需要,隐藏了导航栏,这儿检测不到,因为初始化Vc的时候先走这个方法
 这个时候建议在相应vc中做坐标处理
 */
- (UIView *)contentView {
    //利用runtime实现动态添加属性
    UIView *view = objc_getAssociatedObject(self, ContentView);
    //因为当界面上只有tableview控件时,在iOS7以上,iOS11以下系统,坐标零点都是从导航栏开始
    //设置这个属性能够避免系统bug
    self.automaticallyAdjustsScrollViewInsets = NO;
    //判断vc是否为栈内第一个页面,来设置contenview的高度
    //这儿默认每个页面都有导航栏,如果是自定义导航栏,只需要在self.view上添加即可,不会与contentView冲突
    if (!view) {
            if (self.navigationController.viewControllers.count > 1 ||self.navigationController.viewControllers.count == 0) {
                view = [[UIView alloc]initWithFrame:CGRectMake(0, NavH, kwidth, kheight-NavH)];
            }else{
                view = [[UIView alloc]initWithFrame:CGRectMake(0, NavH, kwidth, kheight-NavH-TabBarH)];
            }
        view.backgroundColor = [UIColor clearColor];
        self.contentView = view;
        //让应用在ipad以滚动视图的方式正常显示,显示内容宽高和iphone5一样,这是为了苹果审核,要求iPad正常显示
        if (kheight == 480) {
            UIScrollView *scorollView = [[UIScrollView alloc]initWithFrame:self.view.bounds];
            scorollView.contentSize = CGSizeMake(kwidth, 568);
            view.frame = CGRectMake(0, 0, kwidth, 568);
            [self.view addSubview:scorollView];
            [scorollView addSubview:view];
        }else{
            [self.view addSubview:view];
        }
    }
    return view;
}
  • 外部调用:
UIView *redView = [[UIView alloc]initWithFrame:AAdaptionRect(100, 100, 100, 100)];
redView.backgroundColor = [UIColor redColor];
[self.contentView addSubview:redView];

你可能感兴趣的:(IOS 适配方案)